From fbc8b984f22cef707669592d84ebee1603d37cb7 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Thu, 13 Oct 2016 19:13:59 +0200 Subject: [PATCH 01/54] Implement support for host side multi-window management --- android/app_manager/Android.mk | 2 + android/hwcomposer/hwcomposer.cpp | 84 +++- .../host/libs/libOpenglRender/CMakeLists.txt | 3 +- .../host/libs/libOpenglRender/FrameBuffer.cpp | 293 +++--------- .../host/libs/libOpenglRender/FrameBuffer.h | 82 +--- .../libs/libOpenglRender/LayerManager.cpp | 92 ++++ .../host/libs/libOpenglRender/LayerManager.h | 63 +++ .../libs/libOpenglRender/NativeSubWindow.h | 18 +- .../NativeSubWindow_delegate.cpp | 22 +- .../{render_api.cpp => RenderApi.cpp} | 90 +--- .../libs/libOpenglRender/RenderControl.cpp | 70 ++- .../libs/libOpenglRender/RenderWindow.cpp | 73 --- .../host/libs/libOpenglRender/RenderWindow.h | 5 - .../renderControl_dec/renderControl.attrib | 3 + .../libs/renderControl_dec/renderControl.in | 8 + .../renderControl_dec/renderControl.types | 2 + src/anbox/cmds/run.cpp | 2 +- src/anbox/graphics/gl_renderer_server.cpp | 6 +- .../boot_properties_message_processor.cpp | 2 +- src/anbox/ubuntu/window.cpp | 443 +----------------- src/anbox/ubuntu/window.h | 13 +- src/anbox/ubuntu/window_creator.cpp | 32 +- src/anbox/ubuntu/window_creator.h | 3 + 23 files changed, 428 insertions(+), 983 deletions(-) create mode 100644 external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp create mode 100644 external/android-emugl/host/libs/libOpenglRender/LayerManager.h rename external/android-emugl/host/libs/libOpenglRender/{render_api.cpp => RenderApi.cpp} (76%) diff --git a/android/app_manager/Android.mk b/android/app_manager/Android.mk index bd37d10..8b1a3b8 100644 --- a/android/app_manager/Android.mk +++ b/android/app_manager/Android.mk @@ -6,6 +6,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := AnboxAppManager LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true +# We kick out several core packages here which would +# otherwise put up the base UI we don't want. LOCAL_OVERRIDES_PACKAGES := \ Home \ Launcher2 \ diff --git a/android/hwcomposer/hwcomposer.cpp b/android/hwcomposer/hwcomposer.cpp index d501029..38d8c4a 100644 --- a/android/hwcomposer/hwcomposer.cpp +++ b/android/hwcomposer/hwcomposer.cpp @@ -18,6 +18,11 @@ #include #include +#include +#include +#include +#include + #define LOG_NDEBUG 0 #include @@ -67,8 +72,8 @@ struct HwcContext { }; static void dump_layer(hwc_layer_1_t const* l) { - ALOGI("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", - l->compositionType, l->flags, l->handle, l->transform, l->blending, + ALOGI("\tname='%s', type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->name, l->compositionType, l->flags, l->handle, l->transform, l->blending, l->sourceCrop.left, l->sourceCrop.top, l->sourceCrop.right, @@ -185,11 +190,22 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, return -EINVAL; } - ALOGI("Posting buffer %p\n", cb->hostHandle); - rcEnc->rcFBPost(rcEnc, cb->hostHandle); + rcEnc->rcPostLayer(rcEnc, + layer->name, + cb->hostHandle, + layer->sourceCrop.left, + layer->sourceCrop.top, + layer->sourceCrop.right, + layer->sourceCrop.bottom, + layer->displayFrame.left, + layer->displayFrame.top, + layer->displayFrame.right, + layer->displayFrame.bottom); hostCon->flush(); } + rcEnc->rcPostAllLayersDone(rcEnc); + check_sync_fds(numDisplays, displays); return 0; @@ -226,8 +242,64 @@ static int hwc_device_close(hw_device_t* dev) { return 0; } +static int hwc_get_display_configs(hwc_composer_device_1* dev, int disp, + uint32_t* configs, size_t* numConfigs) { + ALOGI("%s", __PRETTY_FUNCTION__); + + if (disp != 0) { + return -EINVAL; + } + + if (*numConfigs > 0) { + // Config[0] will be passed in to getDisplayAttributes as the disp + // parameter. The ARC display supports only 1 configuration. + configs[0] = 0; + *numConfigs = 1; + } + return 0; +} + +static int hwc_get_display_attributes(hwc_composer_device_1* dev, + int disp, uint32_t config, + const uint32_t* attributes, + int32_t* values) { + ALOGI("%s", __PRETTY_FUNCTION__); + + if (disp != 0 || config != 0) { + return -EINVAL; + } + + DEFINE_AND_VALIDATE_HOST_CONNECTION(); + + while (*attributes != HWC_DISPLAY_NO_ATTRIBUTE) { + switch (*attributes) { + case HWC_DISPLAY_VSYNC_PERIOD: + *values = rcEnc->rcGetDisplayVsyncPeriod(rcEnc, disp); + break; + case HWC_DISPLAY_WIDTH: + *values = rcEnc->rcGetDisplayWidth(rcEnc, disp); + break; + case HWC_DISPLAY_HEIGHT: + *values = rcEnc->rcGetDisplayHeight(rcEnc, disp); + break; + case HWC_DISPLAY_DPI_X: + *values = 1000 * rcEnc->rcGetDisplayDpiX(rcEnc, disp); + break; + case HWC_DISPLAY_DPI_Y: + *values = 1000 * rcEnc->rcGetDisplayDpiY(rcEnc, disp); + break; + default: + ALOGE("Unknown attribute value 0x%02x", *attributes); + } + ++attributes; + ++values; + } + return 0; +} + static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { ALOGI("%s", __PRETTY_FUNCTION__); + if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) return -EINVAL; @@ -241,9 +313,9 @@ static int hwc_device_open(const hw_module_t* module, const char* name, hw_devic dev->device.eventControl = hwc_event_control; dev->device.blank = hwc_blank; dev->device.query = hwc_query; + dev->device.getDisplayConfigs = hwc_get_display_configs; + dev->device.getDisplayAttributes = hwc_get_display_attributes; dev->device.registerProcs = hwc_register_procs; - // FIXME: eventually implement to dump specific information - dev->device.dump = nullptr; *device = &dev->device.common; diff --git a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt b/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt index 7a25973..bbf5b9a 100644 --- a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt +++ b/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES ColorBuffer.cpp FbConfig.cpp FrameBuffer.cpp + LayerManager.cpp NativeSubWindow_delegate.cpp ReadBuffer.cpp RenderContext.cpp @@ -9,7 +10,7 @@ set(SOURCES RenderServer.cpp RenderThread.cpp RenderThreadInfo.cpp - render_api.cpp + RenderApi.cpp RenderWindow.cpp SocketStream.cpp TcpStream.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp index bff43b3..b81e68e 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -154,9 +154,6 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy) void FrameBuffer::finalize(){ m_colorbuffers.clear(); - if (m_useSubWindow) { - removeSubWindow(); - } m_windows.clear(); m_contexts.clear(); s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL); @@ -431,32 +428,19 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int } FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow) : - m_framebufferWidth(p_width), - m_framebufferHeight(p_height), - m_windowWidth(p_width), - m_windowHeight(p_height), m_useSubWindow(useSubWindow), m_configs(NULL), m_eglDisplay(EGL_NO_DISPLAY), m_colorBufferHelper(new ColorBufferHelper(this)), - m_eglSurface(EGL_NO_SURFACE), m_eglContext(EGL_NO_CONTEXT), m_pbufContext(EGL_NO_CONTEXT), m_prevContext(EGL_NO_CONTEXT), m_prevReadSurf(EGL_NO_SURFACE), m_prevDrawSurf(EGL_NO_SURFACE), - m_subWin((EGLNativeWindowType)0), m_textureDraw(NULL), m_lastPostedColorBuffer(0), - m_zRot(0.0f), - m_px(0), - m_py(0), - m_eglContextInitialized(false), m_statsNumFrames(0), m_statsStartTime(0LL), - m_onPost(NULL), - m_onPostContext(NULL), - m_fbImage(NULL), m_glVendor(NULL), m_glRenderer(NULL), m_glVersion(NULL) @@ -468,147 +452,68 @@ FrameBuffer::~FrameBuffer() { delete m_textureDraw; delete m_configs; delete m_colorBufferHelper; - free(m_fbImage); } -void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext) -{ - emugl::Mutex::AutoLock mutex(m_lock); - m_onPost = onPost; - m_onPostContext = onPostContext; - if (m_onPost && !m_fbImage) { - m_fbImage = (unsigned char*)malloc(4 * m_framebufferWidth * m_framebufferHeight); - if (!m_fbImage) { - ERR("out of memory, cancelling OnPost callback"); - m_onPost = NULL; - m_onPostContext = NULL; - return; - } +struct FrameBufferWindow { + EGLNativeWindowType native_window = 0; + EGLSurface surface = EGL_NO_SURFACE; +}; + +FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height) { + m_lock.lock(); + + auto native_window = createSubWindow(0, x, y, width, height); + if (!native_window) { + m_lock.unlock(); + return nullptr; } -} -static void subWindowRepaint(void* param) { - auto fb = static_cast(param); - fb->repost(); -} + auto window = new FrameBufferWindow; + window->native_window = native_window; -bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window, - int wx, - int wy, - int ww, - int wh, - int fbw, - int fbh, - float dpr, - float zRot) { - bool success = false; - - if (!m_useSubWindow) { - ERR("%s: Cannot create native sub-window in this configuration\n", - __FUNCTION__); - return false; + window->surface = s_egl.eglCreateWindowSurface( + m_eglDisplay, m_eglConfig, window->native_window, nullptr); + if (window->surface == EGL_NO_SURFACE) { + destroyWindow(window); + m_lock.unlock(); + return nullptr; } + if (!bindWindow_locked(window)) { + destroyWindow(window); + m_lock.unlock(); + return nullptr; + } + + s_gles2.glViewport(0, 0, width, height); + s_gles2.glClear(GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + s_egl.eglSwapBuffers(m_eglDisplay, window->surface); + + unbind_locked(); + + m_lock.unlock(); + + return window; +} + +void FrameBuffer::destroyWindow(FrameBufferWindow *window) { + if (!window) + return; + m_lock.lock(); - // If the subwindow doesn't exist, create it with the appropriate dimensions - if (!m_subWin) { + s_egl.eglMakeCurrent(m_eglDisplay, nullptr, nullptr, nullptr); - // Create native subwindow for FB display output - m_x = wx; - m_y = wy; - m_windowWidth = ww; - m_windowHeight = wh; + if (window->surface != EGL_NO_SURFACE) + s_egl.eglDestroySurface(m_eglDisplay, window->surface); - m_subWin = createSubWindow(p_window, m_x, m_y, - m_windowWidth, m_windowHeight, subWindowRepaint, this); - if (m_subWin) { - m_nativeWindow = p_window; + destroySubWindow(window->native_window); - // 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); - m_subWin = (EGLNativeWindowType)0; - } else { - m_px = 0; - m_py = 0; - - success = true; - } - } - } - - // At this point, if the subwindow doesn't exist, it is because it either couldn't be created - // in the first place or the EGLSurface couldn't be created. - if (m_subWin && bindSubwin_locked()) { - - // Only attempt to update window geometry if anything has actually changed. - if (!(m_x == wx && - m_y == wy && - m_windowWidth == ww && - m_windowHeight == wh)) { - - m_x = wx; - m_y = wy; - m_windowWidth = ww; - m_windowHeight = wh; - - success = ::moveSubWindow(m_nativeWindow, m_subWin, - m_x, m_y, m_windowWidth, m_windowHeight); - - // Otherwise, ensure that at least viewport parameters are properly updated. - } else { - success = true; - } - - if (success) { - // Subwin creation or movement was successful, - // update viewport and z rotation and draw - // the last posted color buffer. - s_gles2.glViewport(0, 0, fbw * dpr, fbh * dpr); - m_dpr = dpr; - m_zRot = zRot; - if (m_lastPostedColorBuffer) { - post(m_lastPostedColorBuffer, false); - } else { - s_gles2.glClear(GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT | - GL_STENCIL_BUFFER_BIT); - s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface); - } - } - unbind_locked(); - } + delete window; m_lock.unlock(); - return success; -} - -bool FrameBuffer::removeSubWindow() { - if (!m_useSubWindow) { - ERR("%s: Cannot remove native sub-window in this configuration\n", - __FUNCTION__); - return false; - } - bool removed = false; - m_lock.lock(); - if (m_subWin) { - s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL); - s_egl.eglDestroySurface(m_eglDisplay, m_eglSurface); - destroySubWindow(m_subWin); - - m_eglSurface = EGL_NO_SURFACE; - m_subWin = (EGLNativeWindowType)0; - removed = true; - } - m_lock.unlock(); - return removed; } HandleType FrameBuffer::genHandle() @@ -1021,25 +926,18 @@ bool FrameBuffer::bind_locked() return true; } -bool FrameBuffer::bindSubwin_locked() +bool FrameBuffer::bindWindow_locked(FrameBufferWindow *window) { EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); - if (!s_egl.eglMakeCurrent(m_eglDisplay, m_eglSurface, - m_eglSurface, m_eglContext)) { + if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface, + window->surface, m_eglContext)) { ERR("eglMakeCurrent failed\n"); 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; @@ -1059,64 +957,37 @@ bool FrameBuffer::unbind_locked() return true; } -bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) +bool FrameBuffer::post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock) { - if (needLock) { + if (!window) + return false; + + printf("%s window %p\n", __func__, window); + + if (needLock) m_lock.lock(); - } - bool ret = false; + + bool ret; ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); - if (c == m_colorbuffers.end()) { + if (c == m_colorbuffers.end()) goto EXIT; - } m_lastPostedColorBuffer = p_colorbuffer; - if (m_subWin) { - // bind the subwindow eglSurface - if (!bindSubwin_locked()) { - ERR("FrameBuffer::post(): eglMakeCurrent failed\n"); - goto EXIT; - } + if (!bindWindow_locked(window)) + goto EXIT; - // get the viewport - GLint vp[4]; - s_gles2.glGetIntegerv(GL_VIEWPORT, vp); + s_gles2.glClear(GL_COLOR_BUFFER_BIT); - // divide by device pixel ratio because windowing coordinates ignore DPR, - // but the framebuffer includes DPR - vp[2] = vp[2] / m_dpr; - vp[3] = vp[3] / m_dpr; - - // 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 - float fx = 2.f * (vp[2] - m_windowWidth) / (float) vp[2]; - float fy = 2.f * (vp[3] - m_windowHeight) / (float) vp[3]; - - // finally, compute translation values - float dx = m_px * fx; - float dy = m_py * fy; - - // - // render the color buffer to the window - // - if (m_zRot != 0.0f) { - s_gles2.glClear(GL_COLOR_BUFFER_BIT); - } - ret = (*c).second.cb->post(m_zRot, dx, dy); - if (ret) { - s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface); - } - - // restore previous binding - unbind_locked(); - } else { - // If there is no sub-window, don't display anything, the client will - // rely on m_onPost to get the pixels instead. - ret = true; + ret = (*c).second.cb->post(0.0f, 0, 0); + if (ret) { + s_egl.eglSwapBuffers(m_eglDisplay, window->surface); } + // restore previous binding + unbind_locked(); + // // output FPS statistics // @@ -1131,30 +1002,12 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) } } - // - // Send framebuffer (without FPS overlay) to callback - // - if (m_onPost) { - (*c).second.cb->readback(m_fbImage); - m_onPost(m_onPostContext, - m_framebufferWidth, - m_framebufferHeight, - -1, - GL_RGBA, - GL_UNSIGNED_BYTE, - m_fbImage); - } - EXIT: + if (!ret) + printf("post: FAILED\n"); + if (needLock) { m_lock.unlock(); } return ret; } - -bool FrameBuffer::repost() { - if (m_lastPostedColorBuffer) { - return post(m_lastPostedColorBuffer); - } - return false; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h index b581a44..a3d419d 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h @@ -58,6 +58,8 @@ struct FrameBufferCaps { EGLint eglMinor; }; +struct FrameBufferWindow; + // The FrameBuffer class holds the global state of the emulation library on // top of the underlying EGL/GLES implementation. It should probably be // named "Display" instead of "FrameBuffer". @@ -76,32 +78,8 @@ public: // Returns true on success, false otherwise. static bool initialize(EGLNativeDisplayType nativeDisplay, int width, int height, bool useSubWindow); - // Setup a sub-window to display the content of the emulated GPU - // on-top of an existing UI window. |p_window| is the platform-specific - // parent window handle. |wx|, |wy|, |ww| and |wh| are the - // dimensions in pixels of the sub-window, relative to the parent window's - // coordinate. |fbw| and |fbh| are the dimensions used to initialize - // the framebuffer, which may be different from the dimensions of the - // sub-window (in which case scaling will be applied automatically). - // |dpr| is the device pixel ratio of the monitor, which is needed for - // proper panning on high-density displays (like retina) - // |zRot| is a rotation angle in degrees, (clockwise in the Y-upwards GL - // coordinate space). - // - // If a sub-window already exists, this function updates the subwindow - // and framebuffer properties to match the given values. - // - // Return true on success, false otherwise. - // - // NOTE: This can return false for software-only EGL engines like OSMesa. - bool setupSubWindow(FBNativeWindowType p_window, - int wx, int wy, - int ww, int wh, - int fbw, int fbh, float dpr, float zRot); - - // Remove the sub-window created by setupSubWindow(), if any. - // Return true on success, false otherwise. - bool removeSubWindow(); + FrameBufferWindow* createWindow(int x, int y, int width, int height); + void destroyWindow(FrameBufferWindow *window); // Finalize the instance. void finalize(); @@ -113,12 +91,6 @@ public: // Return the capabilities of the underlying display. const FrameBufferCaps &getCaps() const { return m_caps; } - // Return the emulated GPU display width in pixels. - int getWidth() const { return m_framebufferWidth; } - - // Return the emulated GPU display height in pixels. - int getHeight() const { return m_framebufferHeight; } - // Return the list of configs available from this display. const FbConfigList* getConfigs() const { return m_configs; } @@ -259,36 +231,11 @@ public: // |needLock| is used to indicate whether the operation requires // acquiring/releasing the FrameBuffer instance's lock. It should be // false only when called internally. - bool post(HandleType p_colorbuffer, bool needLock = true); - - // Re-post the last ColorBuffer that was displayed through post(). - // This is useful if you detect that the sub-window content needs to - // be re-displayed for any reason. - bool repost(); + bool post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock = true); // Return the host EGLDisplay used by this instance. EGLDisplay getDisplay() const { return m_eglDisplay; } - // Change the rotation of the displayed GPU sub-window. - void setDisplayRotation(float zRot) { - m_zRot = zRot; - repost(); - } - - // Changes what coordinate of this framebuffer will be displayed at the - // corner of the GPU sub-window. Specifically, |px| and |py| = 0 means - // align the bottom-left of the framebuffer with the bottom-left of the - // sub-window, and |px| and |py| = 1 means align the top right of the - // framebuffer with the top right of the sub-window. Intermediate values - // interpolate between these states. - void setDisplayTranslation(float px, float py) { - - // Sanity check the values to ensure they are between 0 and 1 - m_px = px > 1 ? 1 : (px < 0 ? 0 : px); - m_py = py > 1 ? 1 : (py < 0 ? 0 : py); - repost(); - } - // Return a TextureDraw instance that can be used with this surfaces // and windows created by this instance. TextureDraw* getTextureDraw() const { return m_textureDraw; } @@ -305,18 +252,11 @@ private: ~FrameBuffer(); HandleType genHandle(); - bool bindSubwin_locked(); + bool bindWindow_locked(FrameBufferWindow *window); private: static FrameBuffer *s_theFrameBuffer; static HandleType s_nextHandle; - int m_x; - int m_y; - int m_framebufferWidth; - int m_framebufferHeight; - int m_windowWidth; - int m_windowHeight; - float m_dpr; bool m_useSubWindow; emugl::Mutex m_lock; FbConfigList* m_configs; @@ -328,7 +268,6 @@ private: ColorBufferMap m_colorbuffers; ColorBuffer::Helper* m_colorBufferHelper; - EGLSurface m_eglSurface; EGLContext m_eglContext; EGLSurface m_pbufSurface; EGLContext m_pbufContext; @@ -336,23 +275,14 @@ private: EGLContext m_prevContext; EGLSurface m_prevReadSurf; EGLSurface m_prevDrawSurf; - EGLNativeWindowType m_subWin; TextureDraw* m_textureDraw; EGLConfig m_eglConfig; HandleType m_lastPostedColorBuffer; - float m_zRot; - float m_px; - float m_py; - bool m_eglContextInitialized; int m_statsNumFrames; long long m_statsStartTime; bool m_fpsStats; - OnPostFn m_onPost; - void* m_onPostContext; - unsigned char* m_fbImage; - const char* m_glVendor; const char* m_glRenderer; const char* m_glVersion; diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp new file mode 100644 index 0000000..a90a455 --- /dev/null +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "LayerManager.h" + +#include + +namespace { +std::string get_package_name(const std::string &name) { + return name; +} + +bool is_layer_blacklisted(const std::string &name) { + static std::vector blacklist = { + "BootAnimation", + "StatusBar", + "Sprite", + "KeyguardScrim", + "com.android.launcher/com.android.launcher2.Launcher", + "com.android.settings/com.android.settings.FallbackHome", + "com.android.systemui.ImageWallpaper", + "InputMethod", + }; + return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end(); +} +} + +std::shared_ptr LayerManager::get() { + static auto self = std::shared_ptr{new LayerManager}; + return self; +} + +LayerManager::LayerManager() { +} + +LayerManager::~LayerManager() { +} + +void LayerManager::post_layer(const LayerInfo &layer) { + if (is_layer_blacklisted(layer.name)) { + printf("Ignoring blacklisted layer '%s'\n", layer.name.c_str()); + return; + } + + FrameBufferWindow *window = nullptr; + auto l = layers_.find(layer.name); + if (l != layers_.end()) { + printf("Using existing layer '%s'\n", layer.name.c_str()); + window = l->second.window; + l->second.updated = true; + } + else { + printf("New layer '%s' {%d,%d,%d,%d}\n", layer.name.c_str()); + window = FrameBuffer::getFB()->createWindow( + layer.display_frame.left, + layer.display_frame.top, + layer.display_frame.right, + layer.display_frame.bottom); + if (!window) { + printf("Failed to create window for layer '%s'\n", layer.name.c_str()); + return; + } + layers_.insert({ layer.name, Layer{window, true}}); + } + + printf("%s: window %p buffer %d\n", __func__, window, layer.buffer_handle); + + FrameBuffer::getFB()->post(window, layer.buffer_handle); +} + +void LayerManager::finish_cycle() { + for (auto iter = layers_.begin(); iter != layers_.end(); ++iter) { + if (!iter->second.updated) { + FrameBuffer::getFB()->destroyWindow(iter->second.window); + layers_.erase(iter); + } + } +} diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.h b/external/android-emugl/host/libs/libOpenglRender/LayerManager.h new file mode 100644 index 0000000..52b9100 --- /dev/null +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef LAYER_MANAGER_H_ +#define LAYER_MANAGER_H_ + +#include + +#include +#include +#include + +#include "FrameBuffer.h" + +struct LayerRect { + int top; + int left; + int right; + int bottom; +}; + +struct LayerInfo { + std::string name; + LayerRect source_crop; + LayerRect display_frame; + HandleType buffer_handle; +}; + +class LayerManager { +public: + static std::shared_ptr get(); + + ~LayerManager(); + + void post_layer(const LayerInfo &layer); + void finish_cycle(); + +private: + LayerManager(); + + struct Layer { + FrameBufferWindow *window; + bool updated; + }; + + std::map layers_; +}; + +#endif diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h index 49af52b..21a379c 100644 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h +++ b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h @@ -35,8 +35,6 @@ public: void registerSubWindowHandler(const std::shared_ptr &handler); -typedef void (*SubWindowRepaintCallback)(void*); - // Create a new sub-window that will be used to display the content of the // emulated GPU on top of the regular UI window. // |p_window| is the platform-specific handle to the main UI window. @@ -55,25 +53,11 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, int x, int y, int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param); + int height); // Destroy a sub-window previously created through createSubWindow() above. void destroySubWindow(EGLNativeWindowType win); -// Moves a sub-window previously created through createSubWindow() above. -// |p_parent_window| is the platform-specific handle to the main UI window. -// |p_sub_window| is the platform-specific handle to the EGL subwindow. -// |x|,|y|,|width|,|height| are the new location and dimensions of the -// subwindow. -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height); - #ifdef __cplusplus } #endif diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp index 8984d2f..1eab521 100644 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp @@ -35,12 +35,8 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, int x, int y, int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param) { + int height) { (void) p_window; - (void) repaint_callback; - (void) repaint_callback_param; if (!current_handler) return (EGLNativeWindowType) 0; @@ -54,19 +50,3 @@ void destroySubWindow(EGLNativeWindowType win) { return current_handler->destroy_window(win); } - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - (void) p_parent_window; - (void) p_sub_window; - (void) x; - (void) y; - (void) width; - (void) height; - - return true; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/render_api.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp similarity index 76% rename from external/android-emugl/host/libs/libOpenglRender/render_api.cpp rename to external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp index 228119f..d8b0317 100644 --- a/external/android-emugl/host/libs/libOpenglRender/render_api.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp @@ -21,11 +21,7 @@ #include "TimeUtils.h" #include "TcpStream.h" -#ifdef _WIN32 -#include "Win32PipeStream.h" -#else #include "UnixStream.h" -#endif #include "DispatchTables.h" @@ -142,15 +138,6 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( return true; } -RENDER_APICALL void RENDER_APIENTRY setPostCallback( - OnPostFn onPost, void* onPostContext) { - if (s_renderWindow) { - s_renderWindow->setPostCallback(onPost, onPostContext); - } else { - ERR("Calling setPostCallback() before creating render window!"); - } -} - RENDER_APICALL void RENDER_APIENTRY getHardwareStrings( const char** vendor, const char** renderer, @@ -228,53 +215,7 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void) return false; } -RENDER_APICALL void RENDER_APIENTRY setOpenGLDisplayRotation(float zRot) -{ - RenderWindow* window = s_renderWindow; - - if (window) { - window->setRotation(zRot); - return; - } - // XXX: should be implemented by sending the renderer process - // a request - ERR("%s not implemented for separate renderer process !!!\n", - __FUNCTION__); -} - -RENDER_APICALL void RENDER_APIENTRY setOpenGLDisplayTranslation(float px, float py) -{ - RenderWindow* window = s_renderWindow; - - if (window) { - window->setTranslation(px, py); - return; - } - // XXX: should be implemented by sending the renderer process - // a request - ERR("%s not implemented for separate renderer process !!!\n", - __FUNCTION__); -} - -RENDER_APICALL void RENDER_APIENTRY repaintOpenGLDisplay(void) -{ - RenderWindow* window = s_renderWindow; - - if (window) { - window->repaint(); - return; - } - // XXX: should be implemented by sending the renderer process - // a request - ERR("%s not implemented for separate renderer process !!!\n", - __FUNCTION__); -} - - -/* NOTE: For now, always use TCP mode by default, until the emulator - * has been updated to support Unix and Win32 pipes - */ -#define DEFAULT_STREAM_MODE RENDER_API_STREAM_MODE_TCP +#define DEFAULT_STREAM_MODE RENDER_API_STREAM_MODE_UNIX int gRendererStreamMode = DEFAULT_STREAM_MODE; @@ -285,11 +226,7 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) { stream = new TcpStream(p_stream_buffer_size); } else { -#ifdef _WIN32 - stream = new Win32PipeStream(p_stream_buffer_size); -#else /* !_WIN32 */ stream = new UnixStream(p_stream_buffer_size); -#endif } if (!stream) { @@ -312,28 +249,3 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) return stream; } - -RENDER_APICALL int RENDER_APIENTRY setStreamMode(int mode) -{ - switch (mode) { - case RENDER_API_STREAM_MODE_DEFAULT: - mode = DEFAULT_STREAM_MODE; - break; - - case RENDER_API_STREAM_MODE_TCP: - break; - -#ifndef _WIN32 - case RENDER_API_STREAM_MODE_UNIX: - break; -#else /* _WIN32 */ - case RENDER_API_STREAM_MODE_PIPE: - break; -#endif /* _WIN32 */ - default: - // Invalid stream mode - return false; - } - gRendererStreamMode = mode; - return true; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp index 44fd113..c36769a 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp @@ -20,9 +20,13 @@ #include "FrameBuffer.h" #include "RenderThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h" +#include "LayerManager.h" #include "OpenGLESDispatch/EGLDispatch.h" +#include +#include + static const GLint rendererVersion = 1; static GLint rcGetRendererVersion() @@ -156,10 +160,12 @@ static EGLint rcGetFBParam(EGLint param) switch(param) { case FB_WIDTH: - ret = fb->getWidth(); + // FIXME DISPLAY MANAGER!! + ret = 1920; break; case FB_HEIGHT: - ret = fb->getHeight(); + // FIXME DISPLAY MANAGER!! + ret = 1080; break; case FB_XDPI: ret = 72; // XXX: should be implemented @@ -306,7 +312,7 @@ static void rcFBPost(uint32_t colorBuffer) return; } - fb->post(colorBuffer); + fb->post(nullptr, colorBuffer); } static void rcFBSetSwapInterval(EGLint interval) @@ -392,6 +398,56 @@ static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) { ChecksumCalculatorThreadInfo::setVersion(protocol); } +int rcGetNumDisplays() { + return 1; +} + +int rcGetDisplayWidth(uint32_t display_id) { + printf("%s: display_id=%d\n", __func__, display_id); + return 1920; +} + +int rcGetDisplayHeight(uint32_t display_id) { + printf("%s: display_id=%d\n", __func__, display_id); + return 1080; +} + +int rcGetDisplayDpiX(uint32_t display_id) { + printf("%s: display_id=%d\n", __func__, display_id); + return 120; +} + +int rcGetDisplayDpiY(uint32_t display_id) { + printf("%s: display_id=%d\n", __func__, display_id); + return 120; +} + +int rcGetDisplayVsyncPeriod(uint32_t display_id) { + printf("%s: display_id=%d\n", __func__, display_id); + return 1; +} + +void rcPostLayer(const char *name, uint32_t color_buffer, + int32_t sourceCropLeft, int32_t sourceCropTop, + int32_t sourceCropRight, int32_t sourceCropBottom, + int32_t displayFrameLeft, int32_t displayFrameTop, + int32_t displayFrameRight, int32_t displayFrameBottom) { + + printf("%s: name='%s' color_buffer=%d {%d,%d,%d,%d}, {%d,%d,%d,%d}\n", + __func__, name, color_buffer, + sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom, + displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom); + + LayerRect source_crop{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}; + LayerRect display_frame{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom}; + LayerManager::get()->post_layer({name, source_crop, display_frame, color_buffer}); +} + +void rcPostAllLayersDone() +{ + LayerManager::get()->finish_cycle(); +} + void initRenderControlContext(renderControl_decoder_context_t *dec) { dec->rcGetRendererVersion = rcGetRendererVersion; @@ -423,4 +479,12 @@ void initRenderControlContext(renderControl_decoder_context_t *dec) dec->rcCreateClientImage = rcCreateClientImage; dec->rcDestroyClientImage = rcDestroyClientImage; dec->rcSelectChecksumCalculator = rcSelectChecksumCalculator; + dec->rcGetNumDisplays = rcGetNumDisplays; + dec->rcGetDisplayWidth = rcGetDisplayWidth; + dec->rcGetDisplayHeight = rcGetDisplayHeight; + dec->rcGetDisplayDpiX = rcGetDisplayDpiX; + dec->rcGetDisplayDpiY = rcGetDisplayDpiY; + dec->rcGetDisplayVsyncPeriod = rcGetDisplayVsyncPeriod; + dec->rcPostLayer = rcPostLayer; + dec->rcPostAllLayersDone = rcPostAllLayersDone; } diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp index ced43de..31f50bd 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp @@ -138,69 +138,6 @@ struct RenderWindowMessage { result = true; break; - case CMD_SET_POST_CALLBACK: - D("CMD_SET_POST_CALLBACK\n"); - fb = FrameBuffer::getFB(); - fb->setPostCallback(msg.set_post_callback.on_post, - msg.set_post_callback.on_post_context); - result = true; - break; - - case CMD_SETUP_SUBWINDOW: - D("CMD_SETUP_SUBWINDOW: parent=%p wx=%d wy=%d ww=%d wh=%d fbw=%d fbh=%d dpr=%f rotation=%f\n", - (void*)msg.subwindow.parent, - msg.subwindow.wx, - msg.subwindow.wy, - msg.subwindow.ww, - msg.subwindow.wh, - msg.subwindow.fbw, - msg.subwindow.fbh, - msg.subwindow.dpr, - msg.subwindow.rotation); - result = FrameBuffer::getFB()->setupSubWindow( - msg.subwindow.parent, - msg.subwindow.wx, - msg.subwindow.wy, - msg.subwindow.ww, - msg.subwindow.wh, - msg.subwindow.fbw, - msg.subwindow.fbh, - msg.subwindow.dpr, - msg.subwindow.rotation); - break; - - case CMD_REMOVE_SUBWINDOW: - D("CMD_REMOVE_SUBWINDOW\n"); - result = FrameBuffer::getFB()->removeSubWindow(); - break; - - case CMD_SET_ROTATION: - D("CMD_SET_ROTATION rotation=%f\n", msg.rotation); - fb = FrameBuffer::getFB(); - if (fb) { - fb->setDisplayRotation(msg.rotation); - result = true; - } - break; - - case CMD_SET_TRANSLATION: - D("CMD_SET_TRANSLATION translation=%f,%f\n", msg.trans.px, msg.trans.py); - fb = FrameBuffer::getFB(); - if (fb) { - fb->setDisplayTranslation(msg.trans.px, msg.trans.py); - result = true; - } - break; - - case CMD_REPAINT: - D("CMD_REPAINT\n"); - fb = FrameBuffer::getFB(); - if (fb) { - fb->repost(); - result = true; - } - break; - default: ; } @@ -370,16 +307,6 @@ bool RenderWindow::getHardwareStrings(const char** vendor, return true; } -void RenderWindow::setPostCallback(OnPostFn onPost, void* onPostContext) { - D("Entering\n"); - RenderWindowMessage msg; - msg.cmd = CMD_SET_POST_CALLBACK; - msg.set_post_callback.on_post = onPost; - msg.set_post_callback.on_post_context = onPostContext; - (void) processMessage(msg); - D("Exiting\n"); -} - bool RenderWindow::setupSubWindow(FBNativeWindowType window, int wx, int wy, diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h index 1443688..6389475 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h +++ b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h @@ -75,11 +75,6 @@ public: const char** renderer, const char** version); - // Specify a function that will be called everytime a new frame is - // displayed. This is relatively slow but allows one to capture the - // output. - void setPostCallback(OnPostFn onPost, void* onPostContext); - // Start displaying the emulated framebuffer using a sub-window of a // parent |window| id. |wx|, |wy|, |ww| and |wh| are the position // and dimension of the sub-window, relative to its parent. diff --git a/external/android-emugl/host/libs/renderControl_dec/renderControl.attrib b/external/android-emugl/host/libs/renderControl_dec/renderControl.attrib index 0afa9d3..4a3bb18 100644 --- a/external/android-emugl/host/libs/renderControl_dec/renderControl.attrib +++ b/external/android-emugl/host/libs/renderControl_dec/renderControl.attrib @@ -42,3 +42,6 @@ rcUpdateColorBuffer rcCloseColorBuffer flag flushOnEncode + +rcPostLayer + len name (strlen(name) + 1) diff --git a/external/android-emugl/host/libs/renderControl_dec/renderControl.in b/external/android-emugl/host/libs/renderControl_dec/renderControl.in index 2cc4031..a632a0a 100644 --- a/external/android-emugl/host/libs/renderControl_dec/renderControl.in +++ b/external/android-emugl/host/libs/renderControl_dec/renderControl.in @@ -27,3 +27,11 @@ GL_ENTRY(int, rcOpenColorBuffer2, uint32_t colorbuffer) GL_ENTRY(uint32_t, rcCreateClientImage, uint32_t context, EGLenum target, GLuint buffer) GL_ENTRY(int, rcDestroyClientImage, uint32_t image) GL_ENTRY(void, rcSelectChecksumCalculator, uint32_t newProtocol, uint32_t reserved) +GL_ENTRY(int, rcGetNumDisplays) +GL_ENTRY(int, rcGetDisplayWidth, uint32_t displayId) +GL_ENTRY(int, rcGetDisplayHeight, uint32_t displayId) +GL_ENTRY(int, rcGetDisplayDpiX, uint32_t displayId) +GL_ENTRY(int, rcGetDisplayDpiY, uint32_t displayId) +GL_ENTRY(int, rcGetDisplayVsyncPeriod, uint32_t displayId) +GL_ENTRY(void, rcPostLayer, const char* name, uint32_t colorBuffer, int32_t sourceCropLeft, int32_t sourceCropTop, int32_t sourceCropRight, int32_t sourceCropBottom, int32_t displayFrameLeft, int32_t displayFrameTop, int32_t displayFrameRight, int32_t displayFrameBottom) +GL_ENTRY(void, rcPostAllLayersDone) diff --git a/external/android-emugl/host/libs/renderControl_dec/renderControl.types b/external/android-emugl/host/libs/renderControl_dec/renderControl.types index 2b38470..9bb0546 100644 --- a/external/android-emugl/host/libs/renderControl_dec/renderControl.types +++ b/external/android-emugl/host/libs/renderControl_dec/renderControl.types @@ -1,4 +1,5 @@ uint32_t 32 0x%08x +int32_t 32 0x%08x EGLint 32 0x%08x GLint 32 0x%08x GLuint 32 0x%08x @@ -9,3 +10,4 @@ EGLint* 32 0x%08x GLint* 32 0x%08x GLuint* 32 0x%08x void* 32 0x%08x +char* 32 0x%08x diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 7fffe26..674ac9f 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -140,7 +140,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) // { qemud_connector->socket_file(), "/dev/qemud" }, { qemu_pipe_connector->socket_file(), "/dev/qemu_pipe" }, { bridge_connector->socket_file(), "/dev/anbox_bridge" }, - { config::host_input_device_path(), "/dev/input" }, + { "/dev/input", "/dev/input" }, { "/dev/binder", "/dev/binder" }, { "/dev/ashmem", "/dev/ashmem" }, }; diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 50624f0..3b6d3af 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -45,13 +45,11 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &window_ if (!initLibrary()) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); - setStreamMode(RENDER_API_STREAM_MODE_UNIX); - registerSubWindowHandler(window_creator_); } GLRendererServer::~GLRendererServer() { - destroyOpenGLSubwindow(); + // destroyOpenGLSubwindow(); stopOpenGLRenderer(); } @@ -84,11 +82,13 @@ void GLRendererServer::start() { socket_path_ = server_addr; +#if 0 // Create the window we use for rendering the output we get from the // Android container. This will internally construct a Mir surface // and use the host EGL/GLES libraries for rendering. if (!showOpenGLSubwindow(0, 0, 0, width, height, width, height, 1.0f, 0)) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup GL based window")); +#endif } std::string GLRendererServer::socket_path() const { diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index d5b54c2..a1f9300 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -54,7 +54,7 @@ void BootPropertiesMessageProcessor::list_properties() { // TODO(morphis): Using HDPI here for now but should be adjusted to the device // we're running on. - utils::string_format("ro.sf.lcd_density=%d", static_cast(graphics::DensityType::high)), + utils::string_format("ro.sf.lcd_density=%d", static_cast(graphics::DensityType::medium)), // Disable on-screen virtual keys as we can use the hardware keyboard "qemu.hw.mainkeys=1", diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index 8a057bb..f024dee 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -16,338 +16,26 @@ */ #include "anbox/ubuntu/window.h" -#include "anbox/input/manager.h" -#include "anbox/input/device.h" #include "anbox/logger.h" #include #include -namespace { -class SlotFingerMapper { -public: - int find_or_create(SDL_FingerID id) { - auto iter = std::find(slots_.begin(), slots_.end(), id); - if (iter != slots_.end()) - return std::distance(slots_.begin(), iter); - - std::vector::size_type i; - for(i = 0;i < slots_.size();i++) { - if (slots_[i] == -1) { - slots_[i] = id; - return i; - } - } - - slots_.resize(slots_.size() + 1); - slots_[slots_.size() - 1] = id; - - return slots_.size() - 1; - } - - void erase(SDL_FingerID id) - { - auto it = std::find(slots_.begin(), slots_.end(), id); - - if (it != slots_.end()) { - auto index = std::distance(slots_.begin(), it); - slots_[index] = -1; - if (index == slots_.size()-1) { - while (slots_[index] == -1) { - slots_.resize(index); - index--; - } - } - } - } - -private: - std::vector slots_; -}; - -const std::array kKeycodes {{ - SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED 0 */ - SDL_SCANCODE_ESCAPE, /* KEY_ESC 1 */ - SDL_SCANCODE_1, /* KEY_1 2 */ - SDL_SCANCODE_2, /* KEY_2 3 */ - SDL_SCANCODE_3, /* KEY_3 4 */ - SDL_SCANCODE_4, /* KEY_4 5 */ - SDL_SCANCODE_5, /* KEY_5 6 */ - SDL_SCANCODE_6, /* KEY_6 7 */ - SDL_SCANCODE_7, /* KEY_7 8 */ - SDL_SCANCODE_8, /* KEY_8 9 */ - SDL_SCANCODE_9, /* KEY_9 10 */ - SDL_SCANCODE_0, /* KEY_0 11 */ - SDL_SCANCODE_MINUS, /* KEY_MINUS 12 */ - SDL_SCANCODE_EQUALS, /* KEY_EQUAL 13 */ - SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE 14 */ - SDL_SCANCODE_TAB, /* KEY_TAB 15 */ - SDL_SCANCODE_Q, /* KEY_Q 16 */ - SDL_SCANCODE_W, /* KEY_W 17 */ - SDL_SCANCODE_E, /* KEY_E 18 */ - SDL_SCANCODE_R, /* KEY_R 19 */ - SDL_SCANCODE_T, /* KEY_T 20 */ - SDL_SCANCODE_Y, /* KEY_Y 21 */ - SDL_SCANCODE_U, /* KEY_U 22 */ - SDL_SCANCODE_I, /* KEY_I 23 */ - SDL_SCANCODE_O, /* KEY_O 24 */ - SDL_SCANCODE_P, /* KEY_P 25 */ - SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE 26 */ - SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE 27 */ - SDL_SCANCODE_RETURN, /* KEY_ENTER 28 */ - SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL 29 */ - SDL_SCANCODE_A, /* KEY_A 30 */ - SDL_SCANCODE_S, /* KEY_S 31 */ - SDL_SCANCODE_D, /* KEY_D 32 */ - SDL_SCANCODE_F, /* KEY_F 33 */ - SDL_SCANCODE_G, /* KEY_G 34 */ - SDL_SCANCODE_H, /* KEY_H 35 */ - SDL_SCANCODE_J, /* KEY_J 36 */ - SDL_SCANCODE_K, /* KEY_K 37 */ - SDL_SCANCODE_L, /* KEY_L 38 */ - SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON 39 */ - SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE 40 */ - SDL_SCANCODE_GRAVE, /* KEY_GRAVE 41 */ - SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT 42 */ - SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH 43 */ - SDL_SCANCODE_Z, /* KEY_Z 44 */ - SDL_SCANCODE_X, /* KEY_X 45 */ - SDL_SCANCODE_C, /* KEY_C 46 */ - SDL_SCANCODE_V, /* KEY_V 47 */ - SDL_SCANCODE_B, /* KEY_B 48 */ - SDL_SCANCODE_N, /* KEY_N 49 */ - SDL_SCANCODE_M, /* KEY_M 50 */ - SDL_SCANCODE_COMMA, /* KEY_COMMA 51 */ - SDL_SCANCODE_PERIOD, /* KEY_DOT 52 */ - SDL_SCANCODE_SLASH, /* KEY_SLASH 53 */ - SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT 54 */ - SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK 55 */ - SDL_SCANCODE_LALT, /* KEY_LEFTALT 56 */ - SDL_SCANCODE_SPACE, /* KEY_SPACE 57 */ - SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK 58 */ - SDL_SCANCODE_F1, /* KEY_F1 59 */ - SDL_SCANCODE_F2, /* KEY_F2 60 */ - SDL_SCANCODE_F3, /* KEY_F3 61 */ - SDL_SCANCODE_F4, /* KEY_F4 62 */ - SDL_SCANCODE_F5, /* KEY_F5 63 */ - SDL_SCANCODE_F6, /* KEY_F6 64 */ - SDL_SCANCODE_F7, /* KEY_F7 65 */ - SDL_SCANCODE_F8, /* KEY_F8 66 */ - SDL_SCANCODE_F9, /* KEY_F9 67 */ - SDL_SCANCODE_F10, /* KEY_F10 68 */ - SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK 69 */ - SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK 70 */ - SDL_SCANCODE_KP_7, /* KEY_KP7 71 */ - SDL_SCANCODE_KP_8, /* KEY_KP8 72 */ - SDL_SCANCODE_KP_9, /* KEY_KP9 73 */ - SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS 74 */ - SDL_SCANCODE_KP_4, /* KEY_KP4 75 */ - SDL_SCANCODE_KP_5, /* KEY_KP5 76 */ - SDL_SCANCODE_KP_6, /* KEY_KP6 77 */ - SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS 78 */ - SDL_SCANCODE_KP_1, /* KEY_KP1 79 */ - SDL_SCANCODE_KP_2, /* KEY_KP2 80 */ - SDL_SCANCODE_KP_3, /* KEY_KP3 81 */ - SDL_SCANCODE_KP_0, /* KEY_KP0 82 */ - SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT 83 */ - SDL_SCANCODE_UNKNOWN, /* 84 */ - SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU 85 */ - SDL_SCANCODE_UNKNOWN, /* KEY_102ND 86 */ - SDL_SCANCODE_F11, /* KEY_F11 87 */ - SDL_SCANCODE_F12, /* KEY_F12 88 */ - SDL_SCANCODE_UNKNOWN, /* KEY_RO 89 */ - SDL_SCANCODE_LANG3, /* KEY_KATAKANA 90 */ - SDL_SCANCODE_LANG4, /* KEY_HIRAGANA 91 */ - SDL_SCANCODE_UNKNOWN, /* KEY_HENKAN 92 */ - SDL_SCANCODE_LANG3, /* KEY_KATAKANAHIRAGANA 93 */ - SDL_SCANCODE_UNKNOWN, /* KEY_MUHENKAN 94 */ - SDL_SCANCODE_KP_COMMA, /* KEY_KPJPCOMMA 95 */ - SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER 96 */ - SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL 97 */ - SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH 98 */ - SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ 99 */ - SDL_SCANCODE_RALT, /* KEY_RIGHTALT 100 */ - SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED 101 */ - SDL_SCANCODE_HOME, /* KEY_HOME 102 */ - SDL_SCANCODE_UP, /* KEY_UP 103 */ - SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP 104 */ - SDL_SCANCODE_LEFT, /* KEY_LEFT 105 */ - SDL_SCANCODE_RIGHT, /* KEY_RIGHT 106 */ - SDL_SCANCODE_END, /* KEY_END 107 */ - SDL_SCANCODE_DOWN, /* KEY_DOWN 108 */ - SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN 109 */ - SDL_SCANCODE_INSERT, /* KEY_INSERT 110 */ - SDL_SCANCODE_DELETE, /* KEY_DELETE 111 */ - SDL_SCANCODE_UNKNOWN, /* KEY_MACRO 112 */ - SDL_SCANCODE_MUTE, /* KEY_MUTE 113 */ - SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN 114 */ - SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP 115 */ - SDL_SCANCODE_POWER, /* KEY_POWER 116 SC System Power Down */ - SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL 117 */ - SDL_SCANCODE_KP_MINUS, /* KEY_KPPLUSMINUS 118 */ - SDL_SCANCODE_PAUSE, /* KEY_PAUSE 119 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SCALE 120 AL Compiz Scale (Expose) */ - SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA 121 */ - SDL_SCANCODE_LANG1, /* KEY_HANGEUL,KEY_HANGUEL 122 */ - SDL_SCANCODE_LANG2, /* KEY_HANJA 123 */ - SDL_SCANCODE_INTERNATIONAL3,/* KEY_YEN 124 */ - SDL_SCANCODE_LGUI, /* KEY_LEFTMETA 125 */ - SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA 126 */ - SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE 127 */ - SDL_SCANCODE_STOP, /* KEY_STOP 128 AC Stop */ - SDL_SCANCODE_AGAIN, /* KEY_AGAIN 129 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PROPS 130 AC Properties */ - SDL_SCANCODE_UNDO, /* KEY_UNDO 131 AC Undo */ - SDL_SCANCODE_UNKNOWN, /* KEY_FRONT 132 */ - SDL_SCANCODE_COPY, /* KEY_COPY 133 AC Copy */ - SDL_SCANCODE_UNKNOWN, /* KEY_OPEN 134 AC Open */ - SDL_SCANCODE_PASTE, /* KEY_PASTE 135 AC Paste */ - SDL_SCANCODE_FIND, /* KEY_FIND 136 AC Search */ - SDL_SCANCODE_CUT, /* KEY_CUT 137 AC Cut */ - SDL_SCANCODE_HELP, /* KEY_HELP 138 AL Integrated Help Center */ - SDL_SCANCODE_MENU, /* KEY_MENU 139 Menu (show menu) */ - SDL_SCANCODE_CALCULATOR, /* KEY_CALC 140 AL Calculator */ - SDL_SCANCODE_UNKNOWN, /* KEY_SETUP 141 */ - SDL_SCANCODE_SLEEP, /* KEY_SLEEP 142 SC System Sleep */ - SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP 143 System Wake Up */ - SDL_SCANCODE_UNKNOWN, /* KEY_FILE 144 AL Local Machine Browser */ - SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE 145 */ - SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE 146 */ - SDL_SCANCODE_UNKNOWN, /* KEY_XFER 147 */ - SDL_SCANCODE_APP1, /* KEY_PROG1 148 */ - SDL_SCANCODE_APP1, /* KEY_PROG2 149 */ - SDL_SCANCODE_WWW, /* KEY_WWW 150 AL Internet Browser */ - SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS 151 */ - SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE,KEY_SCREENLOCK 152 AL Terminal Lock/Screensaver */ - SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION 153 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS 154 */ - SDL_SCANCODE_MAIL, /* KEY_MAIL 155 */ - SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS 156 AC Bookmarks */ - SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER 157 */ - SDL_SCANCODE_AC_BACK, /* KEY_BACK 158 AC Back */ - SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD 159 AC Forward */ - SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD 160 */ - SDL_SCANCODE_EJECT, /* KEY_EJECTCD 161 */ - SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD 162 */ - SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG 163 */ - SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE 164 */ - SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG 165 */ - SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD 166 */ - SDL_SCANCODE_UNKNOWN, /* KEY_RECORD 167 */ - SDL_SCANCODE_UNKNOWN, /* KEY_REWIND 168 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PHONE 169 Media Select Telephone */ - SDL_SCANCODE_UNKNOWN, /* KEY_ISO 170 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG 171 AL Consumer Control Configuration */ - SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE 172 AC Home */ - SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH 173 AC Refresh */ - SDL_SCANCODE_UNKNOWN, /* KEY_EXIT 174 AC Exit */ - SDL_SCANCODE_UNKNOWN, /* KEY_MOVE 175 */ - SDL_SCANCODE_UNKNOWN, /* KEY_EDIT 176 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP 177 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN 178 */ - SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN 179 */ - SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN 180 */ - SDL_SCANCODE_UNKNOWN, /* KEY_NEW 181 AC New */ - SDL_SCANCODE_AGAIN, /* KEY_REDO 182 AC Redo/Repeat */ - SDL_SCANCODE_F13, /* KEY_F13 183 */ - SDL_SCANCODE_F14, /* KEY_F14 184 */ - SDL_SCANCODE_F15, /* KEY_F15 185 */ - SDL_SCANCODE_F16, /* KEY_F16 186 */ - SDL_SCANCODE_F17, /* KEY_F17 187 */ - SDL_SCANCODE_F18, /* KEY_F18 188 */ - SDL_SCANCODE_F19, /* KEY_F19 189 */ - SDL_SCANCODE_F20, /* KEY_F20 190 */ - SDL_SCANCODE_F21, /* KEY_F21 191 */ - SDL_SCANCODE_F22, /* KEY_F22 192 */ - SDL_SCANCODE_F23, /* KEY_F23 193 */ - SDL_SCANCODE_F24, /* KEY_F24 194 */ - SDL_SCANCODE_UNKNOWN, /* 195 */ - SDL_SCANCODE_UNKNOWN, /* 196 */ - SDL_SCANCODE_UNKNOWN, /* 197 */ - SDL_SCANCODE_UNKNOWN, /* 198 */ - SDL_SCANCODE_UNKNOWN, /* 199 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD 200 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD 201 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 202 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 203 */ - SDL_SCANCODE_UNKNOWN, /* KEY_DASHBOARD 204 AL Dashboard */ - SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND 205 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE 206 AC Close */ - SDL_SCANCODE_UNKNOWN, /* KEY_PLAY 207 */ - SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD 208 */ - SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST 209 */ - SDL_SCANCODE_UNKNOWN, /* KEY_PRINT 210 AC Print */ - SDL_SCANCODE_UNKNOWN, /* KEY_HP 211 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA 212 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SOUND 213 */ - SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION 214 */ - SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL 215 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CHAT 216 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SEARCH 217 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT 218 */ - SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE 219 AL Checkbook/Finance */ - SDL_SCANCODE_UNKNOWN, /* KEY_SPORT 220 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SHOP 221 */ - SDL_SCANCODE_UNKNOWN, /* KEY_ALTERASE 222 */ - SDL_SCANCODE_UNKNOWN, /* KEY_CANCEL 223 AC Cancel */ - SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSDOWN 224 */ - SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSUP 225 */ - SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA 226 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */ - SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMTOGGLE 228 */ - SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMDOWN 229 */ - SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMUP 230 */ - SDL_SCANCODE_UNKNOWN, /* KEY_SEND 231 AC Send */ - SDL_SCANCODE_UNKNOWN, /* KEY_REPLY 232 AC Reply */ - SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL 233 AC Forward Msg */ - SDL_SCANCODE_UNKNOWN, /* KEY_SAVE 234 AC Save */ - SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS 235 */ - SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY 236 */ - SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH 237 */ - SDL_SCANCODE_UNKNOWN, /* KEY_WLAN 238 */ - SDL_SCANCODE_UNKNOWN, /* KEY_UWB 239 */ - SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN 240 */ - SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT 241 drive next video source */ - SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV 242 drive previous video source */ - SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE 243 brightness up, after max is min */ - SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */ - SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF 245 display device to off state */ - SDL_SCANCODE_UNKNOWN, /* KEY_WIMAX 246 */ - SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL 247 Key that controls all radios */ - SDL_SCANCODE_UNKNOWN /* KEY_MICMUTE 248 Mute / unmute the microphone */ -}}; - -std::uint16_t convert_sdl_scancode_to_evdev(const SDL_Scancode &scan_code) { - for (std::uint16_t n = 0; n < kKeycodes.size(); n++) { - if (kKeycodes[n] == scan_code) - return n; - } - return KEY_RESERVED; -} -} - namespace anbox { namespace ubuntu { -Window::Window(const std::shared_ptr &input_manager, - int width, int height) : +Window::Window(int x, int y, int width, int height) : native_display_(0), native_window_(0) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); - window_ = SDL_CreateWindow("anbox", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - width, - height, - SDL_WINDOW_OPENGL); + window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL); if (!window_) { const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); BOOST_THROW_EXCEPTION(std::runtime_error(message)); } - SDL_SysWMinfo info; SDL_VERSION(&info.version); SDL_GetWindowWMInfo(window_, &info); @@ -363,132 +51,15 @@ Window::Window(const std::shared_ptr &input_manager, } int actual_width = 0, actual_height = 0; + int actual_x = 0, actual_y = 0; SDL_GetWindowSize(window_, &actual_width, &actual_height); - - DEBUG("Window created with %d x %d", actual_width, actual_height); - - // Create our touch panel input device - touchpanel_ = input_manager->create_device(); - touchpanel_->set_name("anbox-touchpanel"); - touchpanel_->set_driver_version(1); - touchpanel_->set_input_id({ BUS_VIRTUAL, 1, 1, 1 }); - touchpanel_->set_physical_location("none"); - touchpanel_->set_abs_bit(ABS_MT_TRACKING_ID); - touchpanel_->set_abs_bit(ABS_MT_SLOT); - touchpanel_->set_abs_bit(ABS_MT_POSITION_X); - touchpanel_->set_abs_bit(ABS_MT_POSITION_Y); - touchpanel_->set_prop_bit(INPUT_PROP_DIRECT); - touchpanel_->set_abs_min(ABS_MT_POSITION_X, 0); - touchpanel_->set_abs_max(ABS_MT_POSITION_X, static_cast(actual_width)); - touchpanel_->set_abs_min(ABS_MT_POSITION_Y, 0); - touchpanel_->set_abs_max(ABS_MT_POSITION_Y, static_cast(actual_height)); - touchpanel_->set_abs_max(ABS_MT_SLOT, 10); - touchpanel_->set_abs_max(ABS_MT_TRACKING_ID, 255); - - pointer_ = input_manager->create_device(); - pointer_->set_name("anbox-pointer"); - pointer_->set_driver_version(1); - pointer_->set_input_id({ BUS_VIRTUAL, 2, 2, 2 }); - pointer_->set_physical_location("none"); - pointer_->set_key_bit(BTN_MOUSE); - // NOTE: We don't use REL_X/REL_Y in reality but have to specify them here - // to allow InputFlinger to detect we're a cursor device. - pointer_->set_rel_bit(REL_X); - pointer_->set_rel_bit(REL_Y); - pointer_->set_rel_bit(REL_HWHEEL); - pointer_->set_rel_bit(REL_WHEEL); - pointer_->set_prop_bit(INPUT_PROP_POINTER); - - keyboard_ = input_manager->create_device(); - keyboard_->set_name("anbox-keyboard"); - keyboard_->set_driver_version(1); - keyboard_->set_input_id({ BUS_VIRTUAL, 3, 3, 3 }); - keyboard_->set_physical_location("none"); - keyboard_->set_key_bit(BTN_MISC); - keyboard_->set_key_bit(KEY_OK); + SDL_GetWindowPosition(window_, &actual_x, &actual_y); + DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height); } Window::~Window() { -} - -void Window::process_input_event(const SDL_Event &event) { - static SlotFingerMapper mapper; - std::vector touch_events; - std::vector mouse_events; - std::vector keyboard_events; - - const auto id = event.tfinger.fingerId; - const auto slot = mapper.find_or_create(id); - - switch (event.type) { - case SDL_FINGERUP: - touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot }); - touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, -1 }); - touch_events.push_back({ EV_KEY, BTN_TOUCH, 0 }); - touch_events.push_back({ EV_KEY, BTN_TOOL_FINGER, 0 }); - touch_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - mapper.erase(id); - break; - case SDL_FINGERDOWN: - touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot }); - touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, static_cast(id) }); - touch_events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast(event.tfinger.x) }); - touch_events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast(event.tfinger.y) }); - touch_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - break; - case SDL_FINGERMOTION: - touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot }); - touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, static_cast(id) }); - touch_events.push_back({ EV_KEY, BTN_TOUCH, 1 }); - touch_events.push_back({ EV_KEY, BTN_TOOL_FINGER, 1 }); - touch_events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast(event.tfinger.x) }); - touch_events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast(event.tfinger.y) }); - touch_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - break; - case SDL_MOUSEBUTTONDOWN: - mouse_events.push_back({ EV_KEY, BTN_LEFT, 1 }); - mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - break; - case SDL_MOUSEBUTTONUP: - mouse_events.push_back({ EV_KEY, BTN_LEFT, 0 }); - mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - break; - case SDL_MOUSEMOTION: - // NOTE: Sending relative move events doesn't really work and we have changes - // in libinputflinger to take ABS_X/ABS_Y instead for absolute position events. - mouse_events.push_back({ EV_ABS, ABS_X, static_cast(event.motion.x) }); - mouse_events.push_back({ EV_ABS, ABS_Y, static_cast(event.motion.y) }); - mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); - break; - case SDL_MOUSEWHEEL: - mouse_events.push_back({ EV_REL, REL_WHEEL, static_cast(event.wheel.y) }); - break; - case SDL_KEYDOWN: { - const auto code = convert_sdl_scancode_to_evdev(event.key.keysym.scancode); - if (code == KEY_RESERVED) - break; - keyboard_events.push_back({ EV_KEY, code, 1 }); - break; - } - case SDL_KEYUP: { - const auto code = convert_sdl_scancode_to_evdev(event.key.keysym.scancode); - if (code == KEY_RESERVED) - break; - keyboard_events.push_back({ EV_KEY, code, 0 }); - break; - } - default: - break; - } - - if (touch_events.size() > 0) - touchpanel_->send_events(touch_events); - - if (mouse_events.size() > 0) - pointer_->send_events(mouse_events); - - if (keyboard_events.size() > 0) - keyboard_->send_events(keyboard_events); + if (window_) + SDL_DestroyWindow(window_); } EGLNativeWindowType Window::native_window() const { diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index 64782e7..7911082 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -26,26 +26,15 @@ #include namespace anbox { -namespace input { -class Manager; -class Device; -class Event; -} // namespace input namespace ubuntu { class Window { public: - Window(const std::shared_ptr &input_manager, - int width, int height); + Window(int x, int y, int width, int height); ~Window(); - void process_input_event(const SDL_Event &event); - EGLNativeWindowType native_window() const; private: - std::shared_ptr touchpanel_; - std::shared_ptr pointer_; - std::shared_ptr keyboard_; EGLNativeDisplayType native_display_; EGLNativeWindowType native_window_; SDL_Window *window_; diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/window_creator.cpp index 6e05691..09d37f3 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/window_creator.cpp @@ -17,6 +17,8 @@ #include "anbox/ubuntu/window_creator.h" #include "anbox/ubuntu/window.h" +#include "anbox/input/manager.h" +#include "anbox/input/device.h" #include "anbox/logger.h" #include @@ -35,6 +37,16 @@ WindowCreator::WindowCreator(const std::shared_ptr &input_manage if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize SDL")); +#if 0 + SDL_DisplayMode display_mode; + // FIXME statically just check the first (primary) display for its mode; + // once we get multi-monitor support we need to do this better. + if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) { + display_info_.horizontal_resolution = display_mode.w; + display_info_.vertical_resolution = display_mode.h; + } +#endif + event_thread_ = std::thread(&WindowCreator::process_events, this); SDL_DisplayMode display_mode; @@ -69,18 +81,6 @@ void WindowCreator::process_events() { case SDL_WINDOWEVENT: process_window_event(event); break; - case SDL_FINGERUP: - case SDL_FINGERMOTION: - case SDL_FINGERDOWN: - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - case SDL_MOUSEWHEEL: - case SDL_KEYDOWN: - case SDL_KEYUP: - if (current_window_) - current_window_->process_input_event(event); - break; } } } @@ -88,17 +88,11 @@ void WindowCreator::process_events() { EGLNativeWindowType WindowCreator::create_window(int x, int y, int width, int height) try { - if (windows_.size() == 1) { - WARNING("Tried to create another window but we currently only allow one"); - return 0; - } - - auto window = std::make_shared(input_manager_, width, height); + auto window = std::make_shared(x, y, width, height); if (not window) BOOST_THROW_EXCEPTION(std::bad_alloc()); windows_.insert({window->native_window(), window}); - current_window_ = window; return window->native_window(); } diff --git a/src/anbox/ubuntu/window_creator.h b/src/anbox/ubuntu/window_creator.h index cef70c4..b8e827e 100644 --- a/src/anbox/ubuntu/window_creator.h +++ b/src/anbox/ubuntu/window_creator.h @@ -27,6 +27,9 @@ #include namespace anbox { +namespace input { +class Device; +} // namespace input namespace ubuntu { class MirDisplayConnection; class Window; From 8dfed5b7921522955384adaca0165a3f5d4e9a28 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 07:42:51 +0100 Subject: [PATCH 02/54] Render all windows without border --- src/anbox/ubuntu/window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index f024dee..e5c59c0 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -30,7 +30,7 @@ Window::Window(int x, int y, int width, int height) : SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); - window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL); + window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); if (!window_) { const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); BOOST_THROW_EXCEPTION(std::runtime_error(message)); From 4c2711cfd0de5a7c2f5c671397fce8db5a4c4d4e Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 07:46:17 +0100 Subject: [PATCH 03/54] Drop superflous second display detection --- src/anbox/ubuntu/window_creator.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/window_creator.cpp index 09d37f3..80522ae 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/window_creator.cpp @@ -37,16 +37,6 @@ WindowCreator::WindowCreator(const std::shared_ptr &input_manage if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize SDL")); -#if 0 - SDL_DisplayMode display_mode; - // FIXME statically just check the first (primary) display for its mode; - // once we get multi-monitor support we need to do this better. - if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) { - display_info_.horizontal_resolution = display_mode.w; - display_info_.vertical_resolution = display_mode.h; - } -#endif - event_thread_ = std::thread(&WindowCreator::process_events, this); SDL_DisplayMode display_mode; From 2d63a6e5680b6b0596f90ea117ef647083332f40 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 07:49:41 +0100 Subject: [PATCH 04/54] emugl: update cmake configuration with missing files --- .../shared/OpenglCodecCommon/CMakeLists.txt | 13 +++++++++++-- .../shared/emugl/common/CMakeLists.txt | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/external/android-emugl/shared/OpenglCodecCommon/CMakeLists.txt b/external/android-emugl/shared/OpenglCodecCommon/CMakeLists.txt index 1dda791..67606d7 100644 --- a/external/android-emugl/shared/OpenglCodecCommon/CMakeLists.txt +++ b/external/android-emugl/shared/OpenglCodecCommon/CMakeLists.txt @@ -1,6 +1,15 @@ set(SOURCES - glUtils.cpp ChecksumCalculator.cpp - ChecksumCalculatorThreadInfo.cpp) + ChecksumCalculator.h + ChecksumCalculatorThreadInfo.cpp + ChecksumCalculatorThreadInfo.h + CMakeLists.txt + ErrorLog.h + gl_base_types.h + GLDecoderContextData.h + glUtils.cpp + glUtils.h + Makefile + ProtocolUtils.h) add_library(OpenglCodecCommon ${SOURCES}) diff --git a/external/android-emugl/shared/emugl/common/CMakeLists.txt b/external/android-emugl/shared/emugl/common/CMakeLists.txt index a479a9b..ef8b6d2 100644 --- a/external/android-emugl/shared/emugl/common/CMakeLists.txt +++ b/external/android-emugl/shared/emugl/common/CMakeLists.txt @@ -1,15 +1,32 @@ set(COMMON_SOURCES + condition_variable.h crash_reporter.cpp + crash_reporter.h id_to_object_map.cpp + id_to_object_map.h lazy_instance.cpp + lazy_instance.h logging.cpp + logging.h message_channel.cpp + message_channel.h + mutex.h + mutex_unittest.cpp pod_vector.cpp + pod_vector.h + scoped_pointer_vector.h shared_library.cpp + shared_library.h smart_ptr.cpp + smart_ptr.h sockets.cpp + sockets.h + thread.h + thread_pthread.cpp thread_store.cpp - thread_pthread.cpp) + thread_store.h + thread_unittest.cpp + unique_integer_map.h) add_library(emugl_common ${COMMON_SOURCES}) target_link_libraries(emugl_common From d5d2f8d36f6e75bc859a1492b281eb7a619cdac4 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 08:14:38 +0100 Subject: [PATCH 05/54] Add display manager instance which hands relevant information to emugl layer --- .../host/libs/libOpenglRender/CMakeLists.txt | 2 + .../libs/libOpenglRender/DisplayManager.cpp | 42 +++++++++++++++++++ .../libs/libOpenglRender/DisplayManager.h | 39 +++++++++++++++++ .../libs/libOpenglRender/RenderControl.cpp | 11 +++-- src/anbox/graphics/gl_renderer_server.cpp | 9 +--- src/anbox/graphics/window_creator.h | 10 ++--- 6 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp create mode 100644 external/android-emugl/host/libs/libOpenglRender/DisplayManager.h diff --git a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt b/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt index bbf5b9a..701ea8c 100644 --- a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt +++ b/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt @@ -1,8 +1,10 @@ set(SOURCES ColorBuffer.cpp + DisplayManager.cpp FbConfig.cpp FrameBuffer.cpp LayerManager.cpp + NativeSubWindow.h NativeSubWindow_delegate.cpp ReadBuffer.cpp RenderContext.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp b/external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp new file mode 100644 index 0000000..2e26a81 --- /dev/null +++ b/external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "DisplayManager.h" + +namespace { +std::shared_ptr display_mgr; + +class NullDisplayManager : public DisplayManager { +public: + DisplayInfo display_info() const override { + return {1280, 720}; + } +}; +} + +DisplayManager::~DisplayManager() { +} + +std::shared_ptr DisplayManager::get() { + if (!display_mgr) + display_mgr = std::make_shared(); + return display_mgr; +} + +void registerDisplayManager(const std::shared_ptr &mgr) { + display_mgr = mgr; +} diff --git a/external/android-emugl/host/libs/libOpenglRender/DisplayManager.h b/external/android-emugl/host/libs/libOpenglRender/DisplayManager.h new file mode 100644 index 0000000..beb678a --- /dev/null +++ b/external/android-emugl/host/libs/libOpenglRender/DisplayManager.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef DISPLAY_MANAGER_H_ +#define DISPLAY_MANAGER_H_ + +#include + +class DisplayManager { +public: + virtual ~DisplayManager(); + + struct DisplayInfo { + int horizontal_resolution; + int vertical_resolution; + }; + + virtual DisplayInfo display_info() const = 0; + + static std::shared_ptr get(); +}; + +void registerDisplayManager(const std::shared_ptr &mgr); + +#endif diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp index c36769a..618f454 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp @@ -21,6 +21,7 @@ #include "RenderThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h" #include "LayerManager.h" +#include "DisplayManager.h" #include "OpenGLESDispatch/EGLDispatch.h" @@ -160,12 +161,10 @@ static EGLint rcGetFBParam(EGLint param) switch(param) { case FB_WIDTH: - // FIXME DISPLAY MANAGER!! - ret = 1920; + ret = DisplayManager::get()->display_info().horizontal_resolution; break; case FB_HEIGHT: - // FIXME DISPLAY MANAGER!! - ret = 1080; + ret = DisplayManager::get()->display_info().vertical_resolution; break; case FB_XDPI: ret = 72; // XXX: should be implemented @@ -404,12 +403,12 @@ int rcGetNumDisplays() { int rcGetDisplayWidth(uint32_t display_id) { printf("%s: display_id=%d\n", __func__, display_id); - return 1920; + return DisplayManager::get()->display_info().horizontal_resolution; } int rcGetDisplayHeight(uint32_t display_id) { printf("%s: display_id=%d\n", __func__, display_id); - return 1080; + return DisplayManager::get()->display_info().vertical_resolution; } int rcGetDisplayDpiX(uint32_t display_id) { diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 3b6d3af..3d02370 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -46,6 +46,7 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &window_ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); registerSubWindowHandler(window_creator_); + registerDisplayManager(window_creator_); } GLRendererServer::~GLRendererServer() { @@ -81,14 +82,6 @@ void GLRendererServer::start() { BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); socket_path_ = server_addr; - -#if 0 - // Create the window we use for rendering the output we get from the - // Android container. This will internally construct a Mir surface - // and use the host EGL/GLES libraries for rendering. - if (!showOpenGLSubwindow(0, 0, 0, width, height, width, height, 1.0f, 0)) - BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup GL based window")); -#endif } std::string GLRendererServer::socket_path() const { diff --git a/src/anbox/graphics/window_creator.h b/src/anbox/graphics/window_creator.h index 00cd8be..66d3c23 100644 --- a/src/anbox/graphics/window_creator.h +++ b/src/anbox/graphics/window_creator.h @@ -19,23 +19,19 @@ #define ANBOX_GRAPHICS_WINDOW_CREATOR_H_ #include "external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h" +#include "external/android-emugl/host/libs/libOpenglRender/DisplayManager.h" namespace anbox { namespace input { class Manager; } // namespace input namespace graphics { -class WindowCreator : public SubWindowHandler { +class WindowCreator : public SubWindowHandler, + public DisplayManager { public: WindowCreator(const std::shared_ptr &input_manager); virtual ~WindowCreator(); - struct DisplayInfo { - int horizontal_resolution; - int vertical_resolution; - }; - - virtual DisplayInfo display_info() const = 0; virtual EGLNativeDisplayType native_display() const = 0; protected: From 2717449710f8c17c8366cc4c728365ed35b7aa9b Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 08:15:25 +0100 Subject: [PATCH 06/54] Remove unneeded width, height and use_sub_window arguments --- .../OpenglRender/render_api_functions.h | 2 +- .../host/libs/libOpenglRender/FrameBuffer.cpp | 9 ++++---- .../host/libs/libOpenglRender/FrameBuffer.h | 5 ++--- .../host/libs/libOpenglRender/RenderApi.cpp | 5 ++--- .../libs/libOpenglRender/RenderWindow.cpp | 21 ++++--------------- .../host/libs/libOpenglRender/RenderWindow.h | 2 +- src/anbox/graphics/gl_renderer_server.cpp | 2 +- 7 files changed, 15 insertions(+), 31 deletions(-) diff --git a/external/android-emugl/host/include/OpenglRender/render_api_functions.h b/external/android-emugl/host/include/OpenglRender/render_api_functions.h index b68deee..59237a8 100644 --- a/external/android-emugl/host/include/OpenglRender/render_api_functions.h +++ b/external/android-emugl/host/include/OpenglRender/render_api_functions.h @@ -25,7 +25,7 @@ typedef void (*emugl_crash_func_t)(const char* format, ...); #define LIST_RENDER_API_FUNCTIONS(X) \ X(int, initLibrary, (), ()) \ X(int, setStreamMode, (int mode), (mode)) \ - X(int, initOpenGLRenderer, (EGLNativeDisplayType native_display, int width, int height, bool useSubWindow, char* addr, size_t addrLen, emugl_logger_struct logfuncs, emugl_crash_func_t crashfunc), (width, height, useSubWindow, addr, addrLen, logfuncs, crashfunc)) \ + X(int, initOpenGLRenderer, (EGLNativeDisplayType native_display, char* addr, size_t addrLen, emugl_logger_struct logfuncs, emugl_crash_func_t crashfunc), (native_display, addr, addrLen, logfuncs, crashfunc)) \ X(void, getHardwareStrings, (const char** vendor, const char** renderer, const char** version), (vendor, renderer, version)) \ X(void, setPostCallback, (OnPostFn onPost, void* onPostContext), (onPost, onPostContext)) \ X(bool, showOpenGLSubwindow, (FBNativeWindowType window, int wx, int wy, int ww, int wh, int fbw, int fbh, float dpr, float zRot), (window, wx, wy, ww, wh, fbw, fbh, dpr, zRot)) \ diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp index b81e68e..0d47b68 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -162,7 +162,7 @@ void FrameBuffer::finalize(){ s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface); } -bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int height, bool useSubWindow) +bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay) { GL_LOG("FrameBuffer::initialize"); if (s_theFrameBuffer != NULL) { @@ -172,7 +172,7 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int // // allocate space for the FrameBuffer object // - FrameBuffer *fb = new FrameBuffer(width, height, useSubWindow); + FrameBuffer *fb = new FrameBuffer(); if (!fb) { ERR("Failed to create fb\n"); return false; @@ -218,7 +218,7 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int // // Create EGL context for framebuffer post rendering. // - GLint surfaceType = (useSubWindow ? EGL_WINDOW_BIT : 0) | EGL_PBUFFER_BIT; + GLint surfaceType = EGL_WINDOW_BIT| EGL_PBUFFER_BIT; const GLint configAttribs[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, @@ -427,8 +427,7 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int return true; } -FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow) : - m_useSubWindow(useSubWindow), +FrameBuffer::FrameBuffer() : m_configs(NULL), m_eglDisplay(EGL_NO_DISPLAY), m_colorBufferHelper(new ColorBufferHelper(this)), diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h index a3d419d..5eb9c60 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h @@ -76,7 +76,7 @@ public: // own sub-windows. If false, this means the caller will use // setPostCallback() instead to retrieve the content. // Returns true on success, false otherwise. - static bool initialize(EGLNativeDisplayType nativeDisplay, int width, int height, bool useSubWindow); + static bool initialize(EGLNativeDisplayType nativeDisplay); FrameBufferWindow* createWindow(int x, int y, int width, int height); void destroyWindow(FrameBufferWindow *window); @@ -248,7 +248,7 @@ public: bool unbind_locked(); private: - FrameBuffer(int p_width, int p_height, bool useSubWindow); + FrameBuffer(); ~FrameBuffer(); HandleType genHandle(); @@ -257,7 +257,6 @@ private: private: static FrameBuffer *s_theFrameBuffer; static HandleType s_nextHandle; - bool m_useSubWindow; emugl::Mutex m_lock; FbConfigList* m_configs; FBNativeWindowType m_nativeWindow; diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp index d8b0317..d0b40e9 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp @@ -74,8 +74,7 @@ RENDER_APICALL int RENDER_APIENTRY initLibrary(void) } RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( - EGLNativeDisplayType native_display, - int width, int height, bool useSubWindow, char* addr, size_t addrLen, + EGLNativeDisplayType native_display, char* addr, size_t addrLen, emugl_logger_struct logfuncs, emugl_crash_func_t crashfunc) { set_emugl_crash_reporter(crashfunc); set_emugl_logger(logfuncs.coarse); @@ -113,7 +112,7 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( // initialize the renderer and listen to connections // on a thread in the current process. // - s_renderWindow = new RenderWindow(native_display, width, height, kUseThread, useSubWindow); + s_renderWindow = new RenderWindow(native_display, kUseThread); if (!s_renderWindow) { ERR("Could not create rendering window class"); GL_LOG("Could not create rendering window class"); diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp index 31f50bd..9916203 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp @@ -73,9 +73,6 @@ struct RenderWindowMessage { // CMD_INITIALIZE struct { EGLNativeDisplayType nativeDisplay; - int width; - int height; - bool useSubWindow; } init; // CMD_SET_POST_CALLBACK @@ -118,13 +115,9 @@ struct RenderWindowMessage { bool result = false; switch (msg.cmd) { case CMD_INITIALIZE: - D("CMD_INITIALIZE w=%d h=%d\n", msg.init.width, msg.init.height); - GL_LOG("RenderWindow: CMD_INITIALIZE w=%d h=%d", - msg.init.width, msg.init.height); - result = FrameBuffer::initialize(msg.init.nativeDisplay, - msg.init.width, - msg.init.height, - msg.init.useSubWindow); + D("CMD_INITIALIZE\n"); + GL_LOG("RenderWindow: CMD_INITIALIZE"); + result = FrameBuffer::initialize(msg.init.nativeDisplay); break; case CMD_FINALIZE: @@ -252,10 +245,7 @@ private: } // namespace RenderWindow::RenderWindow(EGLNativeDisplayType native_display, - int width, - int height, - bool use_thread, - bool use_sub_window) : + bool use_thread) : mValid(false), mHasSubWindow(false), mThread(NULL), @@ -269,9 +259,6 @@ RenderWindow::RenderWindow(EGLNativeDisplayType native_display, RenderWindowMessage msg; msg.cmd = CMD_INITIALIZE; msg.init.nativeDisplay = native_display; - msg.init.width = width; - msg.init.height = height; - msg.init.useSubWindow = use_sub_window; mValid = processMessage(msg); } diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h index 6389475..dd2eb2f 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h +++ b/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h @@ -59,7 +59,7 @@ public: // // Note that this call doesn't display anything, it just initializes // the library, use setupSubWindow() to display something. - RenderWindow(EGLNativeDisplayType native_display, int width, int height, bool use_thread, bool use_sub_window); + RenderWindow(EGLNativeDisplayType native_display, bool use_thread); // Destructor. This will automatically call removeSubWindow() is needed. ~RenderWindow(); diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 3d02370..e7cc739 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -78,7 +78,7 @@ void GLRendererServer::start() { // The width & height we supply here are the dimensions the internal framebuffer // will use. Making this static prevents us for now to resize the window we create // later for the actual display. - if (!initOpenGLRenderer(window_creator_->native_display(), width, height, true, server_addr, sizeof(server_addr), log_funcs, logger_write)) + if (!initOpenGLRenderer(window_creator_->native_display(), server_addr, sizeof(server_addr), log_funcs, logger_write)) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); socket_path_ = server_addr; From 72a7e2e4072bbf53bb5aeaeaf8a5f021a2afad2b Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 08:21:39 +0100 Subject: [PATCH 07/54] Enable hwcomposer support by default --- src/anbox/qemu/boot_properties_message_processor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index a1f9300..8b7e6f8 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -65,13 +65,11 @@ void BootPropertiesMessageProcessor::list_properties() { // Mark us as a device without telephony support (as we don't have a RIL) "ro.radio.noril=yes", - }; - if (utils::is_env_set("USE_HWCOMPOSER")) { // To let surfaceflinger load our hwcomposer implementation we specify // the correct subkey of the module here. - properties.push_back("ro.hardware.hwcomposer=anbox"); - } + "ro.hardware.hwcomposer=anbox" + }; for (const auto &prop : properties) { send_header(prop.length()); From c4a09f75afaea82e52042ef3da466ece939a1c84 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 08:36:03 +0100 Subject: [PATCH 08/54] Reset layer state when cycle is done --- .../android-emugl/host/libs/libOpenglRender/LayerManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index a90a455..891dbf5 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -89,4 +89,7 @@ void LayerManager::finish_cycle() { layers_.erase(iter); } } + + for (auto &layer : layers_) + layer.second.updated = false; } From f7be0f87476b2664fc04ee13084db22e0324b3f9 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 09:47:15 +0100 Subject: [PATCH 09/54] Reuse existing window when a layer with the same package already exists --- .../libs/libOpenglRender/LayerManager.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index 891dbf5..e5e65fb 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -19,6 +19,8 @@ #include +#include + namespace { std::string get_package_name(const std::string &name) { return name; @@ -37,6 +39,23 @@ bool is_layer_blacklisted(const std::string &name) { }; return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end(); } + +struct ActivityInfo { + ActivityInfo(const std::string &name) : + name(name) { + std::vector parts; + boost::split(parts, name, boost::is_any_of("/")); + if (parts.size() > 1) + package = parts[0]; + } + + std::string package; + std::string name; +}; + +bool from_same_package(const std::string &a, const std::string &b) { + return ActivityInfo(a).package == ActivityInfo(b).package; +} } std::shared_ptr LayerManager::get() { @@ -57,11 +76,11 @@ void LayerManager::post_layer(const LayerInfo &layer) { } FrameBufferWindow *window = nullptr; - auto l = layers_.find(layer.name); - if (l != layers_.end()) { - printf("Using existing layer '%s'\n", layer.name.c_str()); - window = l->second.window; - l->second.updated = true; + for (auto &l : layers_) { + if (l.first == layer.name || from_same_package(l.first, layer.name)) { + window = l.second.window; + l.second.updated = true; + } } else { printf("New layer '%s' {%d,%d,%d,%d}\n", layer.name.c_str()); From f2e39fb2f79325b0b1d1dcdc6200574a4f4ac0d0 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 18:05:19 +0100 Subject: [PATCH 10/54] Use correct order in rect definition --- external/android-emugl/host/libs/libOpenglRender/LayerManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.h b/external/android-emugl/host/libs/libOpenglRender/LayerManager.h index 52b9100..9e7bf5f 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.h +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.h @@ -27,8 +27,8 @@ #include "FrameBuffer.h" struct LayerRect { - int top; int left; + int top; int right; int bottom; }; From b05b8bae8bb1c26fca8e4d3b1ffa382e1dda09ab Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 8 Nov 2016 18:07:00 +0100 Subject: [PATCH 11/54] Implement quick&dirty approach to update window size and position --- .../host/libs/libOpenglRender/FrameBuffer.cpp | 7 ++++++ .../host/libs/libOpenglRender/FrameBuffer.h | 1 + .../libs/libOpenglRender/LayerManager.cpp | 22 ++++++++++++------- .../libs/libOpenglRender/NativeSubWindow.h | 3 +++ .../NativeSubWindow_delegate.cpp | 7 ++++++ src/anbox/ubuntu/window.cpp | 8 +++++++ src/anbox/ubuntu/window.h | 3 +++ src/anbox/ubuntu/window_creator.cpp | 9 ++++++++ src/anbox/ubuntu/window_creator.h | 1 + 9 files changed, 53 insertions(+), 8 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp index 0d47b68..fc304ac 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -497,6 +497,13 @@ FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height return window; } +void FrameBuffer::updateWindow(FrameBufferWindow *window, int x, int y, int width, int height) { + if (!window) + return; + + updateSubWindow(window->native_window, x, y, width, height); +} + void FrameBuffer::destroyWindow(FrameBufferWindow *window) { if (!window) return; diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h index 5eb9c60..1a4808d 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h @@ -79,6 +79,7 @@ public: static bool initialize(EGLNativeDisplayType nativeDisplay); FrameBufferWindow* createWindow(int x, int y, int width, int height); + void updateWindow(FrameBufferWindow *window, int x, int y, int width, int height); void destroyWindow(FrameBufferWindow *window); // Finalize the instance. diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index e5e65fb..ee62a72 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -82,13 +82,16 @@ void LayerManager::post_layer(const LayerInfo &layer) { l.second.updated = true; } } - else { - printf("New layer '%s' {%d,%d,%d,%d}\n", layer.name.c_str()); - window = FrameBuffer::getFB()->createWindow( - layer.display_frame.left, - layer.display_frame.top, - layer.display_frame.right, - layer.display_frame.bottom); + + auto width = layer.display_frame.right - layer.display_frame.left; + auto height = layer.display_frame.bottom - layer.display_frame.top; + + if (!window) { + auto buffer = FrameBuffer::getFB()->getColorBufferFromHandle(layer.buffer_handle); + + window = FrameBuffer::getFB()->createWindow(layer.display_frame.left, + layer.display_frame.top, + width, height); if (!window) { printf("Failed to create window for layer '%s'\n", layer.name.c_str()); return; @@ -97,7 +100,10 @@ void LayerManager::post_layer(const LayerInfo &layer) { } printf("%s: window %p buffer %d\n", __func__, window, layer.buffer_handle); - + FrameBuffer::getFB()->updateWindow(window, + layer.display_frame.left, + layer.display_frame.top, + width, height); FrameBuffer::getFB()->post(window, layer.buffer_handle); } diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h index 21a379c..bc3540c 100644 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h +++ b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h @@ -30,6 +30,7 @@ class SubWindowHandler { public: virtual ~SubWindowHandler() { } virtual EGLNativeWindowType create_window(int x, int y, int width, int height) = 0; + virtual void update_window(EGLNativeWindowType win, int x, int y, int width, int height) = 0; virtual void destroy_window(EGLNativeWindowType win) = 0; }; @@ -55,6 +56,8 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, int width, int height); +void updateSubWindow(EGLNativeWindowType win, int x, int y, int width, int height); + // Destroy a sub-window previously created through createSubWindow() above. void destroySubWindow(EGLNativeWindowType win); diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp index 1eab521..172e3da 100644 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp @@ -44,6 +44,13 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, return current_handler->create_window(x, y, width, height); } +void updateSubWindow(EGLNativeWindowType win, int x, int y, int width, int height) { + if (!current_handler) + return; + + return current_handler->update_window(win, x, y, width, height); +} + void destroySubWindow(EGLNativeWindowType win) { if (!current_handler) return; diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index e5c59c0..53b67ed 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -62,6 +62,14 @@ Window::~Window() { SDL_DestroyWindow(window_); } +void Window::resize(int width, int height) { + SDL_SetWindowSize(window_, width, height); +} + +int Window::update_position(int x, int y) { + SDL_SetWindowPosition(window_, x, y); +} + EGLNativeWindowType Window::native_window() const { return native_window_; } diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index 7911082..a0ef3f7 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -32,6 +32,9 @@ public: Window(int x, int y, int width, int height); ~Window(); + void resize(int width, int height); + int update_position(int x, int y); + EGLNativeWindowType native_window() const; private: diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/window_creator.cpp index 80522ae..6bd21f1 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/window_creator.cpp @@ -91,6 +91,15 @@ catch (std::exception &err) { return 0; } +void WindowCreator::update_window(EGLNativeWindowType win, int x, int y, int width, int height) { + auto iter = windows_.find(win); + if (iter == windows_.end()) + return; + + iter->second->resize(width, height); + iter->second->update_position(x, y); +} + void WindowCreator::destroy_window(EGLNativeWindowType win) { auto iter = windows_.find(win); if (iter == windows_.end()) diff --git a/src/anbox/ubuntu/window_creator.h b/src/anbox/ubuntu/window_creator.h index b8e827e..3f35394 100644 --- a/src/anbox/ubuntu/window_creator.h +++ b/src/anbox/ubuntu/window_creator.h @@ -39,6 +39,7 @@ public: ~WindowCreator(); EGLNativeWindowType create_window(int x, int y, int width, int height) override; + void update_window(EGLNativeWindowType win, int x, int y, int width, int height) override; void destroy_window(EGLNativeWindowType win) override; DisplayInfo display_info() const override; From 1aeedaf19983e3acf1beb75e11f85a74e49334f2 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 9 Nov 2016 09:40:25 +0100 Subject: [PATCH 12/54] Update GL viewport when window size changes --- .../host/libs/libOpenglRender/FrameBuffer.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp index fc304ac..0ccdf26 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -456,6 +456,9 @@ FrameBuffer::~FrameBuffer() { struct FrameBufferWindow { EGLNativeWindowType native_window = 0; EGLSurface surface = EGL_NO_SURFACE; + bool needViewportUpdate = false; + int width; + int height; }; FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height) { @@ -469,6 +472,8 @@ FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height auto window = new FrameBufferWindow; window->native_window = native_window; + window->width = width; + window->height = height; window->surface = s_egl.eglCreateWindowSurface( m_eglDisplay, m_eglConfig, window->native_window, nullptr); @@ -502,6 +507,9 @@ void FrameBuffer::updateWindow(FrameBufferWindow *window, int x, int y, int widt return; updateSubWindow(window->native_window, x, y, width, height); + window->width = width; + window->height = height; + window->needViewportUpdate = true; } void FrameBuffer::destroyWindow(FrameBufferWindow *window) { @@ -984,6 +992,12 @@ bool FrameBuffer::post(FrameBufferWindow *window, HandleType p_colorbuffer, bool if (!bindWindow_locked(window)) goto EXIT; + if (window->needViewportUpdate) { + s_gles2.glViewport(0, 0, window->width, window->height); + window->needViewportUpdate = false; + } + + s_gles2.glClearColor(0.0, 0.0, 1.0, 0.0); s_gles2.glClear(GL_COLOR_BUFFER_BIT); ret = (*c).second.cb->post(0.0f, 0, 0); From 905a1a9fb1913bc9fecf18eb285e680ebb2347ce Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 9 Nov 2016 09:42:57 +0100 Subject: [PATCH 13/54] Do not support translation/rotation for textures we render --- .../host/libs/libOpenglRender/ColorBuffer.cpp | 4 ++-- .../host/libs/libOpenglRender/TextureDraw.cpp | 24 ++++--------------- .../host/libs/libOpenglRender/TextureDraw.h | 7 ++---- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp index 95de4dd..6ca08d0 100644 --- a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -335,7 +335,7 @@ bool ColorBuffer::blitFromCurrentReadBuffer() s_gles2.glViewport(0, 0, m_width, m_height); // render m_blitTex - m_helper->getTextureDraw()->draw(m_blitTex, 0., 0, 0); + m_helper->getTextureDraw()->draw(m_blitTex); // Restore previous viewport. s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]); @@ -380,7 +380,7 @@ bool ColorBuffer::bindToRenderbuffer() { bool ColorBuffer::post(float rotation, float dx, float dy) { // NOTE: Do not call m_helper->setupContext() here! - return m_helper->getTextureDraw()->draw(m_resizer->update(m_tex), rotation, dx, dy); + return m_helper->getTextureDraw()->draw(m_resizer->update(m_tex)); } void ColorBuffer::readback(unsigned char* img) { diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp index 9e2a16a..f725ac6 100644 --- a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp @@ -57,20 +57,14 @@ GLuint createShader(GLint shaderType, const char* shaderText) { } // No scaling / projection since we want to fill the whole viewport with -// the texture, hence a trivial vertex shader that only supports clockwise -// rotation. +// the texture, hence a trivial vertex shader. const char kVertexShaderSource[] = "attribute vec4 position;\n" "attribute vec2 inCoord;\n" "varying lowp vec2 outCoord;\n" - "uniform float rotation;\n" - "uniform vec2 translation;\n" - "void main(void) {\n" - " float cs = cos(rotation);\n" - " float sn = sin(rotation);\n" - " gl_Position.x = position.x * cs + position.y * sn - translation.x;\n" - " gl_Position.y = position.y * cs - position.x * sn - translation.y;\n" + " gl_Position.x = position.x;\n" + " gl_Position.y = position.y;\n" " gl_Position.zw = position.zw;\n" " outCoord = inCoord;\n" "}\n"; @@ -142,15 +136,8 @@ TextureDraw::TextureDraw(EGLDisplay display) : mInCoordSlot = s_gles2.glGetAttribLocation(mProgram, "inCoord"); s_gles2.glEnableVertexAttribArray(mInCoordSlot); - mRotationSlot = s_gles2.glGetUniformLocation(mProgram, "rotation"); - mTranslationSlot = s_gles2.glGetUniformLocation(mProgram, "translation"); mTextureSlot = s_gles2.glGetUniformLocation(mProgram, "texture"); -#if 0 - printf("SLOTS position=%d inCoord=%d texture=%d rotation=%d\n", - mPositionSlot, mInCoordSlot, mTextureSlot, mRotationSlot); -#endif - // Create vertex and index buffers. s_gles2.glGenBuffers(1, &mVertexBuffer); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); @@ -165,7 +152,7 @@ TextureDraw::TextureDraw(EGLDisplay display) : GL_STATIC_DRAW); } -bool TextureDraw::draw(GLuint texture, float rotation, float dx, float dy) { +bool TextureDraw::draw(GLuint texture) { if (!mProgram) { ERR("%s: no program\n", __FUNCTION__); return false; @@ -220,9 +207,6 @@ bool TextureDraw::draw(GLuint texture, float rotation, float dx, float dy) { s_gles2.glBindTexture(GL_TEXTURE_2D, texture); s_gles2.glUniform1i(mTextureSlot, 0); - // setup the |rotation| uniform value. - s_gles2.glUniform1f(mRotationSlot, rotation * M_PI / 180.); - s_gles2.glUniform2f(mTranslationSlot, dx, dy); #if 1 // Validate program, just to be sure. diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.h b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.h index ee9371f..b8cc7c3 100644 --- a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.h +++ b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.h @@ -38,11 +38,8 @@ public: ~TextureDraw(); // Fill the current framebuffer with the content of |texture|, which must - // be the name of a GLES 2.x texture object. |rotationDegrees| is a - // clockwise rotation angle in degrees (clockwise in the GL Y-upwards - // coordinate space). |dx,dy| is the translation of the image towards the - // origin. - bool draw(GLuint texture, float rotationDegrees, float dx, float dy); + // be the name of a GLES 2.x texture object. + bool draw(GLuint texture); private: EGLDisplay mDisplay; From aee51246a55404d2b1e420f0ce213779681311f4 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 9 Nov 2016 12:06:57 +0100 Subject: [PATCH 14/54] Drop unneeded ifdef --- .../android-emugl/host/libs/libOpenglRender/TextureDraw.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp index f725ac6..d0f8dd7 100644 --- a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp @@ -207,8 +207,6 @@ bool TextureDraw::draw(GLuint texture) { s_gles2.glBindTexture(GL_TEXTURE_2D, texture); s_gles2.glUniform1i(mTextureSlot, 0); - -#if 1 // Validate program, just to be sure. s_gles2.glValidateProgram(mProgram); GLint validState = 0; @@ -220,7 +218,6 @@ bool TextureDraw::draw(GLuint texture) { ERR("%s: Could not run program: %s\n", __FUNCTION__, messages); return false; } -#endif // Do the rendering. s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); From 792f488cbc05e465c83aa17026c3122b6937dcec Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 9 Nov 2016 15:51:25 +0100 Subject: [PATCH 15/54] Drop use of not existing function --- .../android-emugl/host/libs/libOpenglRender/LayerManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index ee62a72..5a4cbd3 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -87,7 +87,6 @@ void LayerManager::post_layer(const LayerInfo &layer) { auto height = layer.display_frame.bottom - layer.display_frame.top; if (!window) { - auto buffer = FrameBuffer::getFB()->getColorBufferFromHandle(layer.buffer_handle); window = FrameBuffer::getFB()->createWindow(layer.display_frame.left, layer.display_frame.top, From 1d2c2814acc14cd3483e2dae78f4e90ac17a575b Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 9 Nov 2016 17:13:58 +0100 Subject: [PATCH 16/54] Bring back input support for the currently active window --- src/CMakeLists.txt | 1 + src/anbox/cmds/run.cpp | 2 +- src/anbox/ubuntu/keycode_converter.cpp | 284 +++++++++++++++++++++++++ src/anbox/ubuntu/keycode_converter.h | 38 ++++ src/anbox/ubuntu/window.cpp | 23 ++ src/anbox/ubuntu/window.h | 3 + src/anbox/ubuntu/window_creator.cpp | 103 ++++++++- src/anbox/ubuntu/window_creator.h | 7 +- 8 files changed, 454 insertions(+), 7 deletions(-) create mode 100644 src/anbox/ubuntu/keycode_converter.cpp create mode 100644 src/anbox/ubuntu/keycode_converter.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 75eeffe..f452f6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -119,6 +119,7 @@ set(SOURCES anbox/ubuntu/platform_api_skeleton.cpp anbox/ubuntu/window_creator.cpp anbox/ubuntu/window.cpp + anbox/ubuntu/keycode_converter.cpp anbox/dbus/interface.h anbox/dbus/skeleton/service.cpp diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 674ac9f..7fffe26 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -140,7 +140,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) // { qemud_connector->socket_file(), "/dev/qemud" }, { qemu_pipe_connector->socket_file(), "/dev/qemu_pipe" }, { bridge_connector->socket_file(), "/dev/anbox_bridge" }, - { "/dev/input", "/dev/input" }, + { config::host_input_device_path(), "/dev/input" }, { "/dev/binder", "/dev/binder" }, { "/dev/ashmem", "/dev/ashmem" }, }; diff --git a/src/anbox/ubuntu/keycode_converter.cpp b/src/anbox/ubuntu/keycode_converter.cpp new file mode 100644 index 0000000..ac2d46d --- /dev/null +++ b/src/anbox/ubuntu/keycode_converter.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/ubuntu/keycode_converter.h" + +#include + +namespace anbox { +namespace ubuntu { +std::uint16_t KeycodeConverter::convert(const SDL_Scancode &scan_code) { + for (std::uint16_t n = 0; n < code_map.size(); n++) { + if (code_map[n] == scan_code) + return n; + } + return KEY_RESERVED; +} + +const std::array KeycodeConverter::code_map = {{ + SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED 0 */ + SDL_SCANCODE_ESCAPE, /* KEY_ESC 1 */ + SDL_SCANCODE_1, /* KEY_1 2 */ + SDL_SCANCODE_2, /* KEY_2 3 */ + SDL_SCANCODE_3, /* KEY_3 4 */ + SDL_SCANCODE_4, /* KEY_4 5 */ + SDL_SCANCODE_5, /* KEY_5 6 */ + SDL_SCANCODE_6, /* KEY_6 7 */ + SDL_SCANCODE_7, /* KEY_7 8 */ + SDL_SCANCODE_8, /* KEY_8 9 */ + SDL_SCANCODE_9, /* KEY_9 10 */ + SDL_SCANCODE_0, /* KEY_0 11 */ + SDL_SCANCODE_MINUS, /* KEY_MINUS 12 */ + SDL_SCANCODE_EQUALS, /* KEY_EQUAL 13 */ + SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE 14 */ + SDL_SCANCODE_TAB, /* KEY_TAB 15 */ + SDL_SCANCODE_Q, /* KEY_Q 16 */ + SDL_SCANCODE_W, /* KEY_W 17 */ + SDL_SCANCODE_E, /* KEY_E 18 */ + SDL_SCANCODE_R, /* KEY_R 19 */ + SDL_SCANCODE_T, /* KEY_T 20 */ + SDL_SCANCODE_Y, /* KEY_Y 21 */ + SDL_SCANCODE_U, /* KEY_U 22 */ + SDL_SCANCODE_I, /* KEY_I 23 */ + SDL_SCANCODE_O, /* KEY_O 24 */ + SDL_SCANCODE_P, /* KEY_P 25 */ + SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE 26 */ + SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE 27 */ + SDL_SCANCODE_RETURN, /* KEY_ENTER 28 */ + SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL 29 */ + SDL_SCANCODE_A, /* KEY_A 30 */ + SDL_SCANCODE_S, /* KEY_S 31 */ + SDL_SCANCODE_D, /* KEY_D 32 */ + SDL_SCANCODE_F, /* KEY_F 33 */ + SDL_SCANCODE_G, /* KEY_G 34 */ + SDL_SCANCODE_H, /* KEY_H 35 */ + SDL_SCANCODE_J, /* KEY_J 36 */ + SDL_SCANCODE_K, /* KEY_K 37 */ + SDL_SCANCODE_L, /* KEY_L 38 */ + SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON 39 */ + SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE 40 */ + SDL_SCANCODE_GRAVE, /* KEY_GRAVE 41 */ + SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT 42 */ + SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH 43 */ + SDL_SCANCODE_Z, /* KEY_Z 44 */ + SDL_SCANCODE_X, /* KEY_X 45 */ + SDL_SCANCODE_C, /* KEY_C 46 */ + SDL_SCANCODE_V, /* KEY_V 47 */ + SDL_SCANCODE_B, /* KEY_B 48 */ + SDL_SCANCODE_N, /* KEY_N 49 */ + SDL_SCANCODE_M, /* KEY_M 50 */ + SDL_SCANCODE_COMMA, /* KEY_COMMA 51 */ + SDL_SCANCODE_PERIOD, /* KEY_DOT 52 */ + SDL_SCANCODE_SLASH, /* KEY_SLASH 53 */ + SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT 54 */ + SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK 55 */ + SDL_SCANCODE_LALT, /* KEY_LEFTALT 56 */ + SDL_SCANCODE_SPACE, /* KEY_SPACE 57 */ + SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK 58 */ + SDL_SCANCODE_F1, /* KEY_F1 59 */ + SDL_SCANCODE_F2, /* KEY_F2 60 */ + SDL_SCANCODE_F3, /* KEY_F3 61 */ + SDL_SCANCODE_F4, /* KEY_F4 62 */ + SDL_SCANCODE_F5, /* KEY_F5 63 */ + SDL_SCANCODE_F6, /* KEY_F6 64 */ + SDL_SCANCODE_F7, /* KEY_F7 65 */ + SDL_SCANCODE_F8, /* KEY_F8 66 */ + SDL_SCANCODE_F9, /* KEY_F9 67 */ + SDL_SCANCODE_F10, /* KEY_F10 68 */ + SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK 69 */ + SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK 70 */ + SDL_SCANCODE_KP_7, /* KEY_KP7 71 */ + SDL_SCANCODE_KP_8, /* KEY_KP8 72 */ + SDL_SCANCODE_KP_9, /* KEY_KP9 73 */ + SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS 74 */ + SDL_SCANCODE_KP_4, /* KEY_KP4 75 */ + SDL_SCANCODE_KP_5, /* KEY_KP5 76 */ + SDL_SCANCODE_KP_6, /* KEY_KP6 77 */ + SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS 78 */ + SDL_SCANCODE_KP_1, /* KEY_KP1 79 */ + SDL_SCANCODE_KP_2, /* KEY_KP2 80 */ + SDL_SCANCODE_KP_3, /* KEY_KP3 81 */ + SDL_SCANCODE_KP_0, /* KEY_KP0 82 */ + SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT 83 */ + SDL_SCANCODE_UNKNOWN, /* 84 */ + SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU 85 */ + SDL_SCANCODE_UNKNOWN, /* KEY_102ND 86 */ + SDL_SCANCODE_F11, /* KEY_F11 87 */ + SDL_SCANCODE_F12, /* KEY_F12 88 */ + SDL_SCANCODE_UNKNOWN, /* KEY_RO 89 */ + SDL_SCANCODE_LANG3, /* KEY_KATAKANA 90 */ + SDL_SCANCODE_LANG4, /* KEY_HIRAGANA 91 */ + SDL_SCANCODE_UNKNOWN, /* KEY_HENKAN 92 */ + SDL_SCANCODE_LANG3, /* KEY_KATAKANAHIRAGANA 93 */ + SDL_SCANCODE_UNKNOWN, /* KEY_MUHENKAN 94 */ + SDL_SCANCODE_KP_COMMA, /* KEY_KPJPCOMMA 95 */ + SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER 96 */ + SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL 97 */ + SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH 98 */ + SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ 99 */ + SDL_SCANCODE_RALT, /* KEY_RIGHTALT 100 */ + SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED 101 */ + SDL_SCANCODE_HOME, /* KEY_HOME 102 */ + SDL_SCANCODE_UP, /* KEY_UP 103 */ + SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP 104 */ + SDL_SCANCODE_LEFT, /* KEY_LEFT 105 */ + SDL_SCANCODE_RIGHT, /* KEY_RIGHT 106 */ + SDL_SCANCODE_END, /* KEY_END 107 */ + SDL_SCANCODE_DOWN, /* KEY_DOWN 108 */ + SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN 109 */ + SDL_SCANCODE_INSERT, /* KEY_INSERT 110 */ + SDL_SCANCODE_DELETE, /* KEY_DELETE 111 */ + SDL_SCANCODE_UNKNOWN, /* KEY_MACRO 112 */ + SDL_SCANCODE_MUTE, /* KEY_MUTE 113 */ + SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN 114 */ + SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP 115 */ + SDL_SCANCODE_POWER, /* KEY_POWER 116 SC System Power Down */ + SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL 117 */ + SDL_SCANCODE_KP_MINUS, /* KEY_KPPLUSMINUS 118 */ + SDL_SCANCODE_PAUSE, /* KEY_PAUSE 119 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SCALE 120 AL Compiz Scale (Expose) */ + SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA 121 */ + SDL_SCANCODE_LANG1, /* KEY_HANGEUL,KEY_HANGUEL 122 */ + SDL_SCANCODE_LANG2, /* KEY_HANJA 123 */ + SDL_SCANCODE_INTERNATIONAL3,/* KEY_YEN 124 */ + SDL_SCANCODE_LGUI, /* KEY_LEFTMETA 125 */ + SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA 126 */ + SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE 127 */ + SDL_SCANCODE_STOP, /* KEY_STOP 128 AC Stop */ + SDL_SCANCODE_AGAIN, /* KEY_AGAIN 129 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PROPS 130 AC Properties */ + SDL_SCANCODE_UNDO, /* KEY_UNDO 131 AC Undo */ + SDL_SCANCODE_UNKNOWN, /* KEY_FRONT 132 */ + SDL_SCANCODE_COPY, /* KEY_COPY 133 AC Copy */ + SDL_SCANCODE_UNKNOWN, /* KEY_OPEN 134 AC Open */ + SDL_SCANCODE_PASTE, /* KEY_PASTE 135 AC Paste */ + SDL_SCANCODE_FIND, /* KEY_FIND 136 AC Search */ + SDL_SCANCODE_CUT, /* KEY_CUT 137 AC Cut */ + SDL_SCANCODE_HELP, /* KEY_HELP 138 AL Integrated Help Center */ + SDL_SCANCODE_MENU, /* KEY_MENU 139 Menu (show menu) */ + SDL_SCANCODE_CALCULATOR, /* KEY_CALC 140 AL Calculator */ + SDL_SCANCODE_UNKNOWN, /* KEY_SETUP 141 */ + SDL_SCANCODE_SLEEP, /* KEY_SLEEP 142 SC System Sleep */ + SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP 143 System Wake Up */ + SDL_SCANCODE_UNKNOWN, /* KEY_FILE 144 AL Local Machine Browser */ + SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE 145 */ + SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE 146 */ + SDL_SCANCODE_UNKNOWN, /* KEY_XFER 147 */ + SDL_SCANCODE_APP1, /* KEY_PROG1 148 */ + SDL_SCANCODE_APP1, /* KEY_PROG2 149 */ + SDL_SCANCODE_WWW, /* KEY_WWW 150 AL Internet Browser */ + SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS 151 */ + SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE,KEY_SCREENLOCK 152 AL Terminal Lock/Screensaver */ + SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION 153 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS 154 */ + SDL_SCANCODE_MAIL, /* KEY_MAIL 155 */ + SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS 156 AC Bookmarks */ + SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER 157 */ + SDL_SCANCODE_AC_BACK, /* KEY_BACK 158 AC Back */ + SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD 159 AC Forward */ + SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD 160 */ + SDL_SCANCODE_EJECT, /* KEY_EJECTCD 161 */ + SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD 162 */ + SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG 163 */ + SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE 164 */ + SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG 165 */ + SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD 166 */ + SDL_SCANCODE_UNKNOWN, /* KEY_RECORD 167 */ + SDL_SCANCODE_UNKNOWN, /* KEY_REWIND 168 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PHONE 169 Media Select Telephone */ + SDL_SCANCODE_UNKNOWN, /* KEY_ISO 170 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG 171 AL Consumer Control Configuration */ + SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE 172 AC Home */ + SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH 173 AC Refresh */ + SDL_SCANCODE_UNKNOWN, /* KEY_EXIT 174 AC Exit */ + SDL_SCANCODE_UNKNOWN, /* KEY_MOVE 175 */ + SDL_SCANCODE_UNKNOWN, /* KEY_EDIT 176 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP 177 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN 178 */ + SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN 179 */ + SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN 180 */ + SDL_SCANCODE_UNKNOWN, /* KEY_NEW 181 AC New */ + SDL_SCANCODE_AGAIN, /* KEY_REDO 182 AC Redo/Repeat */ + SDL_SCANCODE_F13, /* KEY_F13 183 */ + SDL_SCANCODE_F14, /* KEY_F14 184 */ + SDL_SCANCODE_F15, /* KEY_F15 185 */ + SDL_SCANCODE_F16, /* KEY_F16 186 */ + SDL_SCANCODE_F17, /* KEY_F17 187 */ + SDL_SCANCODE_F18, /* KEY_F18 188 */ + SDL_SCANCODE_F19, /* KEY_F19 189 */ + SDL_SCANCODE_F20, /* KEY_F20 190 */ + SDL_SCANCODE_F21, /* KEY_F21 191 */ + SDL_SCANCODE_F22, /* KEY_F22 192 */ + SDL_SCANCODE_F23, /* KEY_F23 193 */ + SDL_SCANCODE_F24, /* KEY_F24 194 */ + SDL_SCANCODE_UNKNOWN, /* 195 */ + SDL_SCANCODE_UNKNOWN, /* 196 */ + SDL_SCANCODE_UNKNOWN, /* 197 */ + SDL_SCANCODE_UNKNOWN, /* 198 */ + SDL_SCANCODE_UNKNOWN, /* 199 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD 200 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD 201 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 202 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 203 */ + SDL_SCANCODE_UNKNOWN, /* KEY_DASHBOARD 204 AL Dashboard */ + SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND 205 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE 206 AC Close */ + SDL_SCANCODE_UNKNOWN, /* KEY_PLAY 207 */ + SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD 208 */ + SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST 209 */ + SDL_SCANCODE_UNKNOWN, /* KEY_PRINT 210 AC Print */ + SDL_SCANCODE_UNKNOWN, /* KEY_HP 211 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA 212 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SOUND 213 */ + SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION 214 */ + SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL 215 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CHAT 216 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SEARCH 217 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT 218 */ + SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE 219 AL Checkbook/Finance */ + SDL_SCANCODE_UNKNOWN, /* KEY_SPORT 220 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SHOP 221 */ + SDL_SCANCODE_UNKNOWN, /* KEY_ALTERASE 222 */ + SDL_SCANCODE_UNKNOWN, /* KEY_CANCEL 223 AC Cancel */ + SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSDOWN 224 */ + SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSUP 225 */ + SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA 226 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */ + SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMTOGGLE 228 */ + SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMDOWN 229 */ + SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMUP 230 */ + SDL_SCANCODE_UNKNOWN, /* KEY_SEND 231 AC Send */ + SDL_SCANCODE_UNKNOWN, /* KEY_REPLY 232 AC Reply */ + SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL 233 AC Forward Msg */ + SDL_SCANCODE_UNKNOWN, /* KEY_SAVE 234 AC Save */ + SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS 235 */ + SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY 236 */ + SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH 237 */ + SDL_SCANCODE_UNKNOWN, /* KEY_WLAN 238 */ + SDL_SCANCODE_UNKNOWN, /* KEY_UWB 239 */ + SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN 240 */ + SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT 241 drive next video source */ + SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV 242 drive previous video source */ + SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE 243 brightness up, after max is min */ + SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */ + SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF 245 display device to off state */ + SDL_SCANCODE_UNKNOWN, /* KEY_WIMAX 246 */ + SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL 247 Key that controls all radios */ + SDL_SCANCODE_UNKNOWN /* KEY_MICMUTE 248 Mute / unmute the microphone */ +}}; +} // namespace ubuntu +} // namespace anbox diff --git a/src/anbox/ubuntu/keycode_converter.h b/src/anbox/ubuntu/keycode_converter.h new file mode 100644 index 0000000..ae7d2df --- /dev/null +++ b/src/anbox/ubuntu/keycode_converter.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_UBUNTU_KEYCODE_CONVERTER_H_ +#define ANBOX_UBUNTU_KEYCODE_CONVERTER_H_ + +#include + +#include + +#include + +namespace anbox { +namespace ubuntu { +class KeycodeConverter { +public: + static std::uint16_t convert(const SDL_Scancode &scan_code); +private: + static const std::array code_map; +}; +} // namespace ubuntu +} // namespace anbox + +#endif diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index 53b67ed..1e68f3e 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -70,8 +70,31 @@ int Window::update_position(int x, int y) { SDL_SetWindowPosition(window_, x, y); } +void Window::process_event(const SDL_Event &event) { + switch (event.window.type) { + case SDL_WINDOWEVENT_FOCUS_GAINED: + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + break; + case SDL_WINDOWEVENT_RESIZED: + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + break; + case SDL_WINDOWEVENT_MOVED: + break; + case SDL_WINDOWEVENT_SHOWN: + break; + case SDL_WINDOWEVENT_HIDDEN: + break; + } +} + EGLNativeWindowType Window::native_window() const { return native_window_; } + +std::uint32_t Window::id() const { + return SDL_GetWindowID(window_); +} } // namespace bridge } // namespace anbox diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index a0ef3f7..52fcb4a 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -35,7 +35,10 @@ public: void resize(int width, int height); int update_position(int x, int y); + void process_event(const SDL_Event &event); + EGLNativeWindowType native_window() const; + std::uint32_t id() const; private: EGLNativeDisplayType native_display_; diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/window_creator.cpp index 6bd21f1..2d2dd1d 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/window_creator.cpp @@ -17,6 +17,7 @@ #include "anbox/ubuntu/window_creator.h" #include "anbox/ubuntu/window.h" +#include "anbox/ubuntu/keycode_converter.h" #include "anbox/input/manager.h" #include "anbox/input/device.h" #include "anbox/logger.h" @@ -46,6 +47,28 @@ WindowCreator::WindowCreator(const std::shared_ptr &input_manage display_info_.horizontal_resolution = display_mode.w; display_info_.vertical_resolution = display_mode.h; } + + pointer_ = input_manager->create_device(); + pointer_->set_name("anbox-pointer"); + pointer_->set_driver_version(1); + pointer_->set_input_id({ BUS_VIRTUAL, 2, 2, 2 }); + pointer_->set_physical_location("none"); + pointer_->set_key_bit(BTN_MOUSE); + // NOTE: We don't use REL_X/REL_Y in reality but have to specify them here + // to allow InputFlinger to detect we're a cursor device. + pointer_->set_rel_bit(REL_X); + pointer_->set_rel_bit(REL_Y); + pointer_->set_rel_bit(REL_HWHEEL); + pointer_->set_rel_bit(REL_WHEEL); + pointer_->set_prop_bit(INPUT_PROP_POINTER); + + keyboard_ = input_manager->create_device(); + keyboard_->set_name("anbox-keyboard"); + keyboard_->set_driver_version(1); + keyboard_->set_input_id({ BUS_VIRTUAL, 3, 3, 3 }); + keyboard_->set_physical_location("none"); + keyboard_->set_key_bit(BTN_MISC); + keyboard_->set_key_bit(KEY_OK); } WindowCreator::~WindowCreator() { @@ -53,9 +76,6 @@ WindowCreator::~WindowCreator() { event_thread_.join(); } -void WindowCreator::process_window_event(const SDL_Event &event) { -} - void WindowCreator::process_events() { event_thread_running_ = true; @@ -69,13 +89,88 @@ void WindowCreator::process_events() { ::kill(getpid(), SIGTERM); break; case SDL_WINDOWEVENT: - process_window_event(event); + for (auto &iter : windows_) { + if (iter.second->id() == event.window.windowID) { + iter.second->process_event(event); + break; + } + } + break; + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + case SDL_KEYDOWN: + case SDL_KEYUP: + process_input_event(event); break; } } } } +void WindowCreator::process_input_event(const SDL_Event &event) { + std::vector mouse_events; + std::vector keyboard_events; + + std::int32_t x = 0; + std::int32_t y = 0; + SDL_Window *window = nullptr; + + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: + mouse_events.push_back({ EV_KEY, BTN_LEFT, 1 }); + mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); + break; + case SDL_MOUSEBUTTONUP: + mouse_events.push_back({ EV_KEY, BTN_LEFT, 0 }); + mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); + break; + case SDL_MOUSEMOTION: + // As we get only absolute coordindates relative to our window we have to + // calculate the correct position based on the current focused window + window = SDL_GetWindowFromID(event.window.windowID); + if (!window) + break; + + SDL_GetWindowPosition(window, &x, &y); + x += event.motion.x; + y += event.motion.y; + + // NOTE: Sending relative move events doesn't really work and we have changes + // in libinputflinger to take ABS_X/ABS_Y instead for absolute position events. + mouse_events.push_back({ EV_ABS, ABS_X, x }); + mouse_events.push_back({ EV_ABS, ABS_Y, y }); + mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); + break; + case SDL_MOUSEWHEEL: + mouse_events.push_back({ EV_REL, REL_WHEEL, static_cast(event.wheel.y) }); + break; + case SDL_KEYDOWN: { + const auto code = KeycodeConverter::convert(event.key.keysym.scancode); + if (code == KEY_RESERVED) + break; + keyboard_events.push_back({ EV_KEY, code, 1 }); + break; + } + case SDL_KEYUP: { + const auto code = KeycodeConverter::convert(event.key.keysym.scancode); + if (code == KEY_RESERVED) + break; + keyboard_events.push_back({ EV_KEY, code, 0 }); + break; + } + default: + break; + } + + if (mouse_events.size() > 0) + pointer_->send_events(mouse_events); + + if (keyboard_events.size() > 0) + keyboard_->send_events(keyboard_events); +} + EGLNativeWindowType WindowCreator::create_window(int x, int y, int width, int height) try { auto window = std::make_shared(x, y, width, height); diff --git a/src/anbox/ubuntu/window_creator.h b/src/anbox/ubuntu/window_creator.h index 3f35394..4117aea 100644 --- a/src/anbox/ubuntu/window_creator.h +++ b/src/anbox/ubuntu/window_creator.h @@ -29,6 +29,7 @@ namespace anbox { namespace input { class Device; +class Manager; } // namespace input namespace ubuntu { class MirDisplayConnection; @@ -47,7 +48,7 @@ public: private: void process_events(); - void process_window_event(const SDL_Event &event); + void process_input_event(const SDL_Event &event); std::shared_ptr input_manager_; std::map> windows_; @@ -55,8 +56,10 @@ private: std::thread event_thread_; bool event_thread_running_; graphics::WindowCreator::DisplayInfo display_info_; + std::shared_ptr pointer_; + std::shared_ptr keyboard_; }; -} // namespace bridge +} // namespace ubuntu } // namespace anbox #endif From 9ae788ceecdcc386fa0b290cf7d351bc4a30654f Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Thu, 10 Nov 2016 12:24:47 +0100 Subject: [PATCH 17/54] Get rid of the old app manager which we're not going to use --- Android.mk | 2 -- android/app_manager/.idea/vcs.xml | 6 ---- android/app_manager/Android.mk | 15 -------- android/app_manager/AndroidManifest.xml | 14 -------- android/app_manager/res/values/strings.xml | 3 -- .../anbox/app_manager/AppManagerService.java | 21 ----------- .../org/anbox/app_manager/IAppManager.aidl | 22 ------------ .../anbox/app_manager/MainApplication.java | 35 ------------------- 8 files changed, 118 deletions(-) delete mode 100644 android/app_manager/.idea/vcs.xml delete mode 100644 android/app_manager/Android.mk delete mode 100644 android/app_manager/AndroidManifest.xml delete mode 100644 android/app_manager/res/values/strings.xml delete mode 100644 android/app_manager/src/org/anbox/app_manager/AppManagerService.java delete mode 100644 android/app_manager/src/org/anbox/app_manager/IAppManager.aidl delete mode 100644 android/app_manager/src/org/anbox/app_manager/MainApplication.java diff --git a/Android.mk b/Android.mk index a03d70a..cfb848a 100644 --- a/Android.mk +++ b/Android.mk @@ -97,5 +97,3 @@ include $(BUILD_SHARED_LIBRARY) # Include the Android.mk files below will override LOCAL_PATH so we # have to take a copy of it here. TMP_PATH := $(LOCAL_PATH) - -include $(TMP_PATH)/android/app_manager/Android.mk diff --git a/android/app_manager/.idea/vcs.xml b/android/app_manager/.idea/vcs.xml deleted file mode 100644 index b2bdec2..0000000 --- a/android/app_manager/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/android/app_manager/Android.mk b/android/app_manager/Android.mk deleted file mode 100644 index 8b1a3b8..0000000 --- a/android/app_manager/Android.mk +++ /dev/null @@ -1,15 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_PACKAGE_NAME := AnboxAppManager -LOCAL_CERTIFICATE := platform -LOCAL_PRIVILEGED_MODULE := true -# We kick out several core packages here which would -# otherwise put up the base UI we don't want. -LOCAL_OVERRIDES_PACKAGES := \ - Home \ - Launcher2 \ - Launcher3 -include $(BUILD_PACKAGE) diff --git a/android/app_manager/AndroidManifest.xml b/android/app_manager/AndroidManifest.xml deleted file mode 100644 index db222a5..0000000 --- a/android/app_manager/AndroidManifest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/android/app_manager/res/values/strings.xml b/android/app_manager/res/values/strings.xml deleted file mode 100644 index 8926490..0000000 --- a/android/app_manager/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Anbox Application Manager - diff --git a/android/app_manager/src/org/anbox/app_manager/AppManagerService.java b/android/app_manager/src/org/anbox/app_manager/AppManagerService.java deleted file mode 100644 index df500dd..0000000 --- a/android/app_manager/src/org/anbox/app_manager/AppManagerService.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -package org.anbox.app_manager; - -public class AppManagerService { -} diff --git a/android/app_manager/src/org/anbox/app_manager/IAppManager.aidl b/android/app_manager/src/org/anbox/app_manager/IAppManager.aidl deleted file mode 100644 index 04fd299..0000000 --- a/android/app_manager/src/org/anbox/app_manager/IAppManager.aidl +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -package org.anbox.app_manager; - -interface IAppManager { - void launch(string name); -} diff --git a/android/app_manager/src/org/anbox/app_manager/MainApplication.java b/android/app_manager/src/org/anbox/app_manager/MainApplication.java deleted file mode 100644 index ca0f6b3..0000000 --- a/android/app_manager/src/org/anbox/app_manager/MainApplication.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -package org.anbox.app_manager; - -import java.lang.reflect.Method; - -import android.app.Application; -import android.os.IBinder; - -public class MainApplication extends Application { - public void startServices() { - Method addService; - try { - addService = Class.forName("android.os.ServiceManager").getMethod("addService", String.class, IBinder.class); - } - catch (Exception e) { - e.printStackTrace(); - } - } -} \ No newline at end of file From e1a5d5f5c78adb7d5e19ca42916f7025ab1b3920 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Thu, 10 Nov 2016 12:29:01 +0100 Subject: [PATCH 18/54] Exclude a few Android packages which we don't need --- Android.mk | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Android.mk b/Android.mk index cfb848a..7da57f7 100644 --- a/Android.mk +++ b/Android.mk @@ -59,6 +59,15 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_CFLAGS := \ -fexceptions \ -std=c++1y +# Drop a few packages we don't want in our images as they +# are not needed (e.g. a home/launcher application as we +# don't have this concept). +LOCAL_OVERRIDES_PACKAGES := \ + Launcher \ + Launcher2 \ + LatinIME \ + Home \ + QuickSearchBox include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) From ea90344cfd3739842f44e75323ff379a41f64176 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Thu, 10 Nov 2016 18:01:27 +0100 Subject: [PATCH 19/54] Drop unnecessary debug statements --- .../android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp | 2 -- .../android-emugl/host/libs/libOpenglRender/LayerManager.cpp | 5 +---- .../host/libs/libOpenglRender/RenderControl.cpp | 5 ----- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp index 0ccdf26..64b8323 100644 --- a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -976,8 +976,6 @@ bool FrameBuffer::post(FrameBufferWindow *window, HandleType p_colorbuffer, bool if (!window) return false; - printf("%s window %p\n", __func__, window); - if (needLock) m_lock.lock(); diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index 5a4cbd3..e6d15ce 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -70,10 +70,8 @@ LayerManager::~LayerManager() { } void LayerManager::post_layer(const LayerInfo &layer) { - if (is_layer_blacklisted(layer.name)) { - printf("Ignoring blacklisted layer '%s'\n", layer.name.c_str()); + if (is_layer_blacklisted(layer.name)) return; - } FrameBufferWindow *window = nullptr; for (auto &l : layers_) { @@ -98,7 +96,6 @@ void LayerManager::post_layer(const LayerInfo &layer) { layers_.insert({ layer.name, Layer{window, true}}); } - printf("%s: window %p buffer %d\n", __func__, window, layer.buffer_handle); FrameBuffer::getFB()->updateWindow(window, layer.display_frame.left, layer.display_frame.top, diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp index 618f454..942e7a4 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp @@ -432,11 +432,6 @@ void rcPostLayer(const char *name, uint32_t color_buffer, int32_t displayFrameLeft, int32_t displayFrameTop, int32_t displayFrameRight, int32_t displayFrameBottom) { - printf("%s: name='%s' color_buffer=%d {%d,%d,%d,%d}, {%d,%d,%d,%d}\n", - __func__, name, color_buffer, - sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom, - displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom); - LayerRect source_crop{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}; LayerRect display_frame{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom}; LayerManager::get()->post_layer({name, source_crop, display_frame, color_buffer}); From 8b6510e11361709ab82499270226e06ff330874a Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:04:52 +0100 Subject: [PATCH 20/54] hwcomposer: disable verbose logging in info level --- android/hwcomposer/hwcomposer.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/android/hwcomposer/hwcomposer.cpp b/android/hwcomposer/hwcomposer.cpp index 38d8c4a..f6c7f6d 100644 --- a/android/hwcomposer/hwcomposer.cpp +++ b/android/hwcomposer/hwcomposer.cpp @@ -72,7 +72,7 @@ struct HwcContext { }; static void dump_layer(hwc_layer_1_t const* l) { - ALOGI("\tname='%s', type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", + ALOGD("\tname='%s', type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", l->name, l->compositionType, l->flags, l->handle, l->transform, l->blending, l->sourceCrop.left, l->sourceCrop.top, @@ -88,7 +88,7 @@ static int hwc_prepare(hwc_composer_device_1_t* dev, size_t numDisplays, hwc_display_contents_1_t** displays) { auto context = reinterpret_cast(dev); - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); if (displays == NULL || displays[0] == NULL) return -EINVAL; @@ -170,7 +170,7 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, hwc_display_contents_1_t** displays) { auto context = reinterpret_cast(dev); - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); if (displays == NULL || displays[0] == NULL) return -EFAULT; @@ -213,30 +213,30 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, static int hwc_event_control(hwc_composer_device_1* dev, int disp, int event, int enabled) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); return -EFAULT; } static void hwc_register_procs(hwc_composer_device_1* dev, hwc_procs_t const* procs) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); } static int hwc_blank(hwc_composer_device_1* dev, int disp, int blank) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); return 0; } static int hwc_query(hwc_composer_device_1* dev, int what, int* value) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); return 0; } static int hwc_device_close(hw_device_t* dev) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); auto context = reinterpret_cast(dev); delete context; return 0; @@ -244,7 +244,7 @@ static int hwc_device_close(hw_device_t* dev) { static int hwc_get_display_configs(hwc_composer_device_1* dev, int disp, uint32_t* configs, size_t* numConfigs) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); if (disp != 0) { return -EINVAL; @@ -263,7 +263,7 @@ static int hwc_get_display_attributes(hwc_composer_device_1* dev, int disp, uint32_t config, const uint32_t* attributes, int32_t* values) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); if (disp != 0 || config != 0) { return -EINVAL; @@ -298,7 +298,7 @@ static int hwc_get_display_attributes(hwc_composer_device_1* dev, } static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { - ALOGI("%s", __PRETTY_FUNCTION__); + ALOGD("%s", __PRETTY_FUNCTION__); if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) return -EINVAL; From c63088d47f3375a88f57c90b480a8aa88326c509 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:05:06 +0100 Subject: [PATCH 21/54] Also send relative mouse move events --- src/anbox/ubuntu/window_creator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/window_creator.cpp index 2d2dd1d..cad4160 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/window_creator.cpp @@ -141,6 +141,11 @@ void WindowCreator::process_input_event(const SDL_Event &event) { // in libinputflinger to take ABS_X/ABS_Y instead for absolute position events. mouse_events.push_back({ EV_ABS, ABS_X, x }); mouse_events.push_back({ EV_ABS, ABS_Y, y }); + // We're sending relative position updates here too but they will be only used + // by the Android side EventHub/InputReader to determine if the cursor was + // moved. They are not used to find out the exact position. + mouse_events.push_back({ EV_REL, REL_X, event.motion.xrel }); + mouse_events.push_back({ EV_REL, REL_Y, event.motion.yrel }); mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 }); break; case SDL_MOUSEWHEEL: From a39c1b2bd256fb97d65b809ca8d89875a2597724 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:07:09 +0100 Subject: [PATCH 22/54] hwcomposer: and disable debug level logging by default --- android/hwcomposer/hwcomposer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/hwcomposer/hwcomposer.cpp b/android/hwcomposer/hwcomposer.cpp index f6c7f6d..3ab4d23 100644 --- a/android/hwcomposer/hwcomposer.cpp +++ b/android/hwcomposer/hwcomposer.cpp @@ -23,7 +23,7 @@ #include #include -#define LOG_NDEBUG 0 +#define LOG_NDEBUG 1 #include #include "HostConnection.h" From 6ee8734cf380de44a5b3081d8ec7ae01fb121ca3 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:41:10 +0100 Subject: [PATCH 23/54] Add first stub methods to send window status updates from Android to host --- android/service/platform_api_stub.cpp | 49 ++++++++++++++++++- android/service/platform_api_stub.h | 6 +++ android/service/platform_service.cpp | 10 ++++ android/service/platform_service.h | 4 +- .../service/platform_service_interface.cpp | 20 +++++++- android/service/platform_service_interface.h | 6 +++ src/anbox/bridge/platform_api_skeleton.h | 6 ++- .../bridge/platform_message_processor.cpp | 8 +-- src/anbox/ubuntu/platform_api_skeleton.cpp | 31 ++++++++---- src/anbox/ubuntu/platform_api_skeleton.h | 8 ++- 10 files changed, 130 insertions(+), 18 deletions(-) diff --git a/android/service/platform_api_stub.cpp b/android/service/platform_api_stub.cpp index 373df0f..289c859 100644 --- a/android/service/platform_api_stub.cpp +++ b/android/service/platform_api_stub.cpp @@ -52,7 +52,54 @@ void PlatformApiStub::boot_finished() { } void PlatformApiStub::handle_boot_finished_response(Request*) { - ALOGI("handle_boot_finished_response"); boot_finished_wait_handle_.result_received(); } + +void PlatformApiStub::update_window_state() { + auto c = std::make_shared>(); + + ALOGI("Updating window state"); + + { + std::lock_guard lock(mutex_); + update_window_state_wait_handle_.expect_result(); + } + + protobuf::rpc::Void message; + + rpc_channel_->call_method( + "update_window_state", + &message, c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiStub::handle_update_window_state_response, c.get())); + + update_window_state_wait_handle_.wait_for_all(); +} + +void PlatformApiStub::handle_update_window_state_response(Request *request) { + update_window_state_wait_handle_.result_received(); +} + +void PlatformApiStub::remove_window() { + auto c = std::make_shared>(); + + ALOGI("Remove window"); + + { + std::lock_guard lock(mutex_); + remove_window_wait_handle_.expect_result(); + } + + protobuf::rpc::Void message; + + rpc_channel_->call_method( + "remove_window", + &message, c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiStub::handle_remove_window_response, c.get())); + + remove_window_wait_handle_.wait_for_all(); +} + +void PlatformApiStub::handle_remove_window_response(Request *request) { + update_window_state_wait_handle_.result_received(); +} } // namespace anbox diff --git a/android/service/platform_api_stub.h b/android/service/platform_api_stub.h index a18bc55..02271ba 100644 --- a/android/service/platform_api_stub.h +++ b/android/service/platform_api_stub.h @@ -36,6 +36,8 @@ public: PlatformApiStub(const std::shared_ptr &rpc_channel); void boot_finished(); + void update_window_state(); + void remove_window(); private: template @@ -46,9 +48,13 @@ private: }; void handle_boot_finished_response(Request *request); + void handle_update_window_state_response(Request *request); + void handle_remove_window_response(Request *request); mutable std::mutex mutex_; common::WaitHandle boot_finished_wait_handle_; + common::WaitHandle update_window_state_wait_handle_; + common::WaitHandle remove_window_wait_handle_; std::shared_ptr rpc_channel_; }; diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp index 78d45d0..858708f 100644 --- a/android/service/platform_service.cpp +++ b/android/service/platform_service.cpp @@ -33,4 +33,14 @@ status_t PlatformService::boot_finished() { platform_api_stub_->boot_finished(); return OK; } + +status_t PlatformService::update_window_state() { + platform_api_stub_->update_window_state(); + return OK; +} + +status_t PlatformService::remove_window() { + platform_api_stub_->remove_window(); + return OK; +} } // namespace android diff --git a/android/service/platform_service.h b/android/service/platform_service.h index 6fff224..cf07a17 100644 --- a/android/service/platform_service.h +++ b/android/service/platform_service.h @@ -29,11 +29,13 @@ class PlatformApiStub; namespace android { class PlatformService : public BnPlatformService { public: - static const char* service_name() { return "anbox.PlatformService"; } + static const char* service_name() { return "org.anbox.PlatformService"; } PlatformService(const std::shared_ptr &platform_api_stub); status_t boot_finished() override; + status_t update_window_state() override; + status_t remove_window() override; private: std::shared_ptr platform_api_stub_; diff --git a/android/service/platform_service_interface.cpp b/android/service/platform_service_interface.cpp index f523738..14e83cd 100644 --- a/android/service/platform_service_interface.cpp +++ b/android/service/platform_service_interface.cpp @@ -28,7 +28,19 @@ status_t BpPlatformService::boot_finished() { return remote()->transact(IPlatformService::BOOT_FINISHED, data, &reply); } -IMPLEMENT_META_INTERFACE(PlatformService, "anbox.IPlatformService"); +status_t BpPlatformService::update_window_state() { + Parcel data, reply; + data.writeInterfaceToken(IPlatformService::getInterfaceDescriptor()); + return remote()->transact(IPlatformService::UPDATE_WINDOW_STATE, data, &reply); +} + +status_t BpPlatformService::remove_window() { + Parcel data, reply; + data.writeInterfaceToken(IPlatformService::getInterfaceDescriptor()); + return remote()->transact(IPlatformService::REMOVE_WINDOW, data, &reply); +} + +IMPLEMENT_META_INTERFACE(PlatformService, "org.anbox.IPlatformService"); status_t BnPlatformService::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { @@ -36,6 +48,12 @@ status_t BnPlatformService::onTransact(uint32_t code, const Parcel &data, case BOOT_FINISHED: CHECK_INTERFACE(IPlatformService, data, reply); return boot_finished(); + case UPDATE_WINDOW_STATE: + CHECK_INTERFACE(IPlatformService, data, reply); + return update_window_state(); + case REMOVE_WINDOW: + CHECK_INTERFACE(IPlatformService, data, reply); + return remove_window(); default: break; } diff --git a/android/service/platform_service_interface.h b/android/service/platform_service_interface.h index 0a6c75a..343354e 100644 --- a/android/service/platform_service_interface.h +++ b/android/service/platform_service_interface.h @@ -34,9 +34,13 @@ public: enum { BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, + UPDATE_WINDOW_STATE = IBinder::FIRST_CALL_TRANSACTION + 1, + REMOVE_WINDOW = IBinder::FIRST_CALL_TRANSACTION + 2, }; virtual status_t boot_finished() = 0; + virtual status_t update_window_state() = 0; + virtual status_t remove_window() = 0; }; class BpPlatformService : public BpInterface { @@ -44,6 +48,8 @@ public: BpPlatformService(const sp &binder); status_t boot_finished() override; + status_t update_window_state() override; + status_t remove_window() override; }; class BnPlatformService : public BnInterface { diff --git a/src/anbox/bridge/platform_api_skeleton.h b/src/anbox/bridge/platform_api_skeleton.h index aafe417..b07c5d6 100644 --- a/src/anbox/bridge/platform_api_skeleton.h +++ b/src/anbox/bridge/platform_api_skeleton.h @@ -48,10 +48,14 @@ public: anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) = 0; - virtual void handle_notification(anbox::protobuf::bridge::Notification const *request, + virtual void update_window_state(anbox::protobuf::rpc::Void const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) = 0; + virtual void remove_window(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) = 0; + private: std::shared_ptr pending_calls_; }; diff --git a/src/anbox/bridge/platform_message_processor.cpp b/src/anbox/bridge/platform_message_processor.cpp index 599a3cb..bfe7e42 100644 --- a/src/anbox/bridge/platform_message_processor.cpp +++ b/src/anbox/bridge/platform_message_processor.cpp @@ -34,10 +34,12 @@ PlatformMessageProcessor::~PlatformMessageProcessor() { } void PlatformMessageProcessor::dispatch(rpc::Invocation const& invocation) { - if (invocation.method_name() == "handle_notification") - invoke(this, server_.get(), &PlatformApiSkeleton::handle_notification, invocation); - else if (invocation.method_name() == "boot_finished") + if (invocation.method_name() == "boot_finished") invoke(this, server_.get(), &PlatformApiSkeleton::boot_finished, invocation); + else if (invocation.method_name() == "update_window_state") + invoke(this, server_.get(), &PlatformApiSkeleton::update_window_state, invocation); + else if (invocation.method_name() == "remove_window") + invoke(this, server_.get(), &PlatformApiSkeleton::remove_window, invocation); } void PlatformMessageProcessor::process_event_sequence(const std::string&) { diff --git a/src/anbox/ubuntu/platform_api_skeleton.cpp b/src/anbox/ubuntu/platform_api_skeleton.cpp index d7645cd..5cf0261 100644 --- a/src/anbox/ubuntu/platform_api_skeleton.cpp +++ b/src/anbox/ubuntu/platform_api_skeleton.cpp @@ -33,15 +33,6 @@ PlatformApiSekeleton::PlatformApiSekeleton(const std::shared_ptrRun(); -} - void PlatformApiSekeleton::boot_finished(anbox::protobuf::rpc::Void const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) { @@ -54,6 +45,28 @@ void PlatformApiSekeleton::boot_finished(anbox::protobuf::rpc::Void const *reque done->Run(); } +void PlatformApiSekeleton::update_window_state(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) { + (void) request; + (void) response; + + DEBUG(""); + + done->Run(); +} + +void PlatformApiSekeleton::remove_window(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) { + (void) request; + (void) response; + + DEBUG(""); + + done->Run(); +} + void PlatformApiSekeleton::on_boot_finished(const std::function &action) { on_boot_finished_action_ = action; } diff --git a/src/anbox/ubuntu/platform_api_skeleton.h b/src/anbox/ubuntu/platform_api_skeleton.h index a00f391..5e33a71 100644 --- a/src/anbox/ubuntu/platform_api_skeleton.h +++ b/src/anbox/ubuntu/platform_api_skeleton.h @@ -36,11 +36,15 @@ public: PlatformApiSekeleton(const std::shared_ptr &pending_calls); virtual ~PlatformApiSekeleton(); - void handle_notification(anbox::protobuf::bridge::Notification const *request, + void boot_finished(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) override; + + void update_window_state(anbox::protobuf::rpc::Void const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) override; - void boot_finished(anbox::protobuf::rpc::Void const *request, + void remove_window(anbox::protobuf::rpc::Void const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) override; From 66a6f1d2c3eb2a328747124a12f4f46b576f0efb Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:41:19 +0100 Subject: [PATCH 24/54] Drop superflous debug comment --- .../android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp b/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp index 6ca08d0..270ccac 100644 --- a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -127,8 +127,6 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display, Helper* helper) { GLenum texInternalFormat = 0; - printf("Creating new color buffer width %i height %i\n", p_width, p_height); - switch (p_internalFormat) { case GL_RGB: case GL_RGB565_OES: From 5619662b0b4d6fd5da491006559742ad9e26e052 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 09:57:44 +0100 Subject: [PATCH 25/54] Add simple sync script for Android builds --- scripts/android-sync.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 scripts/android-sync.sh diff --git a/scripts/android-sync.sh b/scripts/android-sync.sh new file mode 100755 index 0000000..a3b23de --- /dev/null +++ b/scripts/android-sync.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -ex + +if [ -z "$ANDROID_PRODUCT_OUT" ]; then + echo "ANDROID_PRODUCT_OUT is not set!" + exit 1 +fi + +target=$1 +if [ -z "$target" ]; then + echo "No target path provided!" + exit 1 +fi + +sudo cp -rv $ANDROID_PRODUCT_OUT/system $target +sudo rm /var/lib/anbox/rootfs/.anbox_setup_done From 0ee3c3aad99a87dcc7c1625b23ca355ded8cc628 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 11:35:03 +0100 Subject: [PATCH 26/54] Silence GLESv2 translator on errors we're not interested in --- .../host/libs/Translator/include/GLcommon/GLESmacros.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h index 15e5d04..c66602c 100644 --- a/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h +++ b/external/android-emugl/host/libs/Translator/include/GLcommon/GLESmacros.h @@ -33,14 +33,12 @@ #define SET_ERROR_IF(condition,err) if((condition)) { \ - fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ ctx->setGLerror(err); \ return; \ } #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \ - fprintf(stderr, "%s:%s:%d error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ ctx->setGLerror(err); \ return ret; \ } From 914fcdf1015282b1883461da67c3a551a6d3efea Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 11 Nov 2016 11:45:53 +0100 Subject: [PATCH 27/54] Disable boot animation --- .../android-emugl/host/libs/libOpenglRender/LayerManager.cpp | 2 ++ src/anbox/qemu/boot_properties_message_processor.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp index e6d15ce..f2c0a97 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp @@ -28,6 +28,8 @@ std::string get_package_name(const std::string &name) { bool is_layer_blacklisted(const std::string &name) { static std::vector blacklist = { + // The boot animation should be disabled already but we blacklist it + // here too to ensure it is never visible. "BootAnimation", "StatusBar", "Sprite", diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index 8b7e6f8..52f5089 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -69,6 +69,9 @@ void BootPropertiesMessageProcessor::list_properties() { // To let surfaceflinger load our hwcomposer implementation we specify // the correct subkey of the module here. "ro.hardware.hwcomposer=anbox" + + // Keep boot animation disabled as we don't need it + "debug.sf.nobootanimation=1", }; for (const auto &prop : properties) { From f7820e1f6528fa6e4e2a67f4a30f551f0f9f8b76 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 07:47:07 +0100 Subject: [PATCH 28/54] Fix incorrect boot properties --- src/anbox/qemu/boot_properties_message_processor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index 52f5089..37e1496 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -68,7 +68,7 @@ void BootPropertiesMessageProcessor::list_properties() { // To let surfaceflinger load our hwcomposer implementation we specify // the correct subkey of the module here. - "ro.hardware.hwcomposer=anbox" + "ro.hardware.hwcomposer=anbox", // Keep boot animation disabled as we don't need it "debug.sf.nobootanimation=1", From 0f5006493bd171f28d147aaa7c5db98456193920 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 07:54:19 +0100 Subject: [PATCH 29/54] Implement RPC for window state synchronization --- android/service/platform_api_stub.cpp | 30 +---------- android/service/platform_api_stub.h | 9 ++-- android/service/platform_service.cpp | 52 +++++++++++++++++-- android/service/platform_service.h | 11 +++- .../service/platform_service_interface.cpp | 13 +---- android/service/platform_service_interface.h | 8 ++- src/anbox/bridge/platform_api_skeleton.h | 7 +-- .../bridge/platform_message_processor.cpp | 2 - src/anbox/protobuf/anbox_bridge.proto | 16 ++++++ src/anbox/ubuntu/platform_api_skeleton.cpp | 12 +---- src/anbox/ubuntu/platform_api_skeleton.h | 7 +-- 11 files changed, 89 insertions(+), 78 deletions(-) diff --git a/android/service/platform_api_stub.cpp b/android/service/platform_api_stub.cpp index 289c859..e18e045 100644 --- a/android/service/platform_api_stub.cpp +++ b/android/service/platform_api_stub.cpp @@ -55,7 +55,7 @@ void PlatformApiStub::handle_boot_finished_response(Request boot_finished_wait_handle_.result_received(); } -void PlatformApiStub::update_window_state() { +void PlatformApiStub::update_window_state(const anbox::protobuf::bridge::WindowStateUpdate &window_state) { auto c = std::make_shared>(); ALOGI("Updating window state"); @@ -65,11 +65,9 @@ void PlatformApiStub::update_window_state() { update_window_state_wait_handle_.expect_result(); } - protobuf::rpc::Void message; - rpc_channel_->call_method( "update_window_state", - &message, c->response.get(), + &window_state, c->response.get(), google::protobuf::NewCallback(this, &PlatformApiStub::handle_update_window_state_response, c.get())); update_window_state_wait_handle_.wait_for_all(); @@ -78,28 +76,4 @@ void PlatformApiStub::update_window_state() { void PlatformApiStub::handle_update_window_state_response(Request *request) { update_window_state_wait_handle_.result_received(); } - -void PlatformApiStub::remove_window() { - auto c = std::make_shared>(); - - ALOGI("Remove window"); - - { - std::lock_guard lock(mutex_); - remove_window_wait_handle_.expect_result(); - } - - protobuf::rpc::Void message; - - rpc_channel_->call_method( - "remove_window", - &message, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiStub::handle_remove_window_response, c.get())); - - remove_window_wait_handle_.wait_for_all(); -} - -void PlatformApiStub::handle_remove_window_response(Request *request) { - update_window_state_wait_handle_.result_received(); -} } // namespace anbox diff --git a/android/service/platform_api_stub.h b/android/service/platform_api_stub.h index 02271ba..e13a99c 100644 --- a/android/service/platform_api_stub.h +++ b/android/service/platform_api_stub.h @@ -26,7 +26,11 @@ namespace anbox { namespace protobuf { namespace rpc { class Void; +class WindowStateUpdate; } // namespace rpc +namespace bridge { +class WindowStateUpdate; +} // namespace bridge } // namespace protobuf namespace rpc { class Channel; @@ -36,8 +40,7 @@ public: PlatformApiStub(const std::shared_ptr &rpc_channel); void boot_finished(); - void update_window_state(); - void remove_window(); + void update_window_state(const anbox::protobuf::bridge::WindowStateUpdate &window_state); private: template @@ -49,12 +52,10 @@ private: void handle_boot_finished_response(Request *request); void handle_update_window_state_response(Request *request); - void handle_remove_window_response(Request *request); mutable std::mutex mutex_; common::WaitHandle boot_finished_wait_handle_; common::WaitHandle update_window_state_wait_handle_; - common::WaitHandle remove_window_wait_handle_; std::shared_ptr rpc_channel_; }; diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp index 858708f..d8c9823 100644 --- a/android/service/platform_service.cpp +++ b/android/service/platform_service.cpp @@ -19,9 +19,14 @@ #include "android/service/platform_api_stub.h" #include "anbox/rpc/channel.h" +#include "anbox_rpc.pb.h" +#include "anbox_bridge.pb.h" + #define LOG_TAG "Anboxd" #include +#include + using namespace android; namespace android { @@ -34,13 +39,50 @@ status_t PlatformService::boot_finished() { return OK; } -status_t PlatformService::update_window_state() { - platform_api_stub_->update_window_state(); - return OK; +void PlatformService::unpack_window_state(anbox::protobuf::bridge::WindowStateUpdate_WindowState *window, const Parcel &data) { + window->set_has_surface(data.readByte() != 0); + + String8 package_name(data.readString16()); + + auto frame_left = data.readInt32(); + auto frame_top = data.readInt32(); + auto frame_right = data.readInt32(); + auto frame_bottom = data.readInt32(); + auto task_id = data.readInt32(); + auto stack_id = data.readInt32(); + + window->set_package_name(package_name.string()); + window->set_frame_left(frame_left); + window->set_frame_top(frame_top); + window->set_frame_right(frame_right); + window->set_frame_bottom(frame_bottom); + window->set_task_id(task_id); + window->set_stack_id(stack_id); } -status_t PlatformService::remove_window() { - platform_api_stub_->remove_window(); +status_t PlatformService::update_window_state(const Parcel &data) { + anbox::protobuf::bridge::WindowStateUpdate window_state; + + const auto num_displays = data.readInt32(); + for (auto n = 0; n < num_displays; n++) { + const auto display_id = data.readInt32(); + + for (auto m = 0; m < num_windows; m++) { + auto window = window_state.add_windows(); + window->set_display_id(display_id); + unpack_window_state(window, data); + } + } + + const auto num_removed_windows = data.readInt32(); + for (auto n = 0; n < num_removed_windows; n++) { + auto window = window_state.add_removed_windows(); + window->set_display_id(0); + unpack_window_state(window, data); + } + + platform_api_stub_->update_window_state(window_state); + return OK; } } // namespace android diff --git a/android/service/platform_service.h b/android/service/platform_service.h index cf07a17..2578a58 100644 --- a/android/service/platform_service.h +++ b/android/service/platform_service.h @@ -20,10 +20,17 @@ #include "android/service/platform_service_interface.h" +#include + #include namespace anbox { class PlatformApiStub; +namespace protobuf { +namespace bridge { +class WindowStateUpdate_WindowState; +} // namespace bridge +} // namespace protobuf } // namespace anbox namespace android { @@ -34,10 +41,10 @@ public: PlatformService(const std::shared_ptr &platform_api_stub); status_t boot_finished() override; - status_t update_window_state() override; - status_t remove_window() override; + status_t update_window_state(const Parcel &data) override; private: + void unpack_window_state(anbox::protobuf::bridge::WindowStateUpdate_WindowState *window, const Parcel &data); std::shared_ptr platform_api_stub_; }; } // namespace android diff --git a/android/service/platform_service_interface.cpp b/android/service/platform_service_interface.cpp index 14e83cd..ff2e92c 100644 --- a/android/service/platform_service_interface.cpp +++ b/android/service/platform_service_interface.cpp @@ -28,18 +28,12 @@ status_t BpPlatformService::boot_finished() { return remote()->transact(IPlatformService::BOOT_FINISHED, data, &reply); } -status_t BpPlatformService::update_window_state() { +status_t BpPlatformService::update_window_state(const Parcel&) { Parcel data, reply; data.writeInterfaceToken(IPlatformService::getInterfaceDescriptor()); return remote()->transact(IPlatformService::UPDATE_WINDOW_STATE, data, &reply); } -status_t BpPlatformService::remove_window() { - Parcel data, reply; - data.writeInterfaceToken(IPlatformService::getInterfaceDescriptor()); - return remote()->transact(IPlatformService::REMOVE_WINDOW, data, &reply); -} - IMPLEMENT_META_INTERFACE(PlatformService, "org.anbox.IPlatformService"); status_t BnPlatformService::onTransact(uint32_t code, const Parcel &data, @@ -50,10 +44,7 @@ status_t BnPlatformService::onTransact(uint32_t code, const Parcel &data, return boot_finished(); case UPDATE_WINDOW_STATE: CHECK_INTERFACE(IPlatformService, data, reply); - return update_window_state(); - case REMOVE_WINDOW: - CHECK_INTERFACE(IPlatformService, data, reply); - return remove_window(); + return update_window_state(data); default: break; } diff --git a/android/service/platform_service_interface.h b/android/service/platform_service_interface.h index 343354e..876cf95 100644 --- a/android/service/platform_service_interface.h +++ b/android/service/platform_service_interface.h @@ -33,14 +33,13 @@ public: DECLARE_META_INTERFACE(PlatformService); enum { + // Keep this synchronized with frameworks/base/services/java/com/android/server/wm/AnboxPlatformServiceProxy.java BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, UPDATE_WINDOW_STATE = IBinder::FIRST_CALL_TRANSACTION + 1, - REMOVE_WINDOW = IBinder::FIRST_CALL_TRANSACTION + 2, }; virtual status_t boot_finished() = 0; - virtual status_t update_window_state() = 0; - virtual status_t remove_window() = 0; + virtual status_t update_window_state(const Parcel &data) = 0; }; class BpPlatformService : public BpInterface { @@ -48,8 +47,7 @@ public: BpPlatformService(const sp &binder); status_t boot_finished() override; - status_t update_window_state() override; - status_t remove_window() override; + status_t update_window_state(const Parcel &data) override; }; class BnPlatformService : public BnInterface { diff --git a/src/anbox/bridge/platform_api_skeleton.h b/src/anbox/bridge/platform_api_skeleton.h index b07c5d6..57cc93a 100644 --- a/src/anbox/bridge/platform_api_skeleton.h +++ b/src/anbox/bridge/platform_api_skeleton.h @@ -33,6 +33,7 @@ class Void; } // namespace rpc namespace bridge { class Notification; +class WindowStateUpdate; } // namespace bridge } // namespace protobuf namespace rpc { @@ -48,14 +49,10 @@ public: anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) = 0; - virtual void update_window_state(anbox::protobuf::rpc::Void const *request, + virtual void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) = 0; - virtual void remove_window(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) = 0; - private: std::shared_ptr pending_calls_; }; diff --git a/src/anbox/bridge/platform_message_processor.cpp b/src/anbox/bridge/platform_message_processor.cpp index bfe7e42..59d6f28 100644 --- a/src/anbox/bridge/platform_message_processor.cpp +++ b/src/anbox/bridge/platform_message_processor.cpp @@ -38,8 +38,6 @@ void PlatformMessageProcessor::dispatch(rpc::Invocation const& invocation) { invoke(this, server_.get(), &PlatformApiSkeleton::boot_finished, invocation); else if (invocation.method_name() == "update_window_state") invoke(this, server_.get(), &PlatformApiSkeleton::update_window_state, invocation); - else if (invocation.method_name() == "remove_window") - invoke(this, server_.get(), &PlatformApiSkeleton::remove_window, invocation); } void PlatformMessageProcessor::process_event_sequence(const std::string&) { diff --git a/src/anbox/protobuf/anbox_bridge.proto b/src/anbox/protobuf/anbox_bridge.proto index 2102278..0dce0df 100644 --- a/src/anbox/protobuf/anbox_bridge.proto +++ b/src/anbox/protobuf/anbox_bridge.proto @@ -26,3 +26,19 @@ message SetDnsServers { } repeated Server servers = 2; } + +message WindowStateUpdate { + message WindowState { + required int32 display_id = 1; + required bool has_surface = 2; + required string package_name = 3; + required int32 frame_left = 4; + required int32 frame_top = 5; + required int32 frame_right = 6; + required int32 frame_bottom = 7; + required int32 task_id = 8; + required int32 stack_id = 9; + } + repeated WindowState windows = 1; + repeated WindowState removed_windows = 2; +} diff --git a/src/anbox/ubuntu/platform_api_skeleton.cpp b/src/anbox/ubuntu/platform_api_skeleton.cpp index 5cf0261..459ae17 100644 --- a/src/anbox/ubuntu/platform_api_skeleton.cpp +++ b/src/anbox/ubuntu/platform_api_skeleton.cpp @@ -45,7 +45,7 @@ void PlatformApiSekeleton::boot_finished(anbox::protobuf::rpc::Void const *reque done->Run(); } -void PlatformApiSekeleton::update_window_state(anbox::protobuf::rpc::Void const *request, +void PlatformApiSekeleton::update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) { (void) request; @@ -53,16 +53,6 @@ void PlatformApiSekeleton::update_window_state(anbox::protobuf::rpc::Void const DEBUG(""); - done->Run(); -} - -void PlatformApiSekeleton::remove_window(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) { - (void) request; - (void) response; - - DEBUG(""); done->Run(); } diff --git a/src/anbox/ubuntu/platform_api_skeleton.h b/src/anbox/ubuntu/platform_api_skeleton.h index 5e33a71..338760e 100644 --- a/src/anbox/ubuntu/platform_api_skeleton.h +++ b/src/anbox/ubuntu/platform_api_skeleton.h @@ -26,6 +26,7 @@ class Dispatcher; } // namespace common namespace bridge { class AndroidApiStub; +class WindowStateUpdate; } // namespace bridge namespace rpc { class PendingCallCache; @@ -40,14 +41,10 @@ public: anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) override; - void update_window_state(anbox::protobuf::rpc::Void const *request, + void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) override; - void remove_window(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) override; - void on_boot_finished(const std::function &action); private: From 1e168fd4aa1764878f1b82c5f4c0ea31c77b0f3e Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 08:51:17 +0100 Subject: [PATCH 30/54] Add basic infrastructure for our window manager --- src/CMakeLists.txt | 7 +- src/anbox/bridge/platform_api_skeleton.cpp | 55 ++++++++++- src/anbox/bridge/platform_api_skeleton.h | 22 +++-- src/anbox/cmds/run.cpp | 7 +- src/anbox/graphics/rect.cpp | 25 +++++ src/anbox/graphics/rect.h | 101 +++++++++++++++++++++ src/anbox/ubuntu/platform_api_skeleton.cpp | 64 ------------- src/anbox/ubuntu/platform_api_skeleton.h | 56 ------------ src/anbox/wm/display.cpp | 25 +++++ src/anbox/wm/display.h | 38 ++++++++ src/anbox/wm/manager.cpp | 37 ++++++++ src/anbox/wm/manager.h | 38 ++++++++ src/anbox/wm/task.cpp | 24 +++++ src/anbox/wm/task.h | 37 ++++++++ src/anbox/wm/window_state.cpp | 45 +++++++++ src/anbox/wm/window_state.h | 59 ++++++++++++ 16 files changed, 508 insertions(+), 132 deletions(-) create mode 100644 src/anbox/graphics/rect.cpp create mode 100644 src/anbox/graphics/rect.h delete mode 100644 src/anbox/ubuntu/platform_api_skeleton.cpp delete mode 100644 src/anbox/ubuntu/platform_api_skeleton.h create mode 100644 src/anbox/wm/display.cpp create mode 100644 src/anbox/wm/display.h create mode 100644 src/anbox/wm/manager.cpp create mode 100644 src/anbox/wm/manager.h create mode 100644 src/anbox/wm/task.cpp create mode 100644 src/anbox/wm/task.h create mode 100644 src/anbox/wm/window_state.cpp create mode 100644 src/anbox/wm/window_state.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f452f6f..91035db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,6 +95,12 @@ set(SOURCES anbox/graphics/gl_renderer_server.cpp anbox/graphics/window_creator.cpp anbox/graphics/density.h + anbox/graphics/rect.cpp + + anbox/wm/display.cpp + anbox/wm/task.cpp + anbox/wm/manager.cpp + anbox/wm/window_state.cpp anbox/input/manager.cpp anbox/input/device.cpp @@ -116,7 +122,6 @@ set(SOURCES anbox/bridge/platform_api_skeleton.cpp anbox/bridge/android_api_stub.cpp - anbox/ubuntu/platform_api_skeleton.cpp anbox/ubuntu/window_creator.cpp anbox/ubuntu/window.cpp anbox/ubuntu/keycode_converter.cpp diff --git a/src/anbox/bridge/platform_api_skeleton.cpp b/src/anbox/bridge/platform_api_skeleton.cpp index e9e53e8..34d87fb 100644 --- a/src/anbox/bridge/platform_api_skeleton.cpp +++ b/src/anbox/bridge/platform_api_skeleton.cpp @@ -16,17 +16,68 @@ */ #include "anbox/bridge/platform_api_skeleton.h" +#include "anbox/wm/manager.h" +#include "anbox/wm/window_state.h" #include "anbox/logger.h" #include "anbox_bridge.pb.h" namespace anbox { namespace bridge { -PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptr &pending_calls) : - pending_calls_(pending_calls) { +PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptr &pending_calls, + const std::shared_ptr &window_manager) : + pending_calls_(pending_calls), + window_manager_(window_manager) { } PlatformApiSkeleton::~PlatformApiSkeleton() { } + +void PlatformApiSkeleton::boot_finished(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) { + (void) request; + (void) response; + + if (on_boot_finished_action_) + on_boot_finished_action_(); + + done->Run(); +} + +void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) { + (void) response; + + auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdate_WindowState &window) { + return wm::WindowState( + wm::Display::Id(window.display_id()), + window.has_surface(), + graphics::Rect(window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom()), + window.package_name(), + wm::Task::Id(window.task_id())); + }; + + wm::WindowState::List updated; + for (int n = 0; n < request->windows_size(); n++) { + const auto window = request->windows(n); + updated.push_back(convert_window_state(window)); + } + + wm::WindowState::List removed; + for (int n = 0; n < request->removed_windows_size(); n++) { + const auto window = request->removed_windows(n); + updated.push_back(convert_window_state(window)); + } + + window_manager_->apply_window_state_update(updated, removed); + + done->Run(); +} + +void PlatformApiSkeleton::on_boot_finished(const std::function &action) { + on_boot_finished_action_ = action; +} } // namespace bridge } // namespace anbox diff --git a/src/anbox/bridge/platform_api_skeleton.h b/src/anbox/bridge/platform_api_skeleton.h index 57cc93a..e18f42e 100644 --- a/src/anbox/bridge/platform_api_skeleton.h +++ b/src/anbox/bridge/platform_api_skeleton.h @@ -39,22 +39,30 @@ class WindowStateUpdate; namespace rpc { class PendingCallCache; } // namespace rpc +namespace wm { +class Manager; +} // namespace wm namespace bridge { class PlatformApiSkeleton { public: - PlatformApiSkeleton(const std::shared_ptr &pending_calls); + PlatformApiSkeleton(const std::shared_ptr &pending_calls, + const std::shared_ptr &window_manager); virtual ~PlatformApiSkeleton(); - virtual void boot_finished(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) = 0; + void boot_finished(anbox::protobuf::rpc::Void const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done); - virtual void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) = 0; + void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done); + + void on_boot_finished(const std::function &action); private: std::shared_ptr pending_calls_; + std::shared_ptr window_manager_; + std::function on_boot_finished_action_; }; } // namespace bridge } // namespace anbox diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 7fffe26..e65ce28 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -32,10 +32,11 @@ #include "anbox/rpc/channel.h" #include "anbox/bridge/platform_message_processor.h" #include "anbox/bridge/android_api_stub.h" -#include "anbox/ubuntu/platform_api_skeleton.h" +#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/ubuntu/window_creator.h" #include "anbox/dbus/skeleton/service.h" #include "anbox/container/client.h" +#include "anbox/wm/manager.h" #include @@ -88,6 +89,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto input_manager = std::make_shared(rt); + auto window_manager = std::make_shared(); + auto window_creator = std::make_shared(input_manager); auto renderer = std::make_shared(window_creator); renderer->start(); @@ -123,7 +126,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) // more than one one day we need proper dispatching to the right one. android_api_stub->set_rpc_channel(rpc_channel); - auto server = std::make_shared(pending_calls); + auto server = std::make_shared(pending_calls, window_manager); server->on_boot_finished([&]() { dispatcher->dispatch([&]() { // FIXME make this configurable or once we have a bridge let the host diff --git a/src/anbox/graphics/rect.cpp b/src/anbox/graphics/rect.cpp new file mode 100644 index 0000000..62d3e75 --- /dev/null +++ b/src/anbox/graphics/rect.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/graphics/rect.h" + +namespace anbox { +namespace graphics { +const Rect Rect::Invalid{-1,-1,-1,-1}; +const Rect Rect::Empty{0,0,0,0}; +} // namespace graphics +} // namespace anbox diff --git a/src/anbox/graphics/rect.h b/src/anbox/graphics/rect.h new file mode 100644 index 0000000..a9c994e --- /dev/null +++ b/src/anbox/graphics/rect.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_GRAPHICS_RECT_H_ +#define ANBOX_GRAPHICS_RECT_H_ + +#include + +namespace anbox { +namespace graphics { +class Rect { +public: + static const Rect Invalid; + static const Rect Empty; + + inline Rect() : Rect(Empty) {} + + inline Rect(const std::int32_t &left, + const std::int32_t &top, + const std::int32_t &right, + const std::int32_t &bottom) : + left_(left), + top_(top), + right_(right), + bottom_(bottom) { + } + + inline Rect(const std::int32_t &width, const std::int32_t &height) : + left_(0), + top_(0), + right_(width), + bottom_(height) { + } + + inline void clear() { + left_ = top_ = right_ = bottom_ = 0; + } + + inline bool valid() const { + return width() >= 0 && height() >= 0; + } + + inline std::int32_t width() const { + return right_ - left_; + } + + inline std::int32_t height() const { + return bottom_ - top_; + } + + inline std::int32_t left() const { + return left_; + } + + inline std::int32_t top() const { + return top_; + } + + inline std::int32_t right() const { + return right_; + } + + inline std::int32_t bottom() const { + return bottom_; + } + + inline bool operator == (const Rect &rhs) const { + return (left_ == rhs.left() && + top_ == rhs.top() && + right_ == rhs.right() && + bottom_ == rhs.bottom()); + } + + inline bool operator != (const Rect &rhs) const { + return !operator == (rhs); + } + +private: + std::int32_t left_; + std::int32_t top_; + std::int32_t right_; + std::int32_t bottom_; +}; +} // namespace graphics +} // namespace anbox + +#endif diff --git a/src/anbox/ubuntu/platform_api_skeleton.cpp b/src/anbox/ubuntu/platform_api_skeleton.cpp deleted file mode 100644 index 459ae17..0000000 --- a/src/anbox/ubuntu/platform_api_skeleton.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -#include "anbox/ubuntu/platform_api_skeleton.h" -#include "anbox/common/dispatcher.h" -#include "anbox/bridge/android_api_stub.h" -#include "anbox/rpc/pending_call_cache.h" -#include "anbox/logger.h" - -#include "anbox_rpc.pb.h" -#include "anbox_bridge.pb.h" - -namespace anbox { -namespace ubuntu { -PlatformApiSekeleton::PlatformApiSekeleton(const std::shared_ptr &pending_calls) : - bridge::PlatformApiSkeleton(pending_calls) { -} - -PlatformApiSekeleton::~PlatformApiSekeleton() { -} - -void PlatformApiSekeleton::boot_finished(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) { - (void) request; - (void) response; - - if (on_boot_finished_action_) - on_boot_finished_action_(); - - done->Run(); -} - -void PlatformApiSekeleton::update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) { - (void) request; - (void) response; - - DEBUG(""); - - - done->Run(); -} - -void PlatformApiSekeleton::on_boot_finished(const std::function &action) { - on_boot_finished_action_ = action; -} -} // namespace ubuntu -} // namespace anbox diff --git a/src/anbox/ubuntu/platform_api_skeleton.h b/src/anbox/ubuntu/platform_api_skeleton.h deleted file mode 100644 index 338760e..0000000 --- a/src/anbox/ubuntu/platform_api_skeleton.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -#ifndef ANBOX_UBUNTU_PLATFORM_SERVER_H_ -#define ANBOX_UBUNTU_PLATFORM_SERVER_H_ - -#include "anbox/bridge/platform_api_skeleton.h" - -namespace anbox { -namespace common { -class Dispatcher; -} // namespace common -namespace bridge { -class AndroidApiStub; -class WindowStateUpdate; -} // namespace bridge -namespace rpc { -class PendingCallCache; -} // namespace rpc; -namespace ubuntu { -class PlatformApiSekeleton : public bridge::PlatformApiSkeleton { -public: - PlatformApiSekeleton(const std::shared_ptr &pending_calls); - virtual ~PlatformApiSekeleton(); - - void boot_finished(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) override; - - void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) override; - - void on_boot_finished(const std::function &action); - -private: - std::function on_boot_finished_action_; -}; -} // namespace bridge -} // namespace anbox - -#endif diff --git a/src/anbox/wm/display.cpp b/src/anbox/wm/display.cpp new file mode 100644 index 0000000..671a166 --- /dev/null +++ b/src/anbox/wm/display.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/display.h" + +namespace anbox { +namespace wm { +Display::Id Display::Invalid = -1; +Display::Id Display::Default = 0; +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/display.h b/src/anbox/wm/display.h new file mode 100644 index 0000000..6b53baf --- /dev/null +++ b/src/anbox/wm/display.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_DISPLAY_H_ +#define ANBOX_WM_DISPLAY_H_ + +#include + +namespace anbox { +namespace wm { +class Display { +public: + typedef std::int32_t Id; + + static Id Invalid; + static Id Default; + + Display() = delete; + Display(const Display&) = delete; +}; +} // namespace wm +} // namespace anbox + +#endif diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp new file mode 100644 index 0000000..9e40895 --- /dev/null +++ b/src/anbox/wm/manager.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/manager.h" +#include "anbox/logger.h" + +namespace anbox { +namespace wm { +Manager::Manager() { +} + +Manager::~Manager() { +} + +void Manager::apply_window_state_update(const WindowState::List &updated, + const WindowState::List &removed) { + (void) updated; + (void) removed; + + DEBUG("updated %d removed %d", updated.size(), removed.size()); +} +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/manager.h b/src/anbox/wm/manager.h new file mode 100644 index 0000000..d882321 --- /dev/null +++ b/src/anbox/wm/manager.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_MANAGER_H_ +#define ANBOX_WM_MANAGER_H_ + +#include "anbox/wm/window_state.h" + +namespace anbox { +namespace wm { +class Manager { +public: + Manager(); + ~Manager(); + + void apply_window_state_update(const WindowState::List &updated, + const WindowState::List &removed); + +private: +}; +} // namespace wm +} // namespace anbox + +#endif diff --git a/src/anbox/wm/task.cpp b/src/anbox/wm/task.cpp new file mode 100644 index 0000000..46cecee --- /dev/null +++ b/src/anbox/wm/task.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/task.h" + +namespace anbox { +namespace wm { +Task::Id Task::Invalid = -1; +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/task.h b/src/anbox/wm/task.h new file mode 100644 index 0000000..fa7e8f7 --- /dev/null +++ b/src/anbox/wm/task.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_TASK_H_ +#define ANBOX_WM_TASK_H_ + +#include + +namespace anbox { +namespace wm { +class Task { +public: + typedef std::int32_t Id; + + static Id Invalid; + + Task() = delete; + Task(const Task&) = delete; +}; +} // namespace wm +} // namespace anbox + +#endif diff --git a/src/anbox/wm/window_state.cpp b/src/anbox/wm/window_state.cpp new file mode 100644 index 0000000..1b357f8 --- /dev/null +++ b/src/anbox/wm/window_state.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/window_state.h" + +namespace anbox { +namespace wm { +WindowState::WindowState() : + display_(Display::Invalid), + has_surface_(false), + frame_(graphics::Rect::Invalid), + package_name_(""), + task_(Task::Invalid) { +} + +WindowState::WindowState(const Display::Id &display, + bool has_surface, + const graphics::Rect &frame, + const std::string &package_name, + const Task::Id &task) : + display_(display), + has_surface_(has_surface), + frame_(frame), + package_name_(package_name), + task_(task) { +} + +WindowState::~WindowState() { +} +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/window_state.h b/src/anbox/wm/window_state.h new file mode 100644 index 0000000..f0c2ed0 --- /dev/null +++ b/src/anbox/wm/window_state.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_WINDOW_STATE_H_ +#define ANBOX_WM_WINDOW_STATE_H_ + +#include "anbox/graphics/rect.h" +#include "anbox/wm/display.h" +#include "anbox/wm/task.h" + +#include +#include + +namespace anbox { +namespace wm { +class WindowState { +public: + typedef std::vector List; + + WindowState(); + WindowState(const Display::Id &display, + bool has_surface, + const graphics::Rect &frame, + const std::string &package_name, + const Task::Id &task); + ~WindowState(); + + Display::Id display() const { return display_; } + bool has_surface() const { return has_surface_; } + graphics::Rect frame() const { return frame_; } + std::string package_name() const { return package_name_; } + Task::Id task() const { return task_; } + +private: + Display::Id display_; + bool has_surface_; + graphics::Rect frame_; + std::string package_name_; + Task::Id task_; + +}; +} // namespace wm +} // namespace anbox + +#endif From 609d80395cc3789cb58a0c8220fab95c93b18b84 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 13:59:53 +0100 Subject: [PATCH 31/54] Migrate emugl layer into the core --- .../android-emugl/host/libs/CMakeLists.txt | 1 - .../host/libs/libOpenglRender/CMakeLists.txt | 34 --- .../libOpenglRender/NativeSubWindow_cocoa.m | 101 -------- .../libOpenglRender/NativeSubWindow_mir.cpp | 201 --------------- .../libOpenglRender/NativeSubWindow_null.cpp | 39 --- .../libOpenglRender/NativeSubWindow_win32.cpp | 90 ------- .../libOpenglRender/NativeSubWindow_x11.cpp | 105 -------- .../libs/libOpenglRender/Win32PipeStream.cpp | 241 ------------------ .../libs/libOpenglRender/Win32PipeStream.h | 42 --- src/CMakeLists.txt | 40 ++- .../anbox/graphics/emugl}/ColorBuffer.cpp | 0 .../anbox/graphics/emugl}/ColorBuffer.h | 0 .../anbox/graphics/emugl}/DispatchTables.h | 0 .../anbox/graphics/emugl}/DisplayManager.cpp | 0 .../anbox/graphics/emugl}/DisplayManager.h | 0 .../anbox/graphics/emugl}/FbConfig.cpp | 0 .../anbox/graphics/emugl}/FbConfig.h | 0 .../anbox/graphics/emugl}/FrameBuffer.cpp | 0 .../anbox/graphics/emugl}/FrameBuffer.h | 0 .../anbox/graphics/emugl}/LayerManager.cpp | 12 + .../anbox/graphics/emugl}/LayerManager.h | 0 .../anbox/graphics/emugl}/NativeSubWindow.h | 0 .../emugl}/NativeSubWindow_delegate.cpp | 0 .../anbox/graphics/emugl}/ReadBuffer.cpp | 0 .../anbox/graphics/emugl}/ReadBuffer.h | 0 .../anbox/graphics/emugl}/RenderApi.cpp | 0 .../anbox/graphics/emugl}/RenderContext.cpp | 0 .../anbox/graphics/emugl}/RenderContext.h | 0 .../anbox/graphics/emugl}/RenderControl.cpp | 0 .../anbox/graphics/emugl}/RenderControl.h | 0 .../anbox/graphics/emugl}/RenderServer.cpp | 0 .../anbox/graphics/emugl}/RenderServer.h | 0 .../anbox/graphics/emugl}/RenderThread.cpp | 46 ---- .../anbox/graphics/emugl}/RenderThread.h | 0 .../graphics/emugl}/RenderThreadInfo.cpp | 0 .../anbox/graphics/emugl}/RenderThreadInfo.h | 0 .../anbox/graphics/emugl}/RenderWindow.cpp | 0 .../anbox/graphics/emugl}/RenderWindow.h | 0 .../anbox/graphics/emugl}/SocketStream.cpp | 0 .../anbox/graphics/emugl}/SocketStream.h | 0 .../anbox/graphics/emugl}/TcpStream.cpp | 0 .../anbox/graphics/emugl}/TcpStream.h | 0 .../anbox/graphics/emugl}/TextureDraw.cpp | 0 .../anbox/graphics/emugl}/TextureDraw.h | 0 .../anbox/graphics/emugl}/TextureResize.cpp | 0 .../anbox/graphics/emugl}/TextureResize.h | 0 .../anbox/graphics/emugl}/TimeUtils.cpp | 0 .../anbox/graphics/emugl}/TimeUtils.h | 0 .../anbox/graphics/emugl}/UnixStream.cpp | 0 .../anbox/graphics/emugl}/UnixStream.h | 0 .../anbox/graphics/emugl}/WindowSurface.cpp | 0 .../anbox/graphics/emugl}/WindowSurface.h | 0 .../anbox/graphics/emugl}/render_api.entries | 0 53 files changed, 51 insertions(+), 901 deletions(-) delete mode 100644 external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt delete mode 100644 external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_cocoa.m delete mode 100644 external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_mir.cpp delete mode 100644 external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_null.cpp delete mode 100644 external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_win32.cpp delete mode 100644 external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_x11.cpp delete mode 100644 external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.cpp delete mode 100644 external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.h rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/ColorBuffer.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/ColorBuffer.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/DispatchTables.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/DisplayManager.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/DisplayManager.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/FbConfig.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/FbConfig.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/FrameBuffer.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/FrameBuffer.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/LayerManager.cpp (87%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/LayerManager.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/NativeSubWindow.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/NativeSubWindow_delegate.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/ReadBuffer.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/ReadBuffer.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderApi.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderContext.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderContext.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderControl.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderControl.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderServer.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderServer.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderThread.cpp (72%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderThread.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderThreadInfo.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderThreadInfo.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderWindow.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/RenderWindow.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/SocketStream.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/SocketStream.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TcpStream.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TcpStream.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TextureDraw.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TextureDraw.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TextureResize.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TextureResize.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TimeUtils.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/TimeUtils.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/UnixStream.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/UnixStream.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/WindowSurface.cpp (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/WindowSurface.h (100%) rename {external/android-emugl/host/libs/libOpenglRender => src/anbox/graphics/emugl}/render_api.entries (100%) diff --git a/external/android-emugl/host/libs/CMakeLists.txt b/external/android-emugl/host/libs/CMakeLists.txt index 2e7bf51..09b6e09 100644 --- a/external/android-emugl/host/libs/CMakeLists.txt +++ b/external/android-emugl/host/libs/CMakeLists.txt @@ -1,6 +1,5 @@ add_subdirectory(GLESv1_dec) add_subdirectory(GLESv2_dec) add_subdirectory(libOpenGLESDispatch) -add_subdirectory(libOpenglRender) add_subdirectory(renderControl_dec) add_subdirectory(Translator) diff --git a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt b/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt deleted file mode 100644 index 701ea8c..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -set(SOURCES - ColorBuffer.cpp - DisplayManager.cpp - FbConfig.cpp - FrameBuffer.cpp - LayerManager.cpp - NativeSubWindow.h - NativeSubWindow_delegate.cpp - ReadBuffer.cpp - RenderContext.cpp - RenderControl.cpp - RenderServer.cpp - RenderThread.cpp - RenderThreadInfo.cpp - RenderApi.cpp - RenderWindow.cpp - SocketStream.cpp - TcpStream.cpp - TextureDraw.cpp - TextureResize.cpp - TimeUtils.cpp - UnixStream.cpp - WindowSurface.cpp) - -add_library(OpenglRender ${SOURCES}) -target_link_libraries(OpenglRender - emugl_common - GLESv1_dec - GLESv2_dec - renderControl_dec - OpenGLESDispatch - OpenglCodecCommon - ${EGL_LDFLAGS} - ${EGL_LIBRARIES}) diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_cocoa.m b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_cocoa.m deleted file mode 100644 index 54674b5..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_cocoa.m +++ /dev/null @@ -1,101 +0,0 @@ -/* -* Copyright (C) 2011 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 "NativeSubWindow.h" -#include - -/* - * EmuGLView inherit from NSView and override the isOpaque - * method to return YES. That prevents drawing of underlying window/view - * when the view needs to be redrawn. - */ -@interface EmuGLView : NSView { -} @end - -@implementation EmuGLView - - - (BOOL)isOpaque { - return YES; - } - -@end - - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param) { - NSWindow* win = (NSWindow *)p_window; - if (!win) { - return NULL; - } - - /* (x,y) assume an upper-left origin, but Cocoa uses a lower-left origin */ - NSRect content_rect = [win contentRectForFrameRect:[win frame]]; - int cocoa_y = (int)content_rect.size.height - (y + height); - NSRect contentRect = NSMakeRect(x, cocoa_y, width, height); - - NSView *glView = [[EmuGLView alloc] initWithFrame:contentRect]; - if (glView) { - [glView setWantsBestResolutionOpenGLSurface:YES]; - [[win contentView] addSubview:glView]; - [win makeKeyAndOrderFront:nil]; - } - - return (EGLNativeWindowType)glView; -} - -void destroySubWindow(EGLNativeWindowType win) { - if(win){ - NSView *glView = (NSView *)win; - [glView removeFromSuperview]; - [glView release]; - } -} - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - NSWindow *win = (NSWindow *)p_parent_window; - if (!win) { - return 0; - } - - NSView *glView = (NSView *)p_sub_window; - if (!glView) { - return 0; - } - - /* The view must be removed from the hierarchy to be properly resized */ - [glView removeFromSuperview]; - - /* (x,y) assume an upper-left origin, but Cocoa uses a lower-left origin */ - NSRect content_rect = [win contentRectForFrameRect:[win frame]]; - int cocoa_y = (int)content_rect.size.height - (y + height); - NSRect newFrame = NSMakeRect(x, cocoa_y, width, height); - [glView setFrame:newFrame]; - - /* Re-add the sub-window to the view hierarchy */ - [[win contentView] addSubview:glView]; - [win makeKeyAndOrderFront:nil]; - - return 1; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_mir.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_mir.cpp deleted file mode 100644 index 1bbf0b3..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_mir.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* -* Copyright (C) 2011 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. -*/ - -#define MIR_EGL_PLATFORM - -#include "mir_support/shared_state.h" - -#include "NativeSubWindow.h" - -#include "OpenglCodecCommon/ErrorLog.h" - -#include -#include -#include - -#include - -namespace { -std::map surfaces; - -static const MirDisplayOutput *find_active_output( - const MirDisplayConfiguration *conf) -{ - const MirDisplayOutput *output = NULL; - int d; - - for (d = 0; d < (int)conf->num_outputs; d++) - { - const MirDisplayOutput *out = conf->outputs + d; - - if (out->used && - out->connected && - out->num_modes && - out->current_mode < out->num_modes) - { - output = out; - break; - } - } - - return output; -} -} - -MirPixelFormat defaultPixelFormatFor(MirConnection *connection) -{ - MirPixelFormat format; - unsigned int nformats; - mir_connection_get_available_surface_formats(connection, &format, 1, &nformats); - return format; -} - -void handleSurfaceEvent(const MirSurfaceEvent *event) { - MirSurfaceAttrib attrib = mir_surface_event_get_attribute(event); - if (attrib != mir_surface_attrib_visibility) - return; - switch (mir_surface_event_get_attribute(event)) { - case mir_surface_visibility_exposed: - ERR("Surface exposed\n"); - break; - case mir_surface_visibility_occluded: - ERR("Surface occluded\n"); - break; - default: - break; - } -} - -void surfaceEventHandler(MirSurface *surface, MirEvent const *event, void *context) { - switch (mir_event_get_type(event)) { - case mir_event_type_input: - break; - case mir_event_type_surface: - handleSurfaceEvent(mir_event_get_surface_event(event)); - break; - case mir_event_type_resize: - { - MirResizeEvent const *resize_event = mir_event_get_resize_event(event); - ERR("Resized to %dx%d\n", - mir_resize_event_get_width(resize_event), - mir_resize_event_get_height(resize_event)); - } - break; - case mir_event_type_close_surface: - break; - case mir_event_type_surface_output: - { - MirSurfaceOutputEvent const *output_event = mir_event_get_surface_output_event(event); - ERR("dpi %i output id %d\n", - mir_surface_output_event_get_dpi(output_event), - mir_surface_output_event_get_output_id(output_event)); - } - break; - default: - break; - } -} - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param) { - - (void) p_window; - (void) x; - (void) y; - (void) width; - (void) height; - (void) repaint_callback; - (void) repaint_callback_param; - - mir::support::SharedState::get()->ensure_connection(); - - const auto pixel_format = defaultPixelFormatFor(mir::support::SharedState::get()->connection()); - - ERR("Selected pixel format %d\n", pixel_format); - - MirDisplayConfiguration* display_config = - mir_connection_create_display_config(mir::support::SharedState::get()->connection()); - - const MirDisplayOutput *output = find_active_output(display_config); - if (!output) - throw new std::runtime_error("Failed to find active output display"); - - const MirDisplayMode *mode = &output->modes[output->current_mode]; - - auto spec = mir_connection_create_spec_for_normal_surface( - mir::support::SharedState::get()->connection(), - mode->vertical_resolution, - mode->horizontal_resolution, - pixel_format); - - mir_surface_spec_set_name(spec, "anbox"); - mir_surface_spec_set_event_handler(spec, surfaceEventHandler, nullptr); - ERR("Selecting output id %d", output->output_id); - mir_surface_spec_set_fullscreen_on_output(spec, output->output_id); - mir_surface_spec_set_buffer_usage(spec, mir_buffer_usage_hardware); - - mir_display_config_destroy(display_config); - - auto surface = mir_surface_create_sync(spec); - mir_surface_spec_release(spec); - - if (!mir_surface_is_valid(surface)) { - ERR("surface error: %s\n", mir_surface_get_error_message(surface)); - throw std::runtime_error("Failed to create a Mir surface"); - } - - MirSurfaceParameters parameters; - mir_surface_get_parameters(surface, ¶meters); - ERR("width %i height %i output id %i\n", - parameters.width, - parameters.height, - parameters.output_id); - - auto surface_buffer_stream = mir_surface_get_buffer_stream(surface); - auto native_window = reinterpret_cast( - mir_buffer_stream_get_egl_native_window(surface_buffer_stream)); - - surfaces.insert({ native_window, surface }); - - return native_window; -} - -void destroySubWindow(EGLNativeWindowType win) { - if (surfaces.find(win) == surfaces.end()) - return; - - auto surface = surfaces[win]; - surfaces.erase(win); - - mir_surface_release_sync(surface); -} - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - - ERR("%s: Not implemented", __func__); - - return true; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_null.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_null.cpp deleted file mode 100644 index 46bee10..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_null.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright (C) 2011 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 "NativeSubWindow.h" - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param) { - return NULL; -} - -void destroySubWindow(EGLNativeWindowType win) { -} - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - return false; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_win32.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_win32.cpp deleted file mode 100644 index 344459a..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_win32.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (C) 2011 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 "NativeSubWindow.h" - -struct SubWindowUserData { - SubWindowRepaintCallback repaint_callback; - void* repaint_callback_param; -}; - -static LRESULT CALLBACK subWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - if (uMsg == WM_PAINT) { - auto user_data = - (SubWindowUserData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (user_data && user_data->repaint_callback) { - user_data->repaint_callback(user_data->repaint_callback_param); - } - } else if (uMsg == WM_NCDESTROY) { - SubWindowUserData* user_data = - (SubWindowUserData*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - delete user_data; - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, int y,int width, int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param){ - static const char className[] = "subWin"; - - WNDCLASS wc = {}; - if (!GetClassInfo(GetModuleHandle(NULL), className, &wc)) { - wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;// redraw if size changes - wc.lpfnWndProc = &subWindowProc; // points to window procedure - wc.cbWndExtra = sizeof(void*) ; // save extra window memory - wc.lpszClassName = className; // name of window class - RegisterClass(&wc); - } - - EGLNativeWindowType ret = CreateWindowEx( - WS_EX_NOPARENTNOTIFY, // do not bother our parent window - className, - "sub", - WS_CHILD|WS_DISABLED, - x,y,width,height, - p_window, - NULL, - NULL, - NULL); - - auto user_data = new SubWindowUserData(); - user_data->repaint_callback = repaint_callback; - user_data->repaint_callback_param = repaint_callback_param; - - SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR)user_data); - ShowWindow(ret, SW_SHOW); - return ret; -} - -void destroySubWindow(EGLNativeWindowType win){ - PostMessage(win, WM_CLOSE, 0, 0); -} - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - BOOL ret = MoveWindow(p_sub_window, - x, - y, - width, - height, - TRUE); - return ret; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_x11.cpp b/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_x11.cpp deleted file mode 100644 index be2d4d3..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_x11.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* -* Copyright (C) 2011 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 "NativeSubWindow.h" - -#include - -static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) { - if (e->type == MapNotify && e->xmap.window == (Window)arg) { - return 1; - } - return 0; -} - -static Bool WaitForConfigureNotify(Display *d, XEvent *e, char *arg) { - if (e->type == ConfigureNotify && e->xmap.window == (Window)arg) { - return 1; - } - return 0; -} - -static Display *s_display = NULL; - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height, - SubWindowRepaintCallback repaint_callback, - void* repaint_callback_param) { - // The call to this function is protected by a lock - // in FrameBuffer so it is safe to check and initialize s_display here - if (!s_display) { - s_display = XOpenDisplay(NULL); - } - - XSetWindowAttributes wa; - wa.event_mask = StructureNotifyMask; - wa.override_redirect = True; - Window win = XCreateWindow(s_display, - p_window, - x, - y, - width, - height, - 0, - CopyFromParent, - CopyFromParent, - CopyFromParent, - CWEventMask, - &wa); - XMapWindow(s_display,win); - XSetWindowBackground(s_display, win, BlackPixel(s_display, 0)); - XEvent e; - XIfEvent(s_display, &e, WaitForMapNotify, (char *)win); - return win; -} - -void destroySubWindow(EGLNativeWindowType win) { - if (!s_display) { - return; - } - XDestroyWindow(s_display, win); -} - -int moveSubWindow(FBNativeWindowType p_parent_window, - EGLNativeWindowType p_sub_window, - int x, - int y, - int width, - int height) { - // This value is set during create, so if it is still null, simply - // return because the global state is corrupted - if (!s_display) { - return false; - } - - // This prevents flicker on resize. - XSetWindowBackgroundPixmap(s_display, p_sub_window, None); - - int ret = XMoveResizeWindow( - s_display, - p_sub_window, - x, - y, - width, - height); - - XEvent e; - XIfEvent(s_display, &e, WaitForConfigureNotify, (char *)p_sub_window); - - return ret; -} diff --git a/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.cpp b/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.cpp deleted file mode 100644 index 81ee202..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* -* Copyright (C) 2011 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 "Win32PipeStream.h" - -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#error ONLY BUILD THIS SOURCE FILE FOR WINDOWS! -#endif - -/* The official documentation states that the name of a given named - * pipe cannot be more than 256 characters long. - */ -#define NAMED_PIPE_MAX 256 - -Win32PipeStream::Win32PipeStream(size_t bufSize) : - SocketStream(bufSize), - m_pipe(INVALID_HANDLE_VALUE) -{ -} - -Win32PipeStream::Win32PipeStream(HANDLE pipe, size_t bufSize) : - SocketStream(-1, bufSize), - m_pipe(pipe) -{ -} - -Win32PipeStream::~Win32PipeStream() -{ - if (m_pipe != INVALID_HANDLE_VALUE) { - CloseHandle(m_pipe); - m_pipe = INVALID_HANDLE_VALUE; - } -} - -/* Initialize the pipe name corresponding to a given port - */ -static void -make_pipe_name(char *path, size_t pathlen, int port_number) -{ - snprintf(path, pathlen, "\\\\.\\pipe\\qemu-gles-%d", port_number); -} - - -/* Technical note: Named pipes work differently from BSD Sockets. - * One does not create/bind a pipe, and collect a new handle each - * time a client connects with accept(). - * - * Instead, the server creates a new pipe instance each time it wants - * to get a new client connection, then calls ConnectNamedPipe() to - * wait for a connection. - * - * So listen() is a no-op, and accept() really creates the pipe handle. - * - * Also, connect() must create a pipe handle with CreateFile() and - * wait for a server instance with WaitNamedPipe() - */ -int Win32PipeStream::listen(char addrstr[MAX_ADDRSTR_LEN]) -{ - m_port = GetCurrentProcessId(); - make_pipe_name(addrstr, MAX_ADDRSTR_LEN, m_port); - return 0; -} - -SocketStream * Win32PipeStream::accept() -{ - char path[NAMED_PIPE_MAX+1]; - SocketStream* clientStream; - HANDLE pipe; - - make_pipe_name(path, sizeof(path), m_port); - - pipe = ::CreateNamedPipe( - path, // pipe name - PIPE_ACCESS_DUPLEX, // read-write access - PIPE_TYPE_BYTE | // byte-oriented writes - PIPE_READMODE_BYTE | // byte-oriented reads - PIPE_WAIT, // blocking operations - PIPE_UNLIMITED_INSTANCES, // no limit on clients - 4096, // input buffer size - 4096, // output buffer size - 0, // client time-out - NULL); // default security attributes - - if (pipe == INVALID_HANDLE_VALUE) { - ERR("%s: CreateNamedPipe failed %d\n", __FUNCTION__, (int)GetLastError()); - return NULL; - } - - // Stupid Win32 API design: If a client is already connected, then - // ConnectNamedPipe will return 0, and GetLastError() will return - // ERROR_PIPE_CONNECTED. This is not an error! It just means that the - // function didn't have to wait. - // - if (::ConnectNamedPipe(pipe, NULL) == 0 && GetLastError() != ERROR_PIPE_CONNECTED) { - ERR("%s: ConnectNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); - CloseHandle(pipe); - return NULL; - } - - clientStream = new Win32PipeStream(pipe, m_bufsize); - return clientStream; -} - -int Win32PipeStream::connect(const char* addr) -{ - HANDLE pipe; - int tries = 10; - - /* We're going to loop in order to wait for the pipe server to - * be setup properly. - */ - for (; tries > 0; tries--) { - pipe = ::CreateFile( - addr, // pipe name - GENERIC_READ | GENERIC_WRITE, // read & write - 0, // no sharing - NULL, // default security attrs - OPEN_EXISTING, // open existing pipe - 0, // default attributes - NULL); // no template file - - /* If we have a valid pipe handle, break from the loop */ - if (pipe != INVALID_HANDLE_VALUE) { - break; - } - - /* We can get here if the pipe is busy, i.e. if the server hasn't - * create a new pipe instance to service our request. In which case - * GetLastError() will return ERROR_PIPE_BUSY. - * - * If so, then use WaitNamedPipe() to wait for a decent time - * to try again. - */ - if (GetLastError() != ERROR_PIPE_BUSY) { - /* Not ERROR_PIPE_BUSY */ - ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError()); - errno = EINVAL; - return -1; - } - - /* Wait for 5 seconds */ - if ( !WaitNamedPipe(addr, 5000) ) { - ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); - errno = EINVAL; - return -1; - } - } - - m_pipe = pipe; - return 0; -} - -/* Special buffer methods, since we can't use socket functions here */ - -int Win32PipeStream::commitBuffer(size_t size) -{ - if (m_pipe == INVALID_HANDLE_VALUE) - return -1; - - size_t res = size; - int retval = 0; - - while (res > 0) { - DWORD written; - if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) { - retval = -1; - ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError()); - break; - } - res -= written; - } - return retval; -} - -const unsigned char *Win32PipeStream::readFully(void *buf, size_t len) -{ - if (m_pipe == INVALID_HANDLE_VALUE) - return NULL; - - if (!buf) { - return NULL; // do not allow NULL buf in that implementation - } - - size_t res = len; - while (res > 0) { - DWORD readcount = 0; - if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) { - errno = (int)GetLastError(); - return NULL; - } - res -= readcount; - } - return (const unsigned char *)buf; -} - -const unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len) -{ - size_t len = *inout_len; - DWORD readcount; - - if (m_pipe == INVALID_HANDLE_VALUE) - return NULL; - - if (!buf) { - return NULL; // do not allow NULL buf in that implementation - } - - if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) { - errno = (int)GetLastError(); - return NULL; - } - - *inout_len = (size_t)readcount; - return (const unsigned char *)buf; -} - -void Win32PipeStream::forceStop() -{ - HANDLE handle = m_pipe; - m_pipe = INVALID_HANDLE_VALUE; - CloseHandle(handle); -} diff --git a/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.h b/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.h deleted file mode 100644 index be44074..0000000 --- a/external/android-emugl/host/libs/libOpenglRender/Win32PipeStream.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright (C) 2011 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. -*/ -#ifndef __WIN32_PIPE_STREAM_H -#define __WIN32_PIPE_STREAM_H - -#include "SocketStream.h" -#include - -class Win32PipeStream : public SocketStream { -public: - explicit Win32PipeStream(size_t bufsize = 10000); - virtual ~Win32PipeStream(); - virtual int listen(char addrstr[MAX_ADDRSTR_LEN]); - virtual SocketStream *accept(); - virtual int connect(const char* addr); - - virtual int commitBuffer(size_t size); - virtual const unsigned char *readFully(void *buf, size_t len); - virtual const unsigned char *read(void *buf, size_t *inout_len); - virtual void forceStop(); - -private: - Win32PipeStream(HANDLE pipe, size_t bufSize); - HANDLE m_pipe; - int m_port; -}; - - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91035db..5a4aaed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,17 @@ include_directories( ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include + ${CMAKE_SOURCE_DIR}/external/android-emugl/shared ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include + ${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include/libOpenglRender + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv1_dec + ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv1_dec + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv2_dec + ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv2_dec + ${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/renderControl_dec + ${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/renderControl_dec ) protobuf_generate_cpp( @@ -97,6 +107,29 @@ set(SOURCES anbox/graphics/density.h anbox/graphics/rect.cpp + anbox/graphics/emugl/ColorBuffer.cpp + anbox/graphics/emugl/DisplayManager.cpp + anbox/graphics/emugl/FbConfig.cpp + anbox/graphics/emugl/FrameBuffer.cpp + anbox/graphics/emugl/LayerManager.cpp + anbox/graphics/emugl/NativeSubWindow_delegate.cpp + anbox/graphics/emugl/NativeSubWindow.h + anbox/graphics/emugl/ReadBuffer.cpp + anbox/graphics/emugl/RenderApi.cpp + anbox/graphics/emugl/RenderContext.cpp + anbox/graphics/emugl/RenderControl.cpp + anbox/graphics/emugl/RenderServer.cpp + anbox/graphics/emugl/RenderThread.cpp + anbox/graphics/emugl/RenderThreadInfo.cpp + anbox/graphics/emugl/RenderWindow.cpp + anbox/graphics/emugl/SocketStream.cpp + anbox/graphics/emugl/TcpStream.cpp + anbox/graphics/emugl/TextureDraw.cpp + anbox/graphics/emugl/TextureResize.cpp + anbox/graphics/emugl/TimeUtils.cpp + anbox/graphics/emugl/UnixStream.cpp + anbox/graphics/emugl/WindowSurface.cpp + anbox/wm/display.cpp anbox/wm/task.cpp anbox/wm/manager.cpp @@ -150,7 +183,12 @@ target_link_libraries(anbox-core ${LXC_LIBRARIES} pthread process-cpp - OpenglRender + emugl_common + GLESv1_dec + GLESv2_dec + renderControl_dec + OpenGLESDispatch + OpenglCodecCommon anbox-protobuf) add_executable(anbox main.cpp) diff --git a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp b/src/anbox/graphics/emugl/ColorBuffer.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/ColorBuffer.cpp rename to src/anbox/graphics/emugl/ColorBuffer.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/ColorBuffer.h b/src/anbox/graphics/emugl/ColorBuffer.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/ColorBuffer.h rename to src/anbox/graphics/emugl/ColorBuffer.h diff --git a/external/android-emugl/host/libs/libOpenglRender/DispatchTables.h b/src/anbox/graphics/emugl/DispatchTables.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/DispatchTables.h rename to src/anbox/graphics/emugl/DispatchTables.h diff --git a/external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp b/src/anbox/graphics/emugl/DisplayManager.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/DisplayManager.cpp rename to src/anbox/graphics/emugl/DisplayManager.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/DisplayManager.h b/src/anbox/graphics/emugl/DisplayManager.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/DisplayManager.h rename to src/anbox/graphics/emugl/DisplayManager.h diff --git a/external/android-emugl/host/libs/libOpenglRender/FbConfig.cpp b/src/anbox/graphics/emugl/FbConfig.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/FbConfig.cpp rename to src/anbox/graphics/emugl/FbConfig.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/FbConfig.h b/src/anbox/graphics/emugl/FbConfig.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/FbConfig.h rename to src/anbox/graphics/emugl/FbConfig.h diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp b/src/anbox/graphics/emugl/FrameBuffer.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/FrameBuffer.cpp rename to src/anbox/graphics/emugl/FrameBuffer.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h b/src/anbox/graphics/emugl/FrameBuffer.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/FrameBuffer.h rename to src/anbox/graphics/emugl/FrameBuffer.h diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp b/src/anbox/graphics/emugl/LayerManager.cpp similarity index 87% rename from external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp rename to src/anbox/graphics/emugl/LayerManager.cpp index f2c0a97..ab2e74c 100644 --- a/external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp +++ b/src/anbox/graphics/emugl/LayerManager.cpp @@ -38,6 +38,7 @@ bool is_layer_blacklisted(const std::string &name) { "com.android.settings/com.android.settings.FallbackHome", "com.android.systemui.ImageWallpaper", "InputMethod", + "com.android.quicksearchbox/com.android.quicksearchbox.SearchActivity", }; return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end(); } @@ -87,6 +88,16 @@ void LayerManager::post_layer(const LayerInfo &layer) { auto height = layer.display_frame.bottom - layer.display_frame.top; if (!window) { + printf("New layer '%s' display_frame={%d,%d,%d,%d} source_crop={%d,%d,%d,%d}\n", + layer.name.c_str(), + layer.display_frame.left, + layer.display_frame.top, + layer.display_frame.right, + layer.display_frame.bottom, + layer.source_crop.left, + layer.source_crop.top, + layer.source_crop.right, + layer.source_crop.bottom); window = FrameBuffer::getFB()->createWindow(layer.display_frame.left, layer.display_frame.top, @@ -95,6 +106,7 @@ void LayerManager::post_layer(const LayerInfo &layer) { printf("Failed to create window for layer '%s'\n", layer.name.c_str()); return; } + layers_.insert({ layer.name, Layer{window, true}}); } diff --git a/external/android-emugl/host/libs/libOpenglRender/LayerManager.h b/src/anbox/graphics/emugl/LayerManager.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/LayerManager.h rename to src/anbox/graphics/emugl/LayerManager.h diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h b/src/anbox/graphics/emugl/NativeSubWindow.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h rename to src/anbox/graphics/emugl/NativeSubWindow.h diff --git a/external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp b/src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/NativeSubWindow_delegate.cpp rename to src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/ReadBuffer.cpp b/src/anbox/graphics/emugl/ReadBuffer.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/ReadBuffer.cpp rename to src/anbox/graphics/emugl/ReadBuffer.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/ReadBuffer.h b/src/anbox/graphics/emugl/ReadBuffer.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/ReadBuffer.h rename to src/anbox/graphics/emugl/ReadBuffer.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp b/src/anbox/graphics/emugl/RenderApi.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderApi.cpp rename to src/anbox/graphics/emugl/RenderApi.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderContext.cpp b/src/anbox/graphics/emugl/RenderContext.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderContext.cpp rename to src/anbox/graphics/emugl/RenderContext.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderContext.h b/src/anbox/graphics/emugl/RenderContext.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderContext.h rename to src/anbox/graphics/emugl/RenderContext.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderControl.cpp rename to src/anbox/graphics/emugl/RenderControl.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderControl.h b/src/anbox/graphics/emugl/RenderControl.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderControl.h rename to src/anbox/graphics/emugl/RenderControl.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderServer.cpp b/src/anbox/graphics/emugl/RenderServer.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderServer.cpp rename to src/anbox/graphics/emugl/RenderServer.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderServer.h b/src/anbox/graphics/emugl/RenderServer.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderServer.h rename to src/anbox/graphics/emugl/RenderServer.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp similarity index 72% rename from external/android-emugl/host/libs/libOpenglRender/RenderThread.cpp rename to src/anbox/graphics/emugl/RenderThread.cpp index 22cd9e2..db9c6a9 100644 --- a/external/android-emugl/host/libs/libOpenglRender/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -59,25 +59,6 @@ intptr_t RenderThread::main() { ReadBuffer readBuf(STREAM_BUFFER_SIZE); - int stats_totalBytes = 0; - long long stats_t0 = GetCurrentTimeMS(); - - // - // open dump file if RENDER_DUMP_DIR is defined - // - const char *dump_dir = getenv("RENDERER_DUMP_DIR"); - FILE *dumpFP = NULL; - if (dump_dir) { - size_t bsize = strlen(dump_dir) + 32; - char *fname = new char[bsize]; - snprintf(fname,bsize,"%s/stream_%p", dump_dir, this); - dumpFP = fopen(fname, "wb"); - if (!dumpFP) { - fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname); - } - delete [] fname; - } - while (1) { int stat = readBuf.getData(m_stream); @@ -85,29 +66,6 @@ intptr_t RenderThread::main() { break; } -#if 0 - // - // log received bandwidth statistics - // - stats_totalBytes += readBuf.validData(); - long long dt = GetCurrentTimeMS() - stats_t0; - if (dt > 1000) { - float dts = (float)dt / 1000.0f; - printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f)); - stats_totalBytes = 0; - stats_t0 = GetCurrentTimeMS(); - } -#endif - - // - // dump stream to file if needed - // - if (dumpFP) { - int skip = readBuf.validData() - stat; - fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP); - fflush(dumpFP); - } - bool progress; do { progress = false; @@ -147,10 +105,6 @@ intptr_t RenderThread::main() { } - if (dumpFP) { - fclose(dumpFP); - } - // // Release references to the current thread's context/surfaces if any // diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderThread.h b/src/anbox/graphics/emugl/RenderThread.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderThread.h rename to src/anbox/graphics/emugl/RenderThread.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderThreadInfo.cpp b/src/anbox/graphics/emugl/RenderThreadInfo.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderThreadInfo.cpp rename to src/anbox/graphics/emugl/RenderThreadInfo.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderThreadInfo.h b/src/anbox/graphics/emugl/RenderThreadInfo.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderThreadInfo.h rename to src/anbox/graphics/emugl/RenderThreadInfo.h diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp b/src/anbox/graphics/emugl/RenderWindow.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderWindow.cpp rename to src/anbox/graphics/emugl/RenderWindow.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/RenderWindow.h b/src/anbox/graphics/emugl/RenderWindow.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/RenderWindow.h rename to src/anbox/graphics/emugl/RenderWindow.h diff --git a/external/android-emugl/host/libs/libOpenglRender/SocketStream.cpp b/src/anbox/graphics/emugl/SocketStream.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/SocketStream.cpp rename to src/anbox/graphics/emugl/SocketStream.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/SocketStream.h b/src/anbox/graphics/emugl/SocketStream.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/SocketStream.h rename to src/anbox/graphics/emugl/SocketStream.h diff --git a/external/android-emugl/host/libs/libOpenglRender/TcpStream.cpp b/src/anbox/graphics/emugl/TcpStream.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TcpStream.cpp rename to src/anbox/graphics/emugl/TcpStream.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/TcpStream.h b/src/anbox/graphics/emugl/TcpStream.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TcpStream.h rename to src/anbox/graphics/emugl/TcpStream.h diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp b/src/anbox/graphics/emugl/TextureDraw.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TextureDraw.cpp rename to src/anbox/graphics/emugl/TextureDraw.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureDraw.h b/src/anbox/graphics/emugl/TextureDraw.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TextureDraw.h rename to src/anbox/graphics/emugl/TextureDraw.h diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureResize.cpp b/src/anbox/graphics/emugl/TextureResize.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TextureResize.cpp rename to src/anbox/graphics/emugl/TextureResize.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/TextureResize.h b/src/anbox/graphics/emugl/TextureResize.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TextureResize.h rename to src/anbox/graphics/emugl/TextureResize.h diff --git a/external/android-emugl/host/libs/libOpenglRender/TimeUtils.cpp b/src/anbox/graphics/emugl/TimeUtils.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TimeUtils.cpp rename to src/anbox/graphics/emugl/TimeUtils.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/TimeUtils.h b/src/anbox/graphics/emugl/TimeUtils.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/TimeUtils.h rename to src/anbox/graphics/emugl/TimeUtils.h diff --git a/external/android-emugl/host/libs/libOpenglRender/UnixStream.cpp b/src/anbox/graphics/emugl/UnixStream.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/UnixStream.cpp rename to src/anbox/graphics/emugl/UnixStream.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/UnixStream.h b/src/anbox/graphics/emugl/UnixStream.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/UnixStream.h rename to src/anbox/graphics/emugl/UnixStream.h diff --git a/external/android-emugl/host/libs/libOpenglRender/WindowSurface.cpp b/src/anbox/graphics/emugl/WindowSurface.cpp similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/WindowSurface.cpp rename to src/anbox/graphics/emugl/WindowSurface.cpp diff --git a/external/android-emugl/host/libs/libOpenglRender/WindowSurface.h b/src/anbox/graphics/emugl/WindowSurface.h similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/WindowSurface.h rename to src/anbox/graphics/emugl/WindowSurface.h diff --git a/external/android-emugl/host/libs/libOpenglRender/render_api.entries b/src/anbox/graphics/emugl/render_api.entries similarity index 100% rename from external/android-emugl/host/libs/libOpenglRender/render_api.entries rename to src/anbox/graphics/emugl/render_api.entries From 3e6ac64cd08cc5f14576ed4a38bc9650890c9aaf Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 14:02:15 +0100 Subject: [PATCH 32/54] Drop several win32 specifics from the emugl layer --- src/anbox/graphics/emugl/RenderServer.cpp | 15 ---------- src/anbox/graphics/emugl/RenderWindow.cpp | 4 --- src/anbox/graphics/emugl/SocketStream.cpp | 17 ----------- src/anbox/graphics/emugl/TcpStream.cpp | 4 --- src/anbox/graphics/emugl/TimeUtils.cpp | 36 +---------------------- 5 files changed, 1 insertion(+), 75 deletions(-) diff --git a/src/anbox/graphics/emugl/RenderServer.cpp b/src/anbox/graphics/emugl/RenderServer.cpp index bb09a40..63e211c 100644 --- a/src/anbox/graphics/emugl/RenderServer.cpp +++ b/src/anbox/graphics/emugl/RenderServer.cpp @@ -17,14 +17,9 @@ #include "RenderThread.h" #include "TcpStream.h" -#ifndef _WIN32 #include "UnixStream.h" #include #include -#endif -#ifdef _WIN32 -#include "Win32PipeStream.h" -#endif #include "OpenglRender/render_api.h" @@ -59,11 +54,7 @@ RenderServer *RenderServer::create(char* addr, size_t addrLen) if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) { server->m_listenSock = new TcpStream(); } else { -#ifdef _WIN32 - server->m_listenSock = new Win32PipeStream(); -#else server->m_listenSock = new UnixStream(); -#endif } char addrstr[SocketStream::MAX_ADDRSTR_LEN]; @@ -89,12 +80,6 @@ intptr_t RenderServer::main() { RenderThreadsSet threads; -#ifndef _WIN32 - sigset_t set; - sigfillset(&set); - pthread_sigmask(SIG_SETMASK, &set, NULL); -#endif - while(1) { SocketStream *stream = m_listenSock->accept(); if (!stream) { diff --git a/src/anbox/graphics/emugl/RenderWindow.cpp b/src/anbox/graphics/emugl/RenderWindow.cpp index 9916203..630d966 100644 --- a/src/anbox/graphics/emugl/RenderWindow.cpp +++ b/src/anbox/graphics/emugl/RenderWindow.cpp @@ -22,10 +22,8 @@ #include #include -#ifndef _WIN32 #include #include -#endif #define DEBUG 0 @@ -214,11 +212,9 @@ public: virtual intptr_t main() { D("Entering render window thread thread\n"); -#ifndef _WIN32 sigset_t set; sigfillset(&set); pthread_sigmask(SIG_SETMASK, &set, NULL); -#endif bool running = true; while (running) { RenderWindowMessage msg; diff --git a/src/anbox/graphics/emugl/SocketStream.cpp b/src/anbox/graphics/emugl/SocketStream.cpp index 3121e81..24f5436 100644 --- a/src/anbox/graphics/emugl/SocketStream.cpp +++ b/src/anbox/graphics/emugl/SocketStream.cpp @@ -19,14 +19,9 @@ #include #include #include - -#ifndef _WIN32 #include #include #include -#else -#include -#endif SocketStream::SocketStream(size_t bufSize) : IOStream(bufSize), @@ -48,10 +43,8 @@ SocketStream::~SocketStream() { if (m_sock >= 0) { forceStop(); -#ifndef _WIN32 if(close(m_sock) < 0) perror("Closing SocketStream failed"); -#endif // DBG("SocketStream::~close @ %d \n", m_sock); m_sock = -1; } @@ -169,15 +162,5 @@ int SocketStream::recv(void *buf, size_t len) void SocketStream::forceStop() { // Shutdown socket to force read/write errors. -#ifdef _WIN32 - ::shutdown(m_sock, SD_BOTH); - // As documented by programmers on MSDN, shutdown implementation in Windows does - // NOT result to unblocking threads that are blocked on a recv on the socket - // being shut down. The only way to actually implement this behavior (expected - // by this forceStop() implementation) is to rudely close the socket. - ::closesocket(m_sock); - m_sock = -1; -#else ::shutdown(m_sock, SHUT_RDWR); -#endif } diff --git a/src/anbox/graphics/emugl/TcpStream.cpp b/src/anbox/graphics/emugl/TcpStream.cpp index ba355ab..de97c02 100644 --- a/src/anbox/graphics/emugl/TcpStream.cpp +++ b/src/anbox/graphics/emugl/TcpStream.cpp @@ -22,12 +22,8 @@ #include #include -#ifndef _WIN32 #include #include -#else -#include -#endif #define LISTEN_BACKLOG 4 diff --git a/src/anbox/graphics/emugl/TimeUtils.cpp b/src/anbox/graphics/emugl/TimeUtils.cpp index 50aeb03..1a7fbf9 100644 --- a/src/anbox/graphics/emugl/TimeUtils.cpp +++ b/src/anbox/graphics/emugl/TimeUtils.cpp @@ -15,55 +15,21 @@ */ #include "TimeUtils.h" -#ifdef _WIN32 -#include -#include -#include -#elif defined(__linux__) + #include #include #include #include -#else -#include -#include -#endif long long GetCurrentTimeMS() { -#ifdef _WIN32 - static LARGE_INTEGER freq; - static bool bNotInit = true; - if ( bNotInit ) { - bNotInit = (QueryPerformanceFrequency( &freq ) == FALSE); - } - LARGE_INTEGER currVal; - QueryPerformanceCounter( &currVal ); - - return currVal.QuadPart / (freq.QuadPart / 1000); - -#elif defined(__linux__) - struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); long long iDiff = (now.tv_sec * 1000LL) + now.tv_nsec/1000000LL; return iDiff; - -#else /* Others, e.g. OS X */ - - struct timeval now; - gettimeofday(&now, NULL); - long long iDiff = (now.tv_sec * 1000LL) + now.tv_usec/1000LL; - return iDiff; - -#endif } void TimeSleepMS(int p_mili) { -#ifdef _WIN32 - Sleep(p_mili); -#else usleep(p_mili * 1000); -#endif } From 9d7c565239f2fdca5239af105b7b31368c0c14fe Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 15 Nov 2016 15:09:30 +0100 Subject: [PATCH 33/54] Correct wrong includes --- src/anbox/graphics/window_creator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/anbox/graphics/window_creator.h b/src/anbox/graphics/window_creator.h index 66d3c23..9e1b79f 100644 --- a/src/anbox/graphics/window_creator.h +++ b/src/anbox/graphics/window_creator.h @@ -18,8 +18,8 @@ #ifndef ANBOX_GRAPHICS_WINDOW_CREATOR_H_ #define ANBOX_GRAPHICS_WINDOW_CREATOR_H_ -#include "external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h" -#include "external/android-emugl/host/libs/libOpenglRender/DisplayManager.h" +#include "anbox/graphics/emugl/NativeSubWindow.h" +#include "anbox/graphics/emugl/DisplayManager.h" namespace anbox { namespace input { From 3e126fb252ef0b76616837e455f492e87e3189ab Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 16 Nov 2016 10:29:26 +0100 Subject: [PATCH 34/54] Integrate RenderThread directly into our message processor --- src/anbox/cmds/run.cpp | 4 +- src/anbox/graphics/gl_renderer_server.cpp | 22 +-- src/anbox/graphics/gl_renderer_server.h | 3 - .../graphics/opengles_message_processor.cpp | 146 +++++++++++++++--- .../graphics/opengles_message_processor.h | 16 +- src/anbox/qemu/pipe_connection_creator.cpp | 12 +- src/anbox/qemu/pipe_connection_creator.h | 8 +- 7 files changed, 141 insertions(+), 70 deletions(-) diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index e65ce28..01bc29f 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -109,9 +109,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto qemu_pipe_connector = std::make_shared( utils::string_format("%s/qemu_pipe", config::socket_path()), rt, - std::make_shared(rt, - renderer->socket_path(), - icon_)); + std::make_shared(rt)); auto android_api_stub = std::make_shared(); diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index e7cc739..00d8ec1 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -18,6 +18,7 @@ #include "anbox/logger.h" #include "anbox/graphics/gl_renderer_server.h" #include "anbox/graphics/window_creator.h" +#include "anbox/graphics/emugl/FrameBuffer.h" #include "OpenglRender/render_api.h" @@ -50,8 +51,8 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &window_ } GLRendererServer::~GLRendererServer() { - // destroyOpenGLSubwindow(); - stopOpenGLRenderer(); + if (const auto fb = FrameBuffer::getFB()) + fb->finalize(); } void logger_write(const char *format, ...) { @@ -70,22 +71,7 @@ void GLRendererServer::start() { log_funcs.coarse = logger_write; log_funcs.fine = logger_write; - auto display_info = window_creator_->display_info(); - const auto width = display_info.horizontal_resolution; - const auto height = display_info.vertical_resolution; - - char server_addr[256] = { 0 }; - // The width & height we supply here are the dimensions the internal framebuffer - // will use. Making this static prevents us for now to resize the window we create - // later for the actual display. - if (!initOpenGLRenderer(window_creator_->native_display(), server_addr, sizeof(server_addr), log_funcs, logger_write)) - BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); - - socket_path_ = server_addr; -} - -std::string GLRendererServer::socket_path() const { - return socket_path_; + FrameBuffer::initialize(window_creator_->native_display()); } } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index 4b5fad9..3dedb36 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -34,10 +34,7 @@ public: void start(); - std::string socket_path() const; - private: - std::string socket_path_; std::shared_ptr window_creator_; }; diff --git a/src/anbox/graphics/opengles_message_processor.cpp b/src/anbox/graphics/opengles_message_processor.cpp index 6f5a26d..3452eff 100644 --- a/src/anbox/graphics/opengles_message_processor.cpp +++ b/src/anbox/graphics/opengles_message_processor.cpp @@ -20,39 +20,139 @@ #include "anbox/network/local_socket_messenger.h" #include "anbox/network/connections.h" #include "anbox/network/delegate_message_processor.h" +#include "anbox/graphics/emugl/RenderThread.h" + +#include "external/android-emugl/host/include/libOpenglRender/IOStream.h" + +#include +#include + +namespace { +class DirectIOStream : public IOStream { +public: + explicit DirectIOStream(const std::shared_ptr &messenger, + const size_t &buffer_size = 10000) : + IOStream(buffer_size), + messenger_(messenger) { + } + + virtual ~DirectIOStream() { + if (send_buffer_ != nullptr) { + free(send_buffer_); + send_buffer_ = nullptr; + } + } + + void* allocBuffer(size_t min_size) override { + size_t size = (send_buffer_size_ < min_size ? min_size : send_buffer_size_); + if (!send_buffer_) + send_buffer_ = (unsigned char *) malloc(size); + else if (send_buffer_size_ < size) { + unsigned char *p = (unsigned char *)realloc(send_buffer_, size); + if (p != NULL) { + send_buffer_ = p; + send_buffer_size_ = size; + } else { + free(send_buffer_); + send_buffer_ = NULL; + send_buffer_size_ = 0; + } + } + return send_buffer_; + } + + int commitBuffer(size_t size) override { + messenger_->send(reinterpret_cast(send_buffer_), size); + return size; + } + + const unsigned char* readFully(void*, size_t) override { + ERROR("Not implemented"); + return nullptr; + } + + const unsigned char* read(void *data, size_t *size) override { + if (!wait_for_data() || buffer_.size() == 0) { + *size = 0; + return nullptr; + } + + auto bytes_to_read = *size; + if (bytes_to_read > buffer_.size()) + bytes_to_read = buffer_.size(); + + ::memcpy(data, buffer_.data(), bytes_to_read); + buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_read); + + *size = bytes_to_read; + + return static_cast(data); + } + + int writeFully(const void*, size_t) override { + ERROR("Not implemented"); + return 0; + } + + void forceStop() override { + std::unique_lock l(mutex_); + buffer_.clear(); + } + + void submitData(const std::vector &data) { + std::unique_lock l(mutex_); + for (const auto &byte : data) + buffer_.push_back(byte); + // buffer_.insert(buffer_.end(), data.begin(), data.end()); + lock_.notify_one(); + } + +private: + bool wait_for_data() { + std::unique_lock l(mutex_); + + if (!l.owns_lock()) + return false; + + lock_.wait(l, [&]() { return !buffer_.empty(); }); + return true; + } + + std::shared_ptr messenger_; + std::mutex mutex_; + std::condition_variable lock_; + std::vector buffer_; + unsigned char *send_buffer_ = nullptr; + size_t send_buffer_size_ = 0; +}; +} namespace anbox { namespace graphics { -OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::string &renderer_socket_path, - const std::shared_ptr &rt, - const std::shared_ptr &messenger) : - client_messenger_(messenger) { +emugl::Mutex OpenGlesMessageProcessor::global_lock{}; - connect_and_attach(renderer_socket_path, rt); +OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::shared_ptr &messenger) : + messenger_(messenger), + stream_(std::make_shared(messenger_)), + renderer_(RenderThread::create(stream_.get(), &global_lock)) { + + // We have to read the client flags first before we can continue + // processing the actual commands + std::array buffer; + messenger_->receive_msg(boost::asio::buffer(buffer)); + + renderer_->start(); } OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { -} - -void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path, - const std::shared_ptr &rt) { - - auto socket = std::make_shared(rt->service()); - socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path)); - - messenger_ = std::make_shared(socket); - renderer_ = std::make_shared( - messenger_, messenger_, 0, nullptr, - std::make_shared([&](const std::vector &data) { - client_messenger_->send(reinterpret_cast(data.data()), data.size()); - return true; - })); - renderer_->set_name("opengles-renderer"); - renderer_->read_next_message(); + DEBUG(""); + renderer_->forceStop(); + renderer_->wait(nullptr); } bool OpenGlesMessageProcessor::process_data(const std::vector &data) { - messenger_->send(reinterpret_cast(data.data()), data.size()); + auto stream = std::static_pointer_cast(stream_); + stream->submitData(data); return true; } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.h b/src/anbox/graphics/opengles_message_processor.h index 05612cf..374af97 100644 --- a/src/anbox/graphics/opengles_message_processor.h +++ b/src/anbox/graphics/opengles_message_processor.h @@ -27,24 +27,26 @@ #include "anbox/network/socket_messenger.h" #include "anbox/network/socket_connection.h" +#include "external/android-emugl/shared/emugl/common/mutex.h" + +class IOStream; +class RenderThread; + namespace anbox { namespace graphics { class OpenGlesMessageProcessor : public network::MessageProcessor { public: - OpenGlesMessageProcessor(const std::string &renderer_socket_path, - const std::shared_ptr &rt, - const std::shared_ptr &messenger); + OpenGlesMessageProcessor(const std::shared_ptr &messenger); ~OpenGlesMessageProcessor(); bool process_data(const std::vector &data) override; private: - void connect_and_attach(const std::string &socket_path, - const std::shared_ptr &rt); + static emugl::Mutex global_lock; - std::shared_ptr client_messenger_; std::shared_ptr messenger_; - std::shared_ptr renderer_; + std::shared_ptr stream_; + std::shared_ptr renderer_; }; } // namespace graphics } // namespace anbox diff --git a/src/anbox/qemu/pipe_connection_creator.cpp b/src/anbox/qemu/pipe_connection_creator.cpp index 5d81e89..7c31eb3 100644 --- a/src/anbox/qemu/pipe_connection_creator.cpp +++ b/src/anbox/qemu/pipe_connection_creator.cpp @@ -62,14 +62,10 @@ std::string client_type_to_string(const anbox::qemu::PipeConnectionCreator::clie } namespace anbox { namespace qemu { -PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &rt, - const std::string &renderer_socket_path, - const std::string &boot_animation_icon_path) : +PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &rt) : runtime_(rt), next_connection_id_(0), - connections_(std::make_shared>()), - renderer_socket_path_(renderer_socket_path), - boot_animation_icon_path_(boot_animation_icon_path) { + connections_(std::make_shared>()) { } PipeConnectionCreator::~PipeConnectionCreator() { @@ -137,7 +133,7 @@ PipeConnectionCreator::client_type PipeConnectionCreator::identify_client( std::shared_ptr PipeConnectionCreator::create_processor(const client_type &type, const std::shared_ptr &messenger) { if (type == client_type::opengles) - return std::make_shared(renderer_socket_path_, runtime_, messenger); + return std::make_shared(messenger); else if (type == client_type::qemud_boot_properties) return std::make_shared(messenger); else if (type == client_type::qemud_hw_control) @@ -150,8 +146,6 @@ std::shared_ptr PipeConnectionCreator::create_process return std::make_shared(messenger); else if (type == client_type::qemud_gsm) return std::make_shared(messenger); - else if (type == client_type::bootanimation) - return std::make_shared(messenger, boot_animation_icon_path_); else if (type == client_type::qemud_adb) return std::make_shared(runtime_, messenger); diff --git a/src/anbox/qemu/pipe_connection_creator.h b/src/anbox/qemu/pipe_connection_creator.h index 391fedf..e652e58 100644 --- a/src/anbox/qemu/pipe_connection_creator.h +++ b/src/anbox/qemu/pipe_connection_creator.h @@ -33,10 +33,7 @@ namespace anbox { namespace qemu { class PipeConnectionCreator : public network::ConnectionCreator { public: - PipeConnectionCreator( - const std::shared_ptr &rt, - const std::string &renderer_socket_path, - const std::string &boot_animation_icon_path); + PipeConnectionCreator(const std::shared_ptr &rt); ~PipeConnectionCreator() noexcept; void create_connection_for( @@ -65,9 +62,6 @@ private: std::shared_ptr runtime_; std::atomic next_connection_id_; std::shared_ptr> const connections_; - - std::string renderer_socket_path_; - std::string boot_animation_icon_path_; }; } // namespace qemu } // namespace anbox From e0ce4baa75f5c06aaf5756a16fe921c4827fc22d Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 16 Nov 2016 14:04:48 +0100 Subject: [PATCH 35/54] Read missing window count from message --- android/service/platform_service.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp index d8c9823..2c80f9b 100644 --- a/android/service/platform_service.cpp +++ b/android/service/platform_service.cpp @@ -66,6 +66,7 @@ status_t PlatformService::update_window_state(const Parcel &data) { const auto num_displays = data.readInt32(); for (auto n = 0; n < num_displays; n++) { const auto display_id = data.readInt32(); + const auto num_windows = data.readInt32(); for (auto m = 0; m < num_windows; m++) { auto window = window_state.add_windows(); From 91d37082ab008e3e3d1cae21ac285a01eb57fbd8 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 12:53:27 +0100 Subject: [PATCH 36/54] First attempt on getting rid of the socket server --- external/android-emugl/CMakeLists.txt | 1 + .../host/include/libOpenglRender/IOStream.h | 4 +- .../host/libs/GLESv1_dec/CMakeLists.txt | 2 +- .../host/libs/GLESv2_dec/CMakeLists.txt | 2 +- .../libs/renderControl_dec/CMakeLists.txt | 2 +- src/anbox/graphics/emugl/ColorBuffer.cpp | 5 + src/anbox/graphics/emugl/FrameBuffer.cpp | 8 + src/anbox/graphics/emugl/LayerManager.cpp | 4 +- src/anbox/graphics/emugl/RenderApi.cpp | 55 ---- src/anbox/graphics/emugl/RenderControl.cpp | 5 + src/anbox/graphics/emugl/RenderThread.cpp | 51 ++-- src/anbox/graphics/gl_renderer_server.cpp | 3 + .../graphics/opengles_message_processor.cpp | 238 +++++++++++++----- .../graphics/opengles_message_processor.h | 1 + src/anbox/network/base_socket_messenger.cpp | 11 + src/anbox/network/base_socket_messenger.h | 1 + src/anbox/network/message_sender.h | 2 + 17 files changed, 243 insertions(+), 152 deletions(-) diff --git a/external/android-emugl/CMakeLists.txt b/external/android-emugl/CMakeLists.txt index 29edadb..b328b17 100644 --- a/external/android-emugl/CMakeLists.txt +++ b/external/android-emugl/CMakeLists.txt @@ -3,6 +3,7 @@ set(CMAKE_C_FLAGS "-Wall") include_directories( + ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/external/android-emugl/shared ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include ${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon diff --git a/external/android-emugl/host/include/libOpenglRender/IOStream.h b/external/android-emugl/host/include/libOpenglRender/IOStream.h index 672f5a7..9bb671e 100644 --- a/external/android-emugl/host/include/libOpenglRender/IOStream.h +++ b/external/android-emugl/host/include/libOpenglRender/IOStream.h @@ -21,6 +21,8 @@ #include "ErrorLog.h" +#include "anbox/logger.h" + class IOStream { public: @@ -70,7 +72,7 @@ public: } int flush() { - + DEBUG("buf %p free %d buf size %d", m_buf, m_free, m_bufsize); if (!m_buf || m_free == m_bufsize) return 0; int stat = commitBuffer(m_bufsize - m_free); diff --git a/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt b/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt index e8d83e2..3377489 100644 --- a/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt @@ -14,7 +14,7 @@ add_custom_command( set(SOURCES GLESv1Decoder.cpp) -if ("${cmake_build_type_lower}" STREQUAL "trace") +if ("${cmake_build_type_lower}" STREQUAL "debug") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt b/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt index 140d061..34a700e 100644 --- a/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt @@ -14,7 +14,7 @@ add_custom_command( set(SOURCES GLESv2Decoder.cpp) -if ("${cmake_build_type_lower}" STREQUAL "trace") +if ("${cmake_build_type_lower}" STREQUAL "debug") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt b/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt index cb67c5a..5bc3558 100644 --- a/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt @@ -10,7 +10,7 @@ add_custom_command( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS emugen) -if ("${cmake_build_type_lower}" STREQUAL "trace") +if ("${cmake_build_type_lower}" STREQUAL "debug") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/src/anbox/graphics/emugl/ColorBuffer.cpp b/src/anbox/graphics/emugl/ColorBuffer.cpp index 270ccac..8687654 100644 --- a/src/anbox/graphics/emugl/ColorBuffer.cpp +++ b/src/anbox/graphics/emugl/ColorBuffer.cpp @@ -255,12 +255,17 @@ void ColorBuffer::readPixels(int x, GLenum p_format, GLenum p_type, void* pixels) { + DEBUG(""); + ScopedHelperContext context(m_helper); if (!context.isOk()) { return; } + DEBUG("Before bind"); + if (bindFbo(&m_fbo, m_tex)) { + DEBUG("Off to GL to read pixels"); s_gles2.glReadPixels(x, y, width, height, p_format, p_type, pixels); unbindFbo(); } diff --git a/src/anbox/graphics/emugl/FrameBuffer.cpp b/src/anbox/graphics/emugl/FrameBuffer.cpp index 64b8323..68ed50a 100644 --- a/src/anbox/graphics/emugl/FrameBuffer.cpp +++ b/src/anbox/graphics/emugl/FrameBuffer.cpp @@ -545,7 +545,9 @@ HandleType FrameBuffer::genHandle() HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, GLenum p_internalFormat) { + DEBUG("width %d height %d", p_width, p_height); emugl::Mutex::AutoLock mutex(m_lock); + DEBUG("Got lock"); HandleType ret = 0; ColorBufferPtr cb(ColorBuffer::create( @@ -748,10 +750,16 @@ void FrameBuffer::readColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels) { + DEBUG("handle %d x %d y %d width %d height %d", + p_colorbuffer, x, y, width, height); + emugl::Mutex::AutoLock mutex(m_lock); + DEBUG("Got lock"); + ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { + DEBUG("Didn't found color buffer"); // bad colorbuffer handle return; } diff --git a/src/anbox/graphics/emugl/LayerManager.cpp b/src/anbox/graphics/emugl/LayerManager.cpp index ab2e74c..c7bb97c 100644 --- a/src/anbox/graphics/emugl/LayerManager.cpp +++ b/src/anbox/graphics/emugl/LayerManager.cpp @@ -73,8 +73,8 @@ LayerManager::~LayerManager() { } void LayerManager::post_layer(const LayerInfo &layer) { - if (is_layer_blacklisted(layer.name)) - return; + // if (is_layer_blacklisted(layer.name)) + // return; FrameBufferWindow *window = nullptr; for (auto &l : layers_) { diff --git a/src/anbox/graphics/emugl/RenderApi.cpp b/src/anbox/graphics/emugl/RenderApi.cpp index d0b40e9..c0f742e 100644 --- a/src/anbox/graphics/emugl/RenderApi.cpp +++ b/src/anbox/graphics/emugl/RenderApi.cpp @@ -79,61 +79,6 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( set_emugl_crash_reporter(crashfunc); set_emugl_logger(logfuncs.coarse); set_emugl_cxt_logger(logfuncs.fine); - // - // Fail if renderer is already initialized - // - if (s_renderThread) { - return false; - } - - // kUseThread is used to determine whether the RenderWindow should use - // a separate thread to manage its subwindow GL/GLES context. - // For now, this feature is disabled entirely for the following - // reasons: - // - // - It must be disabled on Windows at all times, otherwise the main window becomes - // unresponsive after a few seconds of user interaction (e.g. trying to - // move it over the desktop). Probably due to the subtle issues around - // input on this platform (input-queue is global, message-queue is - // per-thread). Also, this messes considerably the display of the - // main window when running the executable under Wine. - // - // - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption - // issues with the GL state of the main window when using the SDL UI. - // After the switch to Qt, this is no longer necessary and may actually cause - // undesired interactions between the UI thread and the RenderWindow thread: - // for example, in a multi-monitor setup the context might be recreated when - // dragging the window between monitors, triggering a Qt-specific callback - // in the context of RenderWindow thread, which will become blocked on the UI - // thread, which may in turn be blocked on something else. - bool kUseThread = false; - - // - // initialize the renderer and listen to connections - // on a thread in the current process. - // - s_renderWindow = new RenderWindow(native_display, kUseThread); - if (!s_renderWindow) { - ERR("Could not create rendering window class"); - GL_LOG("Could not create rendering window class"); - return false; - } - if (!s_renderWindow->isValid()) { - ERR("Could not initialize emulated framebuffer\n"); - delete s_renderWindow; - s_renderWindow = NULL; - return false; - } - - s_renderThread = RenderServer::create(addr, addrLen); - if (!s_renderThread) { - return false; - } - strncpy(s_renderAddr, addr, sizeof(s_renderAddr)); - - s_renderThread->start(); - - GL_LOG("OpenGL renderer initialized successfully"); return true; } diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 942e7a4..a147870 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -25,6 +25,8 @@ #include "OpenGLESDispatch/EGLDispatch.h" +#include "anbox/logger.h" + #include #include @@ -236,6 +238,7 @@ static void rcDestroyWindowSurface(uint32_t windowSurface) static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat) { + DEBUG(""); FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; @@ -351,6 +354,8 @@ static void rcReadColorBuffer(uint32_t colorBuffer, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { + DEBUG(""); + FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; diff --git a/src/anbox/graphics/emugl/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp index db9c6a9..be61412 100644 --- a/src/anbox/graphics/emugl/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -26,15 +26,19 @@ #include "OpenGLESDispatch/GLESv1Dispatch.h" #include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h" +#include "anbox/logger.h" + #define STREAM_BUFFER_SIZE 4*1024*1024 RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) : emugl::Thread(), m_lock(lock), - m_stream(stream) {} + m_stream(stream) { + DEBUG(""); +} RenderThread::~RenderThread() { - delete m_stream; + DEBUG(""); } // static @@ -43,78 +47,75 @@ RenderThread* RenderThread::create(IOStream *stream, emugl::Mutex *lock) { } void RenderThread::forceStop() { + DEBUG(""); m_stream->forceStop(); } intptr_t RenderThread::main() { RenderThreadInfo tInfo; + // Not used below but will store a reference of itself in TLS so that + // it can be accessed down the stack in the same thread when decoding + // any of the commands. ChecksumCalculatorThreadInfo tChecksumInfo; - // - // initialize decoders - // tInfo.m_glDec.initGL(gles1_dispatch_get_proc_func, NULL); tInfo.m_gl2Dec.initGL(gles2_dispatch_get_proc_func, NULL); initRenderControlContext(&tInfo.m_rcDec); ReadBuffer readBuf(STREAM_BUFFER_SIZE); - while (1) { + DEBUG("Started"); + while (1) { int stat = readBuf.getData(m_stream); if (stat <= 0) { + DEBUG("Connection closed"); break; } + DEBUG("Got %d bytes for decoding", readBuf.validData()); + bool progress; do { progress = false; - m_lock->lock(); - // - // try to process some of the command buffer using the GLESv1 decoder - // + DEBUG("Locked"); + size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { + DEBUG("Ran GL commands"); progress = true; readBuf.consume(last); } - // - // try to process some of the command buffer using the GLESv2 decoder - // last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { + DEBUG("Ran GL2 commands"); progress = true; readBuf.consume(last); } - // - // try to process some of the command buffer using the - // renderControl decoder - // last = tInfo.m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { + DEBUG("Ran RC commands"); readBuf.consume(last); progress = true; } m_lock->unlock(); - - } while( progress ); + DEBUG("Unlocked"); + } while (progress); } - // + DEBUG("Shutting down"); + // Release references to the current thread's context/surfaces if any - // FrameBuffer::getFB()->bindContext(0, 0, 0); - if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) { - fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n"); - } + if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) + ERROR("Exiting with current context/surfaces"); FrameBuffer::getFB()->drainWindowSurface(); - FrameBuffer::getFB()->drainRenderContext(); return 0; diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 00d8ec1..dcd8e78 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -71,6 +71,9 @@ void GLRendererServer::start() { log_funcs.coarse = logger_write; log_funcs.fine = logger_write; + // HACK: This will do nothing but set our log functions + initOpenGLRenderer(nullptr, nullptr, 0, log_funcs, logger_write); + FrameBuffer::initialize(window_creator_->native_display()); } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.cpp b/src/anbox/graphics/opengles_message_processor.cpp index 3452eff..c067917 100644 --- a/src/anbox/graphics/opengles_message_processor.cpp +++ b/src/anbox/graphics/opengles_message_processor.cpp @@ -26,122 +26,227 @@ #include #include +#include namespace { -class DirectIOStream : public IOStream { +constexpr const size_t default_buffer_size{384}; +constexpr const size_t max_send_buffer_size{1024}; + +class DelayedIOStream : public IOStream { public: - explicit DirectIOStream(const std::shared_ptr &messenger, - const size_t &buffer_size = 10000) : + typedef std::vector Buffer; + + explicit DelayedIOStream(const std::shared_ptr &messenger, + size_t buffer_size = default_buffer_size) : IOStream(buffer_size), messenger_(messenger) { + // writer_thread_(std::bind(&DelayedIOStream::worker_thread, this)) { } - virtual ~DirectIOStream() { - if (send_buffer_ != nullptr) { - free(send_buffer_); - send_buffer_ = nullptr; - } + virtual ~DelayedIOStream() { + DEBUG(""); + forceStop(); + DEBUG("Shutting down"); } void* allocBuffer(size_t min_size) override { - size_t size = (send_buffer_size_ < min_size ? min_size : send_buffer_size_); - if (!send_buffer_) - send_buffer_ = (unsigned char *) malloc(size); - else if (send_buffer_size_ < size) { - unsigned char *p = (unsigned char *)realloc(send_buffer_, size); - if (p != NULL) { - send_buffer_ = p; - send_buffer_size_ = size; - } else { - free(send_buffer_); - send_buffer_ = NULL; - send_buffer_size_ = 0; - } - } - return send_buffer_; + DEBUG("min size %d", min_size); + if (buffer_.size() < min_size) + buffer_.resize(min_size); + return buffer_.data(); } int commitBuffer(size_t size) override { - messenger_->send(reinterpret_cast(send_buffer_), size); - return size; + DEBUG("size %d", size); + std::unique_lock l(read_mutex_); + +#if 0 + if (buffer_.capacity() <= 2 * size) { + buffer_.resize(size); + out_queue_.push(std::move(buffer_)); + } else { + out_queue_.push(Buffer(buffer_.data(), buffer_.data() + size)); + } + DEBUG("Submitted data into output queue (%d bytes)", size); + can_write_.notify_all(); +#else + ssize_t bytes_left = size; + while (bytes_left > 0) { + const ssize_t written = messenger_->send_raw(buffer_.data() + (size - bytes_left), bytes_left); + if (written < 0 ) { + if (errno != EINTR) { + ERROR("Failed to write data: %s", std::strerror(errno)); + break; + } + WARNING("Socket busy, trying again"); + } else + bytes_left -= written; + } + + DEBUG("Sent data to remote (%d bytes)", buffer_.size()); +#endif + return static_cast(size); } - const unsigned char* readFully(void*, size_t) override { - ERROR("Not implemented"); - return nullptr; + const unsigned char* readFully(void *buffer, size_t length) override { + size_t size = length; + auto data = read(buffer, &size); + if (size < length) + return nullptr; + return data; } - const unsigned char* read(void *data, size_t *size) override { - if (!wait_for_data() || buffer_.size() == 0) { - *size = 0; + const unsigned char* read(void *buffer, size_t *length) override { + std::unique_lock l(read_mutex_); + + if (stopped_) { + DEBUG("Aborting"); return nullptr; } - auto bytes_to_read = *size; - if (bytes_to_read > buffer_.size()) - bytes_to_read = buffer_.size(); + if (current_read_buffer_left_ == 0 && in_queue_.empty()) { + DEBUG("Waiting for data to be available"); + can_read_.wait(l); - ::memcpy(data, buffer_.data(), bytes_to_read); - buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_read); + if (stopped_) { + DEBUG("Aborting"); + return nullptr; + } + } - *size = bytes_to_read; + DEBUG("Trying to read %d bytes", *length); + size_t read = 0; + auto buf = static_cast(buffer); + const auto buffer_end = buf + *length; + while (buf != buffer_end) { + if (current_read_buffer_left_ == 0) { + // If we don't have anymore buffers we need to stop reading here + if (in_queue_.empty()) + break; - return static_cast(data); + current_read_buffer_ = in_queue_.front(); + in_queue_.pop(); + current_read_buffer_left_ = current_read_buffer_.size(); + } + + const size_t current_size = std::min(buffer_end - buf, + current_read_buffer_left_); + ::memcpy(buffer, current_read_buffer_.data() + + (current_read_buffer_.size() - current_read_buffer_left_), + current_size); + + read += current_size; + buf += current_size; + current_read_buffer_left_ -= current_size; + + DEBUG("Size %d, left to read %d", current_size, current_read_buffer_left_); + } + + if (read == 0) + return nullptr; + + *length = read; + + DEBUG("Read %d bytes (buffers left %d)", read, in_queue_.size()); + + return buf; } - int writeFully(const void*, size_t) override { + int writeFully(const void *buffer, size_t length) override { + (void) buffer; + (void) length; ERROR("Not implemented"); - return 0; + return -1; } void forceStop() override { - std::unique_lock l(mutex_); - buffer_.clear(); + DEBUG(""); + stopped_ = true; + can_read_.notify_all(); + can_write_.notify_all(); } - void submitData(const std::vector &data) { - std::unique_lock l(mutex_); - for (const auto &byte : data) - buffer_.push_back(byte); - // buffer_.insert(buffer_.end(), data.begin(), data.end()); - lock_.notify_one(); + void post_data(const Buffer &buffer) { + DEBUG("Got data and waiting for lock"); + std::unique_lock l(read_mutex_); + DEBUG("Received %d bytes", buffer.size()); + in_queue_.push(std::move(buffer)); + can_read_.notify_all(); } private: - bool wait_for_data() { - std::unique_lock l(mutex_); + void worker_thread() { + DEBUG("Running send thread"); + while (true) { + std::unique_lock l(write_mutex_); + while (out_queue_.empty() && !stopped_) { + can_write_.wait(l, [&]() { return !out_queue_.empty() || stopped_; }); + DEBUG("Woke up (queue size %d)", out_queue_.size()); + } - if (!l.owns_lock()) - return false; + if (stopped_) + break; - lock_.wait(l, [&]() { return !buffer_.empty(); }); - return true; + DEBUG("Going to send out %d bytes", out_queue_.front().size()); + + auto buffer = out_queue_.front(); + out_queue_.pop(); + + ssize_t bytes_left = buffer.size(); + while (bytes_left > 0) { + const ssize_t written = messenger_->send_raw(buffer.data() + (buffer.size() - bytes_left), bytes_left); + if (written < 0 ) { + if (errno != EINTR) { + ERROR("Failed to write data: %s", std::strerror(errno)); + break; + } + WARNING("Socket busy, trying again"); + } else + bytes_left -= written; + } + DEBUG("Sent %d bytes to client (queue size %d)", buffer.size(), out_queue_.size()); + } + + DEBUG("Shutting down"); } std::shared_ptr messenger_; - std::mutex mutex_; - std::condition_variable lock_; - std::vector buffer_; - unsigned char *send_buffer_ = nullptr; - size_t send_buffer_size_ = 0; + Buffer buffer_; + std::thread writer_thread_; + std::queue out_queue_; + Buffer current_write_buffer_; + size_t current_write_buffer_left_ = 0; + std::queue in_queue_; + Buffer current_read_buffer_; + size_t current_read_buffer_left_ = 0; + std::mutex write_mutex_; + std::mutex read_mutex_; + std::condition_variable can_write_; + std::condition_variable can_read_; + bool stopped_ = false; }; } namespace anbox { namespace graphics { emugl::Mutex OpenGlesMessageProcessor::global_lock{}; - +static int next_id = 0; OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::shared_ptr &messenger) : messenger_(messenger), - stream_(std::make_shared(messenger_)), - renderer_(RenderThread::create(stream_.get(), &global_lock)) { + id_(next_id++), + stream_(std::make_shared(messenger_)) { // We have to read the client flags first before we can continue // processing the actual commands - std::array buffer; - messenger_->receive_msg(boost::asio::buffer(buffer)); + unsigned int client_flags = 0; + auto err = messenger_->receive_msg(boost::asio::buffer(&client_flags, sizeof(unsigned int))); + if (err) + ERROR("%s", err.message()); + renderer_.reset(RenderThread::create(stream_.get(), &global_lock)); renderer_->start(); + + DEBUG("Started new OpenGL ES message processor"); } OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { @@ -151,8 +256,9 @@ OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { } bool OpenGlesMessageProcessor::process_data(const std::vector &data) { - auto stream = std::static_pointer_cast(stream_); - stream->submitData(data); + DEBUG("[%d] Got %d bytes", id_, data.size()); + auto stream = std::static_pointer_cast(stream_); + stream->post_data(DelayedIOStream::Buffer(data.data(), data.data() + data.size())); return true; } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.h b/src/anbox/graphics/opengles_message_processor.h index 374af97..97381d1 100644 --- a/src/anbox/graphics/opengles_message_processor.h +++ b/src/anbox/graphics/opengles_message_processor.h @@ -45,6 +45,7 @@ private: static emugl::Mutex global_lock; std::shared_ptr messenger_; + int id_; std::shared_ptr stream_; std::shared_ptr renderer_; }; diff --git a/src/anbox/network/base_socket_messenger.cpp b/src/anbox/network/base_socket_messenger.cpp index 1cce830..fa75cae 100644 --- a/src/anbox/network/base_socket_messenger.cpp +++ b/src/anbox/network/base_socket_messenger.cpp @@ -74,6 +74,16 @@ Credentials BaseSocketMessenger::creds() const { return {cr.pid, cr.uid, cr.gid}; } +template +ssize_t BaseSocketMessenger::send_raw(char const* data, size_t length) +{ + VariableLengthArray whole_message{length}; + std::copy(data, data + length, whole_message.data()); + + std::unique_lock lg(message_lock); + return ::send(socket_fd, data, length, 0); +} + template void BaseSocketMessenger::send(char const* data, size_t length) { @@ -88,6 +98,7 @@ void BaseSocketMessenger::send(char const* data, size_t length) boost::asio::transfer_all()); } catch (const boost::system::system_error &err) { + DEBUG("Got error: %s", err.what()); if (err.code() == boost::asio::error::try_again) continue; } diff --git a/src/anbox/network/base_socket_messenger.h b/src/anbox/network/base_socket_messenger.h index c28f037..243374a 100644 --- a/src/anbox/network/base_socket_messenger.h +++ b/src/anbox/network/base_socket_messenger.h @@ -37,6 +37,7 @@ public: unsigned short local_port() const override; void send(char const* data, size_t length) override; + ssize_t send_raw(char const* data, size_t length) override; void async_receive_msg(AnboxReadHandler const& handle, boost::asio::mutable_buffers_1 const &buffer) override; boost::system::error_code receive_msg(boost::asio::mutable_buffers_1 const& buffer) override; size_t available_bytes() override; diff --git a/src/anbox/network/message_sender.h b/src/anbox/network/message_sender.h index 750715d..ab4a10d 100644 --- a/src/anbox/network/message_sender.h +++ b/src/anbox/network/message_sender.h @@ -20,6 +20,7 @@ #define ANBOX_NETWORK_MESSAGE_SENDER_H_ #include +#include namespace anbox { namespace network { @@ -27,6 +28,7 @@ class MessageSender { public: virtual void send(char const* data, size_t length) = 0; + virtual ssize_t send_raw(char const* data, size_t length) = 0; protected: MessageSender() = default; From a6e26f46d60af9a79fac308cb4f7dbaef509e8c8 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 12:53:43 +0100 Subject: [PATCH 37/54] Revert "First attempt on getting rid of the socket server" This reverts commit 91d37082ab008e3e3d1cae21ac285a01eb57fbd8. --- external/android-emugl/CMakeLists.txt | 1 - .../host/include/libOpenglRender/IOStream.h | 4 +- .../host/libs/GLESv1_dec/CMakeLists.txt | 2 +- .../host/libs/GLESv2_dec/CMakeLists.txt | 2 +- .../libs/renderControl_dec/CMakeLists.txt | 2 +- src/anbox/graphics/emugl/ColorBuffer.cpp | 5 - src/anbox/graphics/emugl/FrameBuffer.cpp | 8 - src/anbox/graphics/emugl/LayerManager.cpp | 4 +- src/anbox/graphics/emugl/RenderApi.cpp | 55 ++++ src/anbox/graphics/emugl/RenderControl.cpp | 5 - src/anbox/graphics/emugl/RenderThread.cpp | 51 ++-- src/anbox/graphics/gl_renderer_server.cpp | 3 - .../graphics/opengles_message_processor.cpp | 258 ++++++------------ .../graphics/opengles_message_processor.h | 1 - src/anbox/network/base_socket_messenger.cpp | 11 - src/anbox/network/base_socket_messenger.h | 1 - src/anbox/network/message_sender.h | 2 - 17 files changed, 162 insertions(+), 253 deletions(-) diff --git a/external/android-emugl/CMakeLists.txt b/external/android-emugl/CMakeLists.txt index b328b17..29edadb 100644 --- a/external/android-emugl/CMakeLists.txt +++ b/external/android-emugl/CMakeLists.txt @@ -3,7 +3,6 @@ set(CMAKE_C_FLAGS "-Wall") include_directories( - ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/external/android-emugl/shared ${CMAKE_SOURCE_DIR}/external/android-emugl/host/include ${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon diff --git a/external/android-emugl/host/include/libOpenglRender/IOStream.h b/external/android-emugl/host/include/libOpenglRender/IOStream.h index 9bb671e..672f5a7 100644 --- a/external/android-emugl/host/include/libOpenglRender/IOStream.h +++ b/external/android-emugl/host/include/libOpenglRender/IOStream.h @@ -21,8 +21,6 @@ #include "ErrorLog.h" -#include "anbox/logger.h" - class IOStream { public: @@ -72,7 +70,7 @@ public: } int flush() { - DEBUG("buf %p free %d buf size %d", m_buf, m_free, m_bufsize); + if (!m_buf || m_free == m_bufsize) return 0; int stat = commitBuffer(m_bufsize - m_free); diff --git a/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt b/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt index 3377489..e8d83e2 100644 --- a/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/GLESv1_dec/CMakeLists.txt @@ -14,7 +14,7 @@ add_custom_command( set(SOURCES GLESv1Decoder.cpp) -if ("${cmake_build_type_lower}" STREQUAL "debug") +if ("${cmake_build_type_lower}" STREQUAL "trace") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt b/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt index 34a700e..140d061 100644 --- a/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/GLESv2_dec/CMakeLists.txt @@ -14,7 +14,7 @@ add_custom_command( set(SOURCES GLESv2Decoder.cpp) -if ("${cmake_build_type_lower}" STREQUAL "debug") +if ("${cmake_build_type_lower}" STREQUAL "trace") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt b/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt index 5bc3558..cb67c5a 100644 --- a/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt +++ b/external/android-emugl/host/libs/renderControl_dec/CMakeLists.txt @@ -10,7 +10,7 @@ add_custom_command( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS emugen) -if ("${cmake_build_type_lower}" STREQUAL "debug") +if ("${cmake_build_type_lower}" STREQUAL "trace") set(OPENGL_DEBUG "-DOPENGL_DEBUG_PRINTOUT -DCHECK_GL_ERROR") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENGL_DEBUG}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}") diff --git a/src/anbox/graphics/emugl/ColorBuffer.cpp b/src/anbox/graphics/emugl/ColorBuffer.cpp index 8687654..270ccac 100644 --- a/src/anbox/graphics/emugl/ColorBuffer.cpp +++ b/src/anbox/graphics/emugl/ColorBuffer.cpp @@ -255,17 +255,12 @@ void ColorBuffer::readPixels(int x, GLenum p_format, GLenum p_type, void* pixels) { - DEBUG(""); - ScopedHelperContext context(m_helper); if (!context.isOk()) { return; } - DEBUG("Before bind"); - if (bindFbo(&m_fbo, m_tex)) { - DEBUG("Off to GL to read pixels"); s_gles2.glReadPixels(x, y, width, height, p_format, p_type, pixels); unbindFbo(); } diff --git a/src/anbox/graphics/emugl/FrameBuffer.cpp b/src/anbox/graphics/emugl/FrameBuffer.cpp index 68ed50a..64b8323 100644 --- a/src/anbox/graphics/emugl/FrameBuffer.cpp +++ b/src/anbox/graphics/emugl/FrameBuffer.cpp @@ -545,9 +545,7 @@ HandleType FrameBuffer::genHandle() HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, GLenum p_internalFormat) { - DEBUG("width %d height %d", p_width, p_height); emugl::Mutex::AutoLock mutex(m_lock); - DEBUG("Got lock"); HandleType ret = 0; ColorBufferPtr cb(ColorBuffer::create( @@ -750,16 +748,10 @@ void FrameBuffer::readColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels) { - DEBUG("handle %d x %d y %d width %d height %d", - p_colorbuffer, x, y, width, height); - emugl::Mutex::AutoLock mutex(m_lock); - DEBUG("Got lock"); - ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); if (c == m_colorbuffers.end()) { - DEBUG("Didn't found color buffer"); // bad colorbuffer handle return; } diff --git a/src/anbox/graphics/emugl/LayerManager.cpp b/src/anbox/graphics/emugl/LayerManager.cpp index c7bb97c..ab2e74c 100644 --- a/src/anbox/graphics/emugl/LayerManager.cpp +++ b/src/anbox/graphics/emugl/LayerManager.cpp @@ -73,8 +73,8 @@ LayerManager::~LayerManager() { } void LayerManager::post_layer(const LayerInfo &layer) { - // if (is_layer_blacklisted(layer.name)) - // return; + if (is_layer_blacklisted(layer.name)) + return; FrameBufferWindow *window = nullptr; for (auto &l : layers_) { diff --git a/src/anbox/graphics/emugl/RenderApi.cpp b/src/anbox/graphics/emugl/RenderApi.cpp index c0f742e..d0b40e9 100644 --- a/src/anbox/graphics/emugl/RenderApi.cpp +++ b/src/anbox/graphics/emugl/RenderApi.cpp @@ -79,6 +79,61 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( set_emugl_crash_reporter(crashfunc); set_emugl_logger(logfuncs.coarse); set_emugl_cxt_logger(logfuncs.fine); + // + // Fail if renderer is already initialized + // + if (s_renderThread) { + return false; + } + + // kUseThread is used to determine whether the RenderWindow should use + // a separate thread to manage its subwindow GL/GLES context. + // For now, this feature is disabled entirely for the following + // reasons: + // + // - It must be disabled on Windows at all times, otherwise the main window becomes + // unresponsive after a few seconds of user interaction (e.g. trying to + // move it over the desktop). Probably due to the subtle issues around + // input on this platform (input-queue is global, message-queue is + // per-thread). Also, this messes considerably the display of the + // main window when running the executable under Wine. + // + // - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption + // issues with the GL state of the main window when using the SDL UI. + // After the switch to Qt, this is no longer necessary and may actually cause + // undesired interactions between the UI thread and the RenderWindow thread: + // for example, in a multi-monitor setup the context might be recreated when + // dragging the window between monitors, triggering a Qt-specific callback + // in the context of RenderWindow thread, which will become blocked on the UI + // thread, which may in turn be blocked on something else. + bool kUseThread = false; + + // + // initialize the renderer and listen to connections + // on a thread in the current process. + // + s_renderWindow = new RenderWindow(native_display, kUseThread); + if (!s_renderWindow) { + ERR("Could not create rendering window class"); + GL_LOG("Could not create rendering window class"); + return false; + } + if (!s_renderWindow->isValid()) { + ERR("Could not initialize emulated framebuffer\n"); + delete s_renderWindow; + s_renderWindow = NULL; + return false; + } + + s_renderThread = RenderServer::create(addr, addrLen); + if (!s_renderThread) { + return false; + } + strncpy(s_renderAddr, addr, sizeof(s_renderAddr)); + + s_renderThread->start(); + + GL_LOG("OpenGL renderer initialized successfully"); return true; } diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index a147870..942e7a4 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -25,8 +25,6 @@ #include "OpenGLESDispatch/EGLDispatch.h" -#include "anbox/logger.h" - #include #include @@ -238,7 +236,6 @@ static void rcDestroyWindowSurface(uint32_t windowSurface) static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat) { - DEBUG(""); FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; @@ -354,8 +351,6 @@ static void rcReadColorBuffer(uint32_t colorBuffer, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { - DEBUG(""); - FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; diff --git a/src/anbox/graphics/emugl/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp index be61412..db9c6a9 100644 --- a/src/anbox/graphics/emugl/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -26,19 +26,15 @@ #include "OpenGLESDispatch/GLESv1Dispatch.h" #include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h" -#include "anbox/logger.h" - #define STREAM_BUFFER_SIZE 4*1024*1024 RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) : emugl::Thread(), m_lock(lock), - m_stream(stream) { - DEBUG(""); -} + m_stream(stream) {} RenderThread::~RenderThread() { - DEBUG(""); + delete m_stream; } // static @@ -47,75 +43,78 @@ RenderThread* RenderThread::create(IOStream *stream, emugl::Mutex *lock) { } void RenderThread::forceStop() { - DEBUG(""); m_stream->forceStop(); } intptr_t RenderThread::main() { RenderThreadInfo tInfo; - // Not used below but will store a reference of itself in TLS so that - // it can be accessed down the stack in the same thread when decoding - // any of the commands. ChecksumCalculatorThreadInfo tChecksumInfo; + // + // initialize decoders + // tInfo.m_glDec.initGL(gles1_dispatch_get_proc_func, NULL); tInfo.m_gl2Dec.initGL(gles2_dispatch_get_proc_func, NULL); initRenderControlContext(&tInfo.m_rcDec); ReadBuffer readBuf(STREAM_BUFFER_SIZE); - DEBUG("Started"); - while (1) { + int stat = readBuf.getData(m_stream); if (stat <= 0) { - DEBUG("Connection closed"); break; } - DEBUG("Got %d bytes for decoding", readBuf.validData()); - bool progress; do { progress = false; - m_lock->lock(); - DEBUG("Locked"); + m_lock->lock(); + // + // try to process some of the command buffer using the GLESv1 decoder + // size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { - DEBUG("Ran GL commands"); progress = true; readBuf.consume(last); } + // + // try to process some of the command buffer using the GLESv2 decoder + // last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { - DEBUG("Ran GL2 commands"); progress = true; readBuf.consume(last); } + // + // try to process some of the command buffer using the + // renderControl decoder + // last = tInfo.m_rcDec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { - DEBUG("Ran RC commands"); readBuf.consume(last); progress = true; } m_lock->unlock(); - DEBUG("Unlocked"); - } while (progress); + + } while( progress ); } - DEBUG("Shutting down"); - + // // Release references to the current thread's context/surfaces if any + // FrameBuffer::getFB()->bindContext(0, 0, 0); - if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) - ERROR("Exiting with current context/surfaces"); + if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) { + fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n"); + } FrameBuffer::getFB()->drainWindowSurface(); + FrameBuffer::getFB()->drainRenderContext(); return 0; diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index dcd8e78..00d8ec1 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -71,9 +71,6 @@ void GLRendererServer::start() { log_funcs.coarse = logger_write; log_funcs.fine = logger_write; - // HACK: This will do nothing but set our log functions - initOpenGLRenderer(nullptr, nullptr, 0, log_funcs, logger_write); - FrameBuffer::initialize(window_creator_->native_display()); } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.cpp b/src/anbox/graphics/opengles_message_processor.cpp index c067917..3452eff 100644 --- a/src/anbox/graphics/opengles_message_processor.cpp +++ b/src/anbox/graphics/opengles_message_processor.cpp @@ -26,227 +26,122 @@ #include #include -#include namespace { -constexpr const size_t default_buffer_size{384}; -constexpr const size_t max_send_buffer_size{1024}; - -class DelayedIOStream : public IOStream { +class DirectIOStream : public IOStream { public: - typedef std::vector Buffer; - - explicit DelayedIOStream(const std::shared_ptr &messenger, - size_t buffer_size = default_buffer_size) : + explicit DirectIOStream(const std::shared_ptr &messenger, + const size_t &buffer_size = 10000) : IOStream(buffer_size), messenger_(messenger) { - // writer_thread_(std::bind(&DelayedIOStream::worker_thread, this)) { } - virtual ~DelayedIOStream() { - DEBUG(""); - forceStop(); - DEBUG("Shutting down"); + virtual ~DirectIOStream() { + if (send_buffer_ != nullptr) { + free(send_buffer_); + send_buffer_ = nullptr; + } } void* allocBuffer(size_t min_size) override { - DEBUG("min size %d", min_size); - if (buffer_.size() < min_size) - buffer_.resize(min_size); - return buffer_.data(); + size_t size = (send_buffer_size_ < min_size ? min_size : send_buffer_size_); + if (!send_buffer_) + send_buffer_ = (unsigned char *) malloc(size); + else if (send_buffer_size_ < size) { + unsigned char *p = (unsigned char *)realloc(send_buffer_, size); + if (p != NULL) { + send_buffer_ = p; + send_buffer_size_ = size; + } else { + free(send_buffer_); + send_buffer_ = NULL; + send_buffer_size_ = 0; + } + } + return send_buffer_; } int commitBuffer(size_t size) override { - DEBUG("size %d", size); - std::unique_lock l(read_mutex_); - -#if 0 - if (buffer_.capacity() <= 2 * size) { - buffer_.resize(size); - out_queue_.push(std::move(buffer_)); - } else { - out_queue_.push(Buffer(buffer_.data(), buffer_.data() + size)); - } - DEBUG("Submitted data into output queue (%d bytes)", size); - can_write_.notify_all(); -#else - ssize_t bytes_left = size; - while (bytes_left > 0) { - const ssize_t written = messenger_->send_raw(buffer_.data() + (size - bytes_left), bytes_left); - if (written < 0 ) { - if (errno != EINTR) { - ERROR("Failed to write data: %s", std::strerror(errno)); - break; - } - WARNING("Socket busy, trying again"); - } else - bytes_left -= written; - } - - DEBUG("Sent data to remote (%d bytes)", buffer_.size()); -#endif - return static_cast(size); + messenger_->send(reinterpret_cast(send_buffer_), size); + return size; } - const unsigned char* readFully(void *buffer, size_t length) override { - size_t size = length; - auto data = read(buffer, &size); - if (size < length) - return nullptr; - return data; - } - - const unsigned char* read(void *buffer, size_t *length) override { - std::unique_lock l(read_mutex_); - - if (stopped_) { - DEBUG("Aborting"); - return nullptr; - } - - if (current_read_buffer_left_ == 0 && in_queue_.empty()) { - DEBUG("Waiting for data to be available"); - can_read_.wait(l); - - if (stopped_) { - DEBUG("Aborting"); - return nullptr; - } - } - - DEBUG("Trying to read %d bytes", *length); - size_t read = 0; - auto buf = static_cast(buffer); - const auto buffer_end = buf + *length; - while (buf != buffer_end) { - if (current_read_buffer_left_ == 0) { - // If we don't have anymore buffers we need to stop reading here - if (in_queue_.empty()) - break; - - current_read_buffer_ = in_queue_.front(); - in_queue_.pop(); - current_read_buffer_left_ = current_read_buffer_.size(); - } - - const size_t current_size = std::min(buffer_end - buf, - current_read_buffer_left_); - ::memcpy(buffer, current_read_buffer_.data() + - (current_read_buffer_.size() - current_read_buffer_left_), - current_size); - - read += current_size; - buf += current_size; - current_read_buffer_left_ -= current_size; - - DEBUG("Size %d, left to read %d", current_size, current_read_buffer_left_); - } - - if (read == 0) - return nullptr; - - *length = read; - - DEBUG("Read %d bytes (buffers left %d)", read, in_queue_.size()); - - return buf; - } - - int writeFully(const void *buffer, size_t length) override { - (void) buffer; - (void) length; + const unsigned char* readFully(void*, size_t) override { ERROR("Not implemented"); - return -1; + return nullptr; + } + + const unsigned char* read(void *data, size_t *size) override { + if (!wait_for_data() || buffer_.size() == 0) { + *size = 0; + return nullptr; + } + + auto bytes_to_read = *size; + if (bytes_to_read > buffer_.size()) + bytes_to_read = buffer_.size(); + + ::memcpy(data, buffer_.data(), bytes_to_read); + buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_read); + + *size = bytes_to_read; + + return static_cast(data); + } + + int writeFully(const void*, size_t) override { + ERROR("Not implemented"); + return 0; } void forceStop() override { - DEBUG(""); - stopped_ = true; - can_read_.notify_all(); - can_write_.notify_all(); + std::unique_lock l(mutex_); + buffer_.clear(); } - void post_data(const Buffer &buffer) { - DEBUG("Got data and waiting for lock"); - std::unique_lock l(read_mutex_); - DEBUG("Received %d bytes", buffer.size()); - in_queue_.push(std::move(buffer)); - can_read_.notify_all(); + void submitData(const std::vector &data) { + std::unique_lock l(mutex_); + for (const auto &byte : data) + buffer_.push_back(byte); + // buffer_.insert(buffer_.end(), data.begin(), data.end()); + lock_.notify_one(); } private: - void worker_thread() { - DEBUG("Running send thread"); - while (true) { - std::unique_lock l(write_mutex_); - while (out_queue_.empty() && !stopped_) { - can_write_.wait(l, [&]() { return !out_queue_.empty() || stopped_; }); - DEBUG("Woke up (queue size %d)", out_queue_.size()); - } + bool wait_for_data() { + std::unique_lock l(mutex_); - if (stopped_) - break; + if (!l.owns_lock()) + return false; - DEBUG("Going to send out %d bytes", out_queue_.front().size()); - - auto buffer = out_queue_.front(); - out_queue_.pop(); - - ssize_t bytes_left = buffer.size(); - while (bytes_left > 0) { - const ssize_t written = messenger_->send_raw(buffer.data() + (buffer.size() - bytes_left), bytes_left); - if (written < 0 ) { - if (errno != EINTR) { - ERROR("Failed to write data: %s", std::strerror(errno)); - break; - } - WARNING("Socket busy, trying again"); - } else - bytes_left -= written; - } - DEBUG("Sent %d bytes to client (queue size %d)", buffer.size(), out_queue_.size()); - } - - DEBUG("Shutting down"); + lock_.wait(l, [&]() { return !buffer_.empty(); }); + return true; } std::shared_ptr messenger_; - Buffer buffer_; - std::thread writer_thread_; - std::queue out_queue_; - Buffer current_write_buffer_; - size_t current_write_buffer_left_ = 0; - std::queue in_queue_; - Buffer current_read_buffer_; - size_t current_read_buffer_left_ = 0; - std::mutex write_mutex_; - std::mutex read_mutex_; - std::condition_variable can_write_; - std::condition_variable can_read_; - bool stopped_ = false; + std::mutex mutex_; + std::condition_variable lock_; + std::vector buffer_; + unsigned char *send_buffer_ = nullptr; + size_t send_buffer_size_ = 0; }; } namespace anbox { namespace graphics { emugl::Mutex OpenGlesMessageProcessor::global_lock{}; -static int next_id = 0; + OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::shared_ptr &messenger) : messenger_(messenger), - id_(next_id++), - stream_(std::make_shared(messenger_)) { + stream_(std::make_shared(messenger_)), + renderer_(RenderThread::create(stream_.get(), &global_lock)) { // We have to read the client flags first before we can continue // processing the actual commands - unsigned int client_flags = 0; - auto err = messenger_->receive_msg(boost::asio::buffer(&client_flags, sizeof(unsigned int))); - if (err) - ERROR("%s", err.message()); + std::array buffer; + messenger_->receive_msg(boost::asio::buffer(buffer)); - renderer_.reset(RenderThread::create(stream_.get(), &global_lock)); renderer_->start(); - - DEBUG("Started new OpenGL ES message processor"); } OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { @@ -256,9 +151,8 @@ OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { } bool OpenGlesMessageProcessor::process_data(const std::vector &data) { - DEBUG("[%d] Got %d bytes", id_, data.size()); - auto stream = std::static_pointer_cast(stream_); - stream->post_data(DelayedIOStream::Buffer(data.data(), data.data() + data.size())); + auto stream = std::static_pointer_cast(stream_); + stream->submitData(data); return true; } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.h b/src/anbox/graphics/opengles_message_processor.h index 97381d1..374af97 100644 --- a/src/anbox/graphics/opengles_message_processor.h +++ b/src/anbox/graphics/opengles_message_processor.h @@ -45,7 +45,6 @@ private: static emugl::Mutex global_lock; std::shared_ptr messenger_; - int id_; std::shared_ptr stream_; std::shared_ptr renderer_; }; diff --git a/src/anbox/network/base_socket_messenger.cpp b/src/anbox/network/base_socket_messenger.cpp index fa75cae..1cce830 100644 --- a/src/anbox/network/base_socket_messenger.cpp +++ b/src/anbox/network/base_socket_messenger.cpp @@ -74,16 +74,6 @@ Credentials BaseSocketMessenger::creds() const { return {cr.pid, cr.uid, cr.gid}; } -template -ssize_t BaseSocketMessenger::send_raw(char const* data, size_t length) -{ - VariableLengthArray whole_message{length}; - std::copy(data, data + length, whole_message.data()); - - std::unique_lock lg(message_lock); - return ::send(socket_fd, data, length, 0); -} - template void BaseSocketMessenger::send(char const* data, size_t length) { @@ -98,7 +88,6 @@ void BaseSocketMessenger::send(char const* data, size_t length) boost::asio::transfer_all()); } catch (const boost::system::system_error &err) { - DEBUG("Got error: %s", err.what()); if (err.code() == boost::asio::error::try_again) continue; } diff --git a/src/anbox/network/base_socket_messenger.h b/src/anbox/network/base_socket_messenger.h index 243374a..c28f037 100644 --- a/src/anbox/network/base_socket_messenger.h +++ b/src/anbox/network/base_socket_messenger.h @@ -37,7 +37,6 @@ public: unsigned short local_port() const override; void send(char const* data, size_t length) override; - ssize_t send_raw(char const* data, size_t length) override; void async_receive_msg(AnboxReadHandler const& handle, boost::asio::mutable_buffers_1 const &buffer) override; boost::system::error_code receive_msg(boost::asio::mutable_buffers_1 const& buffer) override; size_t available_bytes() override; diff --git a/src/anbox/network/message_sender.h b/src/anbox/network/message_sender.h index ab4a10d..750715d 100644 --- a/src/anbox/network/message_sender.h +++ b/src/anbox/network/message_sender.h @@ -20,7 +20,6 @@ #define ANBOX_NETWORK_MESSAGE_SENDER_H_ #include -#include namespace anbox { namespace network { @@ -28,7 +27,6 @@ class MessageSender { public: virtual void send(char const* data, size_t length) = 0; - virtual ssize_t send_raw(char const* data, size_t length) = 0; protected: MessageSender() = default; From ca09dd1fa17baac55461a3a9a15636e87b5e4804 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 12:53:57 +0100 Subject: [PATCH 38/54] Revert "Integrate RenderThread directly into our message processor" This reverts commit 3e126fb252ef0b76616837e455f492e87e3189ab. --- src/anbox/cmds/run.cpp | 4 +- src/anbox/graphics/gl_renderer_server.cpp | 22 ++- src/anbox/graphics/gl_renderer_server.h | 3 + .../graphics/opengles_message_processor.cpp | 146 +++--------------- .../graphics/opengles_message_processor.h | 16 +- src/anbox/qemu/pipe_connection_creator.cpp | 12 +- src/anbox/qemu/pipe_connection_creator.h | 8 +- 7 files changed, 70 insertions(+), 141 deletions(-) diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 01bc29f..e65ce28 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -109,7 +109,9 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto qemu_pipe_connector = std::make_shared( utils::string_format("%s/qemu_pipe", config::socket_path()), rt, - std::make_shared(rt)); + std::make_shared(rt, + renderer->socket_path(), + icon_)); auto android_api_stub = std::make_shared(); diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 00d8ec1..e7cc739 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -18,7 +18,6 @@ #include "anbox/logger.h" #include "anbox/graphics/gl_renderer_server.h" #include "anbox/graphics/window_creator.h" -#include "anbox/graphics/emugl/FrameBuffer.h" #include "OpenglRender/render_api.h" @@ -51,8 +50,8 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &window_ } GLRendererServer::~GLRendererServer() { - if (const auto fb = FrameBuffer::getFB()) - fb->finalize(); + // destroyOpenGLSubwindow(); + stopOpenGLRenderer(); } void logger_write(const char *format, ...) { @@ -71,7 +70,22 @@ void GLRendererServer::start() { log_funcs.coarse = logger_write; log_funcs.fine = logger_write; - FrameBuffer::initialize(window_creator_->native_display()); + auto display_info = window_creator_->display_info(); + const auto width = display_info.horizontal_resolution; + const auto height = display_info.vertical_resolution; + + char server_addr[256] = { 0 }; + // The width & height we supply here are the dimensions the internal framebuffer + // will use. Making this static prevents us for now to resize the window we create + // later for the actual display. + if (!initOpenGLRenderer(window_creator_->native_display(), server_addr, sizeof(server_addr), log_funcs, logger_write)) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); + + socket_path_ = server_addr; +} + +std::string GLRendererServer::socket_path() const { + return socket_path_; } } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index 3dedb36..4b5fad9 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -34,7 +34,10 @@ public: void start(); + std::string socket_path() const; + private: + std::string socket_path_; std::shared_ptr window_creator_; }; diff --git a/src/anbox/graphics/opengles_message_processor.cpp b/src/anbox/graphics/opengles_message_processor.cpp index 3452eff..6f5a26d 100644 --- a/src/anbox/graphics/opengles_message_processor.cpp +++ b/src/anbox/graphics/opengles_message_processor.cpp @@ -20,139 +20,39 @@ #include "anbox/network/local_socket_messenger.h" #include "anbox/network/connections.h" #include "anbox/network/delegate_message_processor.h" -#include "anbox/graphics/emugl/RenderThread.h" - -#include "external/android-emugl/host/include/libOpenglRender/IOStream.h" - -#include -#include - -namespace { -class DirectIOStream : public IOStream { -public: - explicit DirectIOStream(const std::shared_ptr &messenger, - const size_t &buffer_size = 10000) : - IOStream(buffer_size), - messenger_(messenger) { - } - - virtual ~DirectIOStream() { - if (send_buffer_ != nullptr) { - free(send_buffer_); - send_buffer_ = nullptr; - } - } - - void* allocBuffer(size_t min_size) override { - size_t size = (send_buffer_size_ < min_size ? min_size : send_buffer_size_); - if (!send_buffer_) - send_buffer_ = (unsigned char *) malloc(size); - else if (send_buffer_size_ < size) { - unsigned char *p = (unsigned char *)realloc(send_buffer_, size); - if (p != NULL) { - send_buffer_ = p; - send_buffer_size_ = size; - } else { - free(send_buffer_); - send_buffer_ = NULL; - send_buffer_size_ = 0; - } - } - return send_buffer_; - } - - int commitBuffer(size_t size) override { - messenger_->send(reinterpret_cast(send_buffer_), size); - return size; - } - - const unsigned char* readFully(void*, size_t) override { - ERROR("Not implemented"); - return nullptr; - } - - const unsigned char* read(void *data, size_t *size) override { - if (!wait_for_data() || buffer_.size() == 0) { - *size = 0; - return nullptr; - } - - auto bytes_to_read = *size; - if (bytes_to_read > buffer_.size()) - bytes_to_read = buffer_.size(); - - ::memcpy(data, buffer_.data(), bytes_to_read); - buffer_.erase(buffer_.begin(), buffer_.begin() + bytes_to_read); - - *size = bytes_to_read; - - return static_cast(data); - } - - int writeFully(const void*, size_t) override { - ERROR("Not implemented"); - return 0; - } - - void forceStop() override { - std::unique_lock l(mutex_); - buffer_.clear(); - } - - void submitData(const std::vector &data) { - std::unique_lock l(mutex_); - for (const auto &byte : data) - buffer_.push_back(byte); - // buffer_.insert(buffer_.end(), data.begin(), data.end()); - lock_.notify_one(); - } - -private: - bool wait_for_data() { - std::unique_lock l(mutex_); - - if (!l.owns_lock()) - return false; - - lock_.wait(l, [&]() { return !buffer_.empty(); }); - return true; - } - - std::shared_ptr messenger_; - std::mutex mutex_; - std::condition_variable lock_; - std::vector buffer_; - unsigned char *send_buffer_ = nullptr; - size_t send_buffer_size_ = 0; -}; -} namespace anbox { namespace graphics { -emugl::Mutex OpenGlesMessageProcessor::global_lock{}; +OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::string &renderer_socket_path, + const std::shared_ptr &rt, + const std::shared_ptr &messenger) : + client_messenger_(messenger) { -OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::shared_ptr &messenger) : - messenger_(messenger), - stream_(std::make_shared(messenger_)), - renderer_(RenderThread::create(stream_.get(), &global_lock)) { - - // We have to read the client flags first before we can continue - // processing the actual commands - std::array buffer; - messenger_->receive_msg(boost::asio::buffer(buffer)); - - renderer_->start(); + connect_and_attach(renderer_socket_path, rt); } OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { - DEBUG(""); - renderer_->forceStop(); - renderer_->wait(nullptr); +} + +void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path, + const std::shared_ptr &rt) { + + auto socket = std::make_shared(rt->service()); + socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path)); + + messenger_ = std::make_shared(socket); + renderer_ = std::make_shared( + messenger_, messenger_, 0, nullptr, + std::make_shared([&](const std::vector &data) { + client_messenger_->send(reinterpret_cast(data.data()), data.size()); + return true; + })); + renderer_->set_name("opengles-renderer"); + renderer_->read_next_message(); } bool OpenGlesMessageProcessor::process_data(const std::vector &data) { - auto stream = std::static_pointer_cast(stream_); - stream->submitData(data); + messenger_->send(reinterpret_cast(data.data()), data.size()); return true; } } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.h b/src/anbox/graphics/opengles_message_processor.h index 374af97..05612cf 100644 --- a/src/anbox/graphics/opengles_message_processor.h +++ b/src/anbox/graphics/opengles_message_processor.h @@ -27,26 +27,24 @@ #include "anbox/network/socket_messenger.h" #include "anbox/network/socket_connection.h" -#include "external/android-emugl/shared/emugl/common/mutex.h" - -class IOStream; -class RenderThread; - namespace anbox { namespace graphics { class OpenGlesMessageProcessor : public network::MessageProcessor { public: - OpenGlesMessageProcessor(const std::shared_ptr &messenger); + OpenGlesMessageProcessor(const std::string &renderer_socket_path, + const std::shared_ptr &rt, + const std::shared_ptr &messenger); ~OpenGlesMessageProcessor(); bool process_data(const std::vector &data) override; private: - static emugl::Mutex global_lock; + void connect_and_attach(const std::string &socket_path, + const std::shared_ptr &rt); + std::shared_ptr client_messenger_; std::shared_ptr messenger_; - std::shared_ptr stream_; - std::shared_ptr renderer_; + std::shared_ptr renderer_; }; } // namespace graphics } // namespace anbox diff --git a/src/anbox/qemu/pipe_connection_creator.cpp b/src/anbox/qemu/pipe_connection_creator.cpp index 7c31eb3..5d81e89 100644 --- a/src/anbox/qemu/pipe_connection_creator.cpp +++ b/src/anbox/qemu/pipe_connection_creator.cpp @@ -62,10 +62,14 @@ std::string client_type_to_string(const anbox::qemu::PipeConnectionCreator::clie } namespace anbox { namespace qemu { -PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &rt) : +PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &rt, + const std::string &renderer_socket_path, + const std::string &boot_animation_icon_path) : runtime_(rt), next_connection_id_(0), - connections_(std::make_shared>()) { + connections_(std::make_shared>()), + renderer_socket_path_(renderer_socket_path), + boot_animation_icon_path_(boot_animation_icon_path) { } PipeConnectionCreator::~PipeConnectionCreator() { @@ -133,7 +137,7 @@ PipeConnectionCreator::client_type PipeConnectionCreator::identify_client( std::shared_ptr PipeConnectionCreator::create_processor(const client_type &type, const std::shared_ptr &messenger) { if (type == client_type::opengles) - return std::make_shared(messenger); + return std::make_shared(renderer_socket_path_, runtime_, messenger); else if (type == client_type::qemud_boot_properties) return std::make_shared(messenger); else if (type == client_type::qemud_hw_control) @@ -146,6 +150,8 @@ std::shared_ptr PipeConnectionCreator::create_process return std::make_shared(messenger); else if (type == client_type::qemud_gsm) return std::make_shared(messenger); + else if (type == client_type::bootanimation) + return std::make_shared(messenger, boot_animation_icon_path_); else if (type == client_type::qemud_adb) return std::make_shared(runtime_, messenger); diff --git a/src/anbox/qemu/pipe_connection_creator.h b/src/anbox/qemu/pipe_connection_creator.h index e652e58..391fedf 100644 --- a/src/anbox/qemu/pipe_connection_creator.h +++ b/src/anbox/qemu/pipe_connection_creator.h @@ -33,7 +33,10 @@ namespace anbox { namespace qemu { class PipeConnectionCreator : public network::ConnectionCreator { public: - PipeConnectionCreator(const std::shared_ptr &rt); + PipeConnectionCreator( + const std::shared_ptr &rt, + const std::string &renderer_socket_path, + const std::string &boot_animation_icon_path); ~PipeConnectionCreator() noexcept; void create_connection_for( @@ -62,6 +65,9 @@ private: std::shared_ptr runtime_; std::atomic next_connection_id_; std::shared_ptr> const connections_; + + std::string renderer_socket_path_; + std::string boot_animation_icon_path_; }; } // namespace qemu } // namespace anbox From 2cbc3a5021a426abad517e3c2cf8a655f9f849de Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 12:54:20 +0100 Subject: [PATCH 39/54] Drop all properties which are now in build.prop --- .../boot_properties_message_processor.cpp | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index 37e1496..0165942 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -28,7 +28,6 @@ BootPropertiesMessageProcessor::BootPropertiesMessageProcessor(const std::shared BootPropertiesMessageProcessor::~BootPropertiesMessageProcessor() { } - void BootPropertiesMessageProcessor::handle_command(const std::string &command) { if (command == "list") list_properties(); @@ -36,42 +35,9 @@ void BootPropertiesMessageProcessor::handle_command(const std::string &command) void BootPropertiesMessageProcessor::list_properties() { std::vector properties = { - // Simple indicator to say we're anbox and if needed things in the container - // can adjust to this. Normally everything should detect we're qemu which - // should be enough for the simple cases. - "ro.anbox=1", - - // Needed for identification within the system. Normally retrieve from - // kernel configuration which isn't possible in our case. - "ro.hardware=goldfish", - - // Needed to let the gralloc HAL load the right implementation - "ro.kernel.qemu.gles=1", - - // Needed from different parts of the system in order to load - // the right implementation for qemu - "ro.kernel.qemu=1", - // TODO(morphis): Using HDPI here for now but should be adjusted to the device // we're running on. utils::string_format("ro.sf.lcd_density=%d", static_cast(graphics::DensityType::medium)), - - // Disable on-screen virtual keys as we can use the hardware keyboard - "qemu.hw.mainkeys=1", - - // Android has builtin detection (inside Zygote) for proper container - // detection support - "ro.boot.container=1", - - // Mark us as a device without telephony support (as we don't have a RIL) - "ro.radio.noril=yes", - - // To let surfaceflinger load our hwcomposer implementation we specify - // the correct subkey of the module here. - "ro.hardware.hwcomposer=anbox", - - // Keep boot animation disabled as we don't need it - "debug.sf.nobootanimation=1", }; for (const auto &prop : properties) { From 7c7c8982b23a5cb6ce30f4dbbc6b4fd9d7add306 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 13:07:39 +0100 Subject: [PATCH 40/54] Add initial bits of window management abstraction --- src/CMakeLists.txt | 3 ++ src/anbox/cmds/run.cpp | 4 +- src/anbox/wm/default_platform_policy.cpp | 39 ++++++++++++++++ src/anbox/wm/default_platform_policy.h | 33 +++++++++++++ src/anbox/wm/manager.cpp | 3 +- src/anbox/wm/manager.h | 6 ++- src/anbox/wm/platform_policy.cpp | 25 ++++++++++ src/anbox/wm/platform_policy.h | 38 +++++++++++++++ src/anbox/wm/window.cpp | 38 +++++++++++++++ src/anbox/wm/window.h | 59 ++++++++++++++++++++++++ 10 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 src/anbox/wm/default_platform_policy.cpp create mode 100644 src/anbox/wm/default_platform_policy.h create mode 100644 src/anbox/wm/platform_policy.cpp create mode 100644 src/anbox/wm/platform_policy.h create mode 100644 src/anbox/wm/window.cpp create mode 100644 src/anbox/wm/window.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a4aaed..d49897d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,6 +134,9 @@ set(SOURCES anbox/wm/task.cpp anbox/wm/manager.cpp anbox/wm/window_state.cpp + anbox/wm/window.cpp + anbox/wm/platform_policy.cpp + anbox/wm/default_platform_policy.cpp anbox/input/manager.cpp anbox/input/device.cpp diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index e65ce28..9ec3e0b 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -37,6 +37,7 @@ #include "anbox/dbus/skeleton/service.h" #include "anbox/container/client.h" #include "anbox/wm/manager.h" +#include "anbox/wm/default_platform_policy.h" #include @@ -89,7 +90,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto input_manager = std::make_shared(rt); - auto window_manager = std::make_shared(); + auto policy = std::make_shared(); + auto window_manager = std::make_shared(policy); auto window_creator = std::make_shared(input_manager); auto renderer = std::make_shared(window_creator); diff --git a/src/anbox/wm/default_platform_policy.cpp b/src/anbox/wm/default_platform_policy.cpp new file mode 100644 index 0000000..9c6cbc9 --- /dev/null +++ b/src/anbox/wm/default_platform_policy.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/default_platform_policy.h" +#include "anbox/wm/window.h" + +namespace { +class Window : public anbox::wm::Window { +public: + Window(const anbox::wm::WindowState &state) : + anbox::wm::Window(state) { + } +}; +} + +namespace anbox { +namespace wm { +DefaultPlatformPolicy::DefaultPlatformPolicy() { +} + +std::shared_ptr DefaultPlatformPolicy::create_window(const WindowState &state) { + return std::make_shared<::Window>(state); +} +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/default_platform_policy.h b/src/anbox/wm/default_platform_policy.h new file mode 100644 index 0000000..e9af49c --- /dev/null +++ b/src/anbox/wm/default_platform_policy.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_DEFAULT_PLATFORM_POLICY_H_ +#define ANBOX_WM_DEFAULT_PLATFORM_POLICY_H_ + +#include "anbox/wm/platform_policy.h" + +namespace anbox { +namespace wm { +class DefaultPlatformPolicy : public PlatformPolicy { +public: + DefaultPlatformPolicy(); + std::shared_ptr create_window(const WindowState &state) override; +}; +} // namespace wm +} // namespace anbox + +#endif diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp index 9e40895..8ef817a 100644 --- a/src/anbox/wm/manager.cpp +++ b/src/anbox/wm/manager.cpp @@ -20,7 +20,8 @@ namespace anbox { namespace wm { -Manager::Manager() { +Manager::Manager(const std::shared_ptr &platform) : + platform_(platform) { } Manager::~Manager() { diff --git a/src/anbox/wm/manager.h b/src/anbox/wm/manager.h index d882321..ebaf4e9 100644 --- a/src/anbox/wm/manager.h +++ b/src/anbox/wm/manager.h @@ -20,17 +20,21 @@ #include "anbox/wm/window_state.h" +#include + namespace anbox { namespace wm { +class PlatformPolicy; class Manager { public: - Manager(); + Manager(const std::shared_ptr &platform); ~Manager(); void apply_window_state_update(const WindowState::List &updated, const WindowState::List &removed); private: + std::shared_ptr platform_; }; } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/platform_policy.cpp b/src/anbox/wm/platform_policy.cpp new file mode 100644 index 0000000..922acf5 --- /dev/null +++ b/src/anbox/wm/platform_policy.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/platform_policy.h" + +namespace anbox { +namespace wm { +PlatformPolicy::~PlatformPolicy() { +} +} // namespace wm +} // namespace anbox diff --git a/src/anbox/wm/platform_policy.h b/src/anbox/wm/platform_policy.h new file mode 100644 index 0000000..7270ae0 --- /dev/null +++ b/src/anbox/wm/platform_policy.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_PLATFORM_POLICY_H_ +#define ANBOX_WM_PLATFORM_POLICY_H_ + +#include "anbox/graphics/rect.h" +#include "anbox/wm/window_state.h" + +#include + +namespace anbox { +namespace wm { +class Window; +class PlatformPolicy { +public: + virtual ~PlatformPolicy(); + + virtual std::shared_ptr create_window(const WindowState &state) = 0; +}; +} // namespace wm +} // namespace anbox + +#endif diff --git a/src/anbox/wm/window.cpp b/src/anbox/wm/window.cpp new file mode 100644 index 0000000..f8b8307 --- /dev/null +++ b/src/anbox/wm/window.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/wm/window.h" + +namespace anbox { +namespace wm { +Window::Window(const WindowState &state) : + state_(state) { +} + +Window::~Window() { +} + +void Window::update_state(const WindowState &state) { + state_ = state; +} + +void Window::render_layer(const Layer &layer) { + (void) layer; +} +} // namespace wm +} // namespace anbox + diff --git a/src/anbox/wm/window.h b/src/anbox/wm/window.h new file mode 100644 index 0000000..687aefd --- /dev/null +++ b/src/anbox/wm/window.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_WM_WINDOW_H_ +#define ANBOX_WM_WINDOW_H_ + +#include "anbox/wm/window_state.h" + +#include +#include + +namespace anbox { +namespace wm { +// FIXME(morphis): move this somewhere else once we have the integration +// with the emugl layer. +class Layer { +public: + graphics::Rect frame() const { return frame_; } + +private: + graphics::Rect frame_; +}; + +class Window { +public: + typedef std::vector List; + + Window(const WindowState &state); + virtual ~Window(); + + void update_state(const WindowState &state); + + // Render a layer into the window. The layer itself includes all + // necessary information for correct rendering. + void render_layer(const Layer &layer); + + WindowState state() const; + +private: + WindowState state_; +}; +} // namespace wm +} // namespace anbox + +#endif From 467874a196324243279cb849017946e4333d1bee Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 13:26:54 +0100 Subject: [PATCH 41/54] Rename Framebuffer to Renderer --- src/CMakeLists.txt | 4 +- src/anbox/graphics/emugl/LayerManager.cpp | 10 +-- src/anbox/graphics/emugl/LayerManager.h | 4 +- src/anbox/graphics/emugl/RenderControl.cpp | 50 +++++------ src/anbox/graphics/emugl/RenderThread.cpp | 8 +- src/anbox/graphics/emugl/RenderWindow.cpp | 10 +-- .../emugl/{FrameBuffer.cpp => Renderer.cpp} | 90 +++++++++---------- .../emugl/{FrameBuffer.h => Renderer.h} | 34 +++---- .../{FbConfig.cpp => RendererConfig.cpp} | 20 ++--- .../emugl/{FbConfig.h => RendererConfig.h} | 26 +++--- src/anbox/graphics/emugl/WindowSurface.cpp | 2 +- 11 files changed, 129 insertions(+), 129 deletions(-) rename src/anbox/graphics/emugl/{FrameBuffer.cpp => Renderer.cpp} (91%) rename src/anbox/graphics/emugl/{FrameBuffer.h => Renderer.h} (93%) rename src/anbox/graphics/emugl/{FbConfig.cpp => RendererConfig.cpp} (93%) rename src/anbox/graphics/emugl/{FbConfig.h => RendererConfig.h} (91%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d49897d..8d00b7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -109,8 +109,8 @@ set(SOURCES anbox/graphics/emugl/ColorBuffer.cpp anbox/graphics/emugl/DisplayManager.cpp - anbox/graphics/emugl/FbConfig.cpp - anbox/graphics/emugl/FrameBuffer.cpp + anbox/graphics/emugl/RendererConfig.cpp + anbox/graphics/emugl/Renderer.cpp anbox/graphics/emugl/LayerManager.cpp anbox/graphics/emugl/NativeSubWindow_delegate.cpp anbox/graphics/emugl/NativeSubWindow.h diff --git a/src/anbox/graphics/emugl/LayerManager.cpp b/src/anbox/graphics/emugl/LayerManager.cpp index ab2e74c..ac3dd2f 100644 --- a/src/anbox/graphics/emugl/LayerManager.cpp +++ b/src/anbox/graphics/emugl/LayerManager.cpp @@ -76,7 +76,7 @@ void LayerManager::post_layer(const LayerInfo &layer) { if (is_layer_blacklisted(layer.name)) return; - FrameBufferWindow *window = nullptr; + RendererWindow *window = nullptr; for (auto &l : layers_) { if (l.first == layer.name || from_same_package(l.first, layer.name)) { window = l.second.window; @@ -99,7 +99,7 @@ void LayerManager::post_layer(const LayerInfo &layer) { layer.source_crop.right, layer.source_crop.bottom); - window = FrameBuffer::getFB()->createWindow(layer.display_frame.left, + window = Renderer::get()->createWindow(layer.display_frame.left, layer.display_frame.top, width, height); if (!window) { @@ -110,17 +110,17 @@ void LayerManager::post_layer(const LayerInfo &layer) { layers_.insert({ layer.name, Layer{window, true}}); } - FrameBuffer::getFB()->updateWindow(window, + Renderer::get()->updateWindow(window, layer.display_frame.left, layer.display_frame.top, width, height); - FrameBuffer::getFB()->post(window, layer.buffer_handle); + Renderer::get()->post(window, layer.buffer_handle); } void LayerManager::finish_cycle() { for (auto iter = layers_.begin(); iter != layers_.end(); ++iter) { if (!iter->second.updated) { - FrameBuffer::getFB()->destroyWindow(iter->second.window); + Renderer::get()->destroyWindow(iter->second.window); layers_.erase(iter); } } diff --git a/src/anbox/graphics/emugl/LayerManager.h b/src/anbox/graphics/emugl/LayerManager.h index 9e7bf5f..79b104e 100644 --- a/src/anbox/graphics/emugl/LayerManager.h +++ b/src/anbox/graphics/emugl/LayerManager.h @@ -24,7 +24,7 @@ #include #include -#include "FrameBuffer.h" +#include "Renderer.h" struct LayerRect { int left; @@ -53,7 +53,7 @@ private: LayerManager(); struct Layer { - FrameBufferWindow *window; + RendererWindow *window; bool updated; }; diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 942e7a4..9e36cc9 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -16,8 +16,8 @@ #include "RenderControl.h" #include "DispatchTables.h" -#include "FbConfig.h" -#include "FrameBuffer.h" +#include "RendererConfig.h" +#include "Renderer.h" #include "RenderThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h" #include "LayerManager.h" @@ -37,7 +37,7 @@ static GLint rcGetRendererVersion() static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return EGL_FALSE; } @@ -49,7 +49,7 @@ static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor) static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -123,7 +123,7 @@ static EGLint rcGetNumConfigs(uint32_t* p_numAttribs) { int numConfigs = 0, numAttribs = 0; - FrameBuffer::getFB()->getConfigs()->getPackInfo(&numConfigs, &numAttribs); + Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs); if (p_numAttribs) { *p_numAttribs = static_cast(numAttribs); } @@ -133,7 +133,7 @@ static EGLint rcGetNumConfigs(uint32_t* p_numAttribs) static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) { GLuint bufferSize = (GLuint)bufSize; - return FrameBuffer::getFB()->getConfigs()->packConfigs(bufferSize, buffer); + return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer); } static EGLint rcChooseConfig(EGLint *attribs, @@ -141,7 +141,7 @@ static EGLint rcChooseConfig(EGLint *attribs, uint32_t *configs, uint32_t configs_size) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb || attribs_size==0) { return 0; } @@ -152,7 +152,7 @@ static EGLint rcChooseConfig(EGLint *attribs, static EGLint rcGetFBParam(EGLint param) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -191,7 +191,7 @@ static EGLint rcGetFBParam(EGLint param) static uint32_t rcCreateContext(uint32_t config, uint32_t share, uint32_t glVersion) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -204,7 +204,7 @@ static uint32_t rcCreateContext(uint32_t config, static void rcDestroyContext(uint32_t context) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -215,7 +215,7 @@ static void rcDestroyContext(uint32_t context) static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width, uint32_t height) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -225,7 +225,7 @@ static uint32_t rcCreateWindowSurface(uint32_t config, static void rcDestroyWindowSurface(uint32_t windowSurface) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -236,7 +236,7 @@ static void rcDestroyWindowSurface(uint32_t windowSurface) static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -246,7 +246,7 @@ static uint32_t rcCreateColorBuffer(uint32_t width, static int rcOpenColorBuffer2(uint32_t colorbuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return -1; } @@ -262,7 +262,7 @@ static void rcOpenColorBuffer(uint32_t colorbuffer) static void rcCloseColorBuffer(uint32_t colorbuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -271,7 +271,7 @@ static void rcCloseColorBuffer(uint32_t colorbuffer) static int rcFlushWindowColorBuffer(uint32_t windowSurface) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return -1; } @@ -284,7 +284,7 @@ static int rcFlushWindowColorBuffer(uint32_t windowSurface) static void rcSetWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -294,7 +294,7 @@ static void rcSetWindowColorBuffer(uint32_t windowSurface, static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf, uint32_t readSurf) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return EGL_FALSE; } @@ -306,7 +306,7 @@ static EGLint rcMakeCurrent(uint32_t context, static void rcFBPost(uint32_t colorBuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -321,7 +321,7 @@ static void rcFBSetSwapInterval(EGLint interval) static void rcBindTexture(uint32_t colorBuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -331,7 +331,7 @@ static void rcBindTexture(uint32_t colorBuffer) static void rcBindRenderbuffer(uint32_t colorBuffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -351,7 +351,7 @@ static void rcReadColorBuffer(uint32_t colorBuffer, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return; } @@ -364,7 +364,7 @@ static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return -1; } @@ -375,7 +375,7 @@ static int rcUpdateColorBuffer(uint32_t colorBuffer, static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } @@ -385,7 +385,7 @@ static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buf static int rcDestroyClientImage(uint32_t image) { - FrameBuffer *fb = FrameBuffer::getFB(); + Renderer *fb = Renderer::get(); if (!fb) { return 0; } diff --git a/src/anbox/graphics/emugl/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp index db9c6a9..2185e8c 100644 --- a/src/anbox/graphics/emugl/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -15,7 +15,7 @@ */ #include "RenderThread.h" -#include "FrameBuffer.h" +#include "Renderer.h" #include "ReadBuffer.h" #include "RenderControl.h" #include "RenderThreadInfo.h" @@ -108,14 +108,14 @@ intptr_t RenderThread::main() { // // Release references to the current thread's context/surfaces if any // - FrameBuffer::getFB()->bindContext(0, 0, 0); + Renderer::get()->bindContext(0, 0, 0); if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) { fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n"); } - FrameBuffer::getFB()->drainWindowSurface(); + Renderer::get()->drainWindowSurface(); - FrameBuffer::getFB()->drainRenderContext(); + Renderer::get()->drainRenderContext(); return 0; } diff --git a/src/anbox/graphics/emugl/RenderWindow.cpp b/src/anbox/graphics/emugl/RenderWindow.cpp index 630d966..a734045 100644 --- a/src/anbox/graphics/emugl/RenderWindow.cpp +++ b/src/anbox/graphics/emugl/RenderWindow.cpp @@ -18,7 +18,7 @@ #include "emugl/common/message_channel.h" #include "emugl/common/mutex.h" #include "emugl/common/thread.h" -#include "FrameBuffer.h" +#include "Renderer.h" #include #include @@ -109,13 +109,13 @@ struct RenderWindowMessage { // Returns true on success, or false on failure. bool process() const { const RenderWindowMessage& msg = *this; - FrameBuffer* fb; + Renderer* fb; bool result = false; switch (msg.cmd) { case CMD_INITIALIZE: D("CMD_INITIALIZE\n"); GL_LOG("RenderWindow: CMD_INITIALIZE"); - result = FrameBuffer::initialize(msg.init.nativeDisplay); + result = Renderer::initialize(msg.init.nativeDisplay); break; case CMD_FINALIZE: @@ -123,7 +123,7 @@ struct RenderWindowMessage { // this command may be issued even when frame buffer is not // yet created (e.g. if CMD_INITIALIZE failed), // so make sure we check if it is there before finalizing - if (const auto fb = FrameBuffer::getFB()) { + if (const auto fb = Renderer::get()) { fb->finalize(); } result = true; @@ -278,7 +278,7 @@ bool RenderWindow::getHardwareStrings(const char** vendor, const char** version) { D("Entering\n"); // TODO(digit): Move this to render window thread. - FrameBuffer* fb = FrameBuffer::getFB(); + Renderer* fb = Renderer::get(); if (!fb) { D("No framebuffer!\n"); return false; diff --git a/src/anbox/graphics/emugl/FrameBuffer.cpp b/src/anbox/graphics/emugl/Renderer.cpp similarity index 91% rename from src/anbox/graphics/emugl/FrameBuffer.cpp rename to src/anbox/graphics/emugl/Renderer.cpp index 64b8323..3bce805 100644 --- a/src/anbox/graphics/emugl/FrameBuffer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "FrameBuffer.h" +#include "Renderer.h" #include "DispatchTables.h" #include "NativeSubWindow.h" @@ -35,7 +35,7 @@ class ScopedBind { public: // Constructor will call bind_locked() on |fb|. // Use isValid() to check for errors. - ScopedBind(FrameBuffer* fb) : mFb(fb) { + ScopedBind(Renderer* fb) : mFb(fb) { if (!mFb->bind_locked()) { mFb = NULL; } @@ -59,14 +59,14 @@ public: } private: - FrameBuffer* mFb; + Renderer* mFb; }; // Implementation of a ColorBuffer::Helper instance that redirects calls // to a FrameBuffer instance. class ColorBufferHelper : public ColorBuffer::Helper { public: - ColorBufferHelper(FrameBuffer* fb) : mFb(fb) {} + ColorBufferHelper(Renderer* fb) : mFb(fb) {} virtual bool setupContext() { return mFb->bind_locked(); @@ -80,13 +80,13 @@ public: return mFb->getTextureDraw(); } private: - FrameBuffer* mFb; + Renderer* mFb; }; } // namespace -FrameBuffer *FrameBuffer::s_theFrameBuffer = NULL; -HandleType FrameBuffer::s_nextHandle = 0; +Renderer *Renderer::s_renderer = NULL; +HandleType Renderer::s_nextHandle = 0; static char* getGLES1ExtensionString(EGLDisplay p_dpy) { @@ -152,7 +152,7 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy) return extString; } -void FrameBuffer::finalize(){ +void Renderer::finalize(){ m_colorbuffers.clear(); m_windows.clear(); m_contexts.clear(); @@ -162,17 +162,17 @@ void FrameBuffer::finalize(){ s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface); } -bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay) +bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { GL_LOG("FrameBuffer::initialize"); - if (s_theFrameBuffer != NULL) { + if (s_renderer != NULL) { return true; } // // allocate space for the FrameBuffer object // - FrameBuffer *fb = new FrameBuffer(); + Renderer *fb = new Renderer(); if (!fb) { ERR("Failed to create fb\n"); return false; @@ -355,7 +355,7 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay) // // Initialize set of configs // - fb->m_configs = new FbConfigList(fb->m_eglDisplay); + fb->m_configs = new RendererConfigList(fb->m_eglDisplay); if (fb->m_configs->empty()) { ERR("Failed: Initialize set of configs\n"); bind.release(); @@ -422,12 +422,12 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay) // // Keep the singleton framebuffer pointer // - s_theFrameBuffer = fb; + s_renderer = fb; GL_LOG("basic EGL initialization successful"); return true; } -FrameBuffer::FrameBuffer() : +Renderer::Renderer() : m_configs(NULL), m_eglDisplay(EGL_NO_DISPLAY), m_colorBufferHelper(new ColorBufferHelper(this)), @@ -447,13 +447,13 @@ FrameBuffer::FrameBuffer() : m_fpsStats = getenv("SHOW_FPS_STATS") != NULL; } -FrameBuffer::~FrameBuffer() { +Renderer::~Renderer() { delete m_textureDraw; delete m_configs; delete m_colorBufferHelper; } -struct FrameBufferWindow { +struct RendererWindow { EGLNativeWindowType native_window = 0; EGLSurface surface = EGL_NO_SURFACE; bool needViewportUpdate = false; @@ -461,7 +461,7 @@ struct FrameBufferWindow { int height; }; -FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height) { +RendererWindow* Renderer::createWindow(int x, int y, int width, int height) { m_lock.lock(); auto native_window = createSubWindow(0, x, y, width, height); @@ -470,7 +470,7 @@ FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height return nullptr; } - auto window = new FrameBufferWindow; + auto window = new RendererWindow; window->native_window = native_window; window->width = width; window->height = height; @@ -502,7 +502,7 @@ FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height return window; } -void FrameBuffer::updateWindow(FrameBufferWindow *window, int x, int y, int width, int height) { +void Renderer::updateWindow(RendererWindow *window, int x, int y, int width, int height) { if (!window) return; @@ -512,7 +512,7 @@ void FrameBuffer::updateWindow(FrameBufferWindow *window, int x, int y, int widt window->needViewportUpdate = true; } -void FrameBuffer::destroyWindow(FrameBufferWindow *window) { +void Renderer::destroyWindow(RendererWindow *window) { if (!window) return; @@ -530,7 +530,7 @@ void FrameBuffer::destroyWindow(FrameBufferWindow *window) { m_lock.unlock(); } -HandleType FrameBuffer::genHandle() +HandleType Renderer::genHandle() { HandleType id; do { @@ -542,7 +542,7 @@ HandleType FrameBuffer::genHandle() return id; } -HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, +HandleType Renderer::createColorBuffer(int p_width, int p_height, GLenum p_internalFormat) { emugl::Mutex::AutoLock mutex(m_lock); @@ -563,13 +563,13 @@ HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, return ret; } -HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share, +HandleType Renderer::createRenderContext(int p_config, HandleType p_share, bool p_isGL2) { emugl::Mutex::AutoLock mutex(m_lock); HandleType ret = 0; - const FbConfig* config = getConfigs()->get(p_config); + const RendererConfig* config = getConfigs()->get(p_config); if (!config) { return ret; } @@ -596,13 +596,13 @@ HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share, return ret; } -HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_height) +HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height) { emugl::Mutex::AutoLock mutex(m_lock); HandleType ret = 0; - const FbConfig* config = getConfigs()->get(p_config); + const RendererConfig* config = getConfigs()->get(p_config); if (!config) { return ret; } @@ -619,7 +619,7 @@ HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_hei return ret; } -void FrameBuffer::drainRenderContext() +void Renderer::drainRenderContext() { emugl::Mutex::AutoLock mutex(m_lock); RenderThreadInfo *tinfo = RenderThreadInfo::get(); @@ -632,7 +632,7 @@ void FrameBuffer::drainRenderContext() tinfo->m_contextSet.clear(); } -void FrameBuffer::drainWindowSurface() +void Renderer::drainWindowSurface() { emugl::Mutex::AutoLock mutex(m_lock); RenderThreadInfo *tinfo = RenderThreadInfo::get(); @@ -654,7 +654,7 @@ void FrameBuffer::drainWindowSurface() tinfo->m_windowSet.clear(); } -void FrameBuffer::DestroyRenderContext(HandleType p_context) +void Renderer::DestroyRenderContext(HandleType p_context) { emugl::Mutex::AutoLock mutex(m_lock); m_contexts.erase(p_context); @@ -663,7 +663,7 @@ void FrameBuffer::DestroyRenderContext(HandleType p_context) tinfo->m_contextSet.erase(p_context); } -void FrameBuffer::DestroyWindowSurface(HandleType p_surface) +void Renderer::DestroyWindowSurface(HandleType p_surface) { emugl::Mutex::AutoLock mutex(m_lock); if (m_windows.find(p_surface) != m_windows.end()) { @@ -674,7 +674,7 @@ void FrameBuffer::DestroyWindowSurface(HandleType p_surface) } } -int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) +int Renderer::openColorBuffer(HandleType p_colorbuffer) { emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); @@ -687,7 +687,7 @@ int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) return 0; } -void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) +void Renderer::closeColorBuffer(HandleType p_colorbuffer) { emugl::Mutex::AutoLock mutex(m_lock); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); @@ -703,7 +703,7 @@ void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) } } -bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) +bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) { emugl::Mutex::AutoLock mutex(m_lock); @@ -720,7 +720,7 @@ bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) return true; } -bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, +bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer) { emugl::Mutex::AutoLock mutex(m_lock); @@ -744,7 +744,7 @@ bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, return true; } -void FrameBuffer::readColorBuffer(HandleType p_colorbuffer, +void Renderer::readColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels) { @@ -759,7 +759,7 @@ void FrameBuffer::readColorBuffer(HandleType p_colorbuffer, (*c).second.cb->readPixels(x, y, width, height, format, type, pixels); } -bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, +bool Renderer::updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels) { @@ -776,7 +776,7 @@ bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, return true; } -bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) +bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) { emugl::Mutex::AutoLock mutex(m_lock); @@ -789,7 +789,7 @@ bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) return (*c).second.cb->bindToTexture(); } -bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) +bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) { emugl::Mutex::AutoLock mutex(m_lock); @@ -802,7 +802,7 @@ bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) return (*c).second.cb->bindToRenderbuffer(); } -bool FrameBuffer::bindContext(HandleType p_context, +bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface) { @@ -891,7 +891,7 @@ bool FrameBuffer::bindContext(HandleType p_context, return true; } -HandleType FrameBuffer::createClientImage(HandleType context, EGLenum target, GLuint buffer) +HandleType Renderer::createClientImage(HandleType context, EGLenum target, GLuint buffer) { RenderContextPtr ctx(NULL); @@ -913,7 +913,7 @@ HandleType FrameBuffer::createClientImage(HandleType context, EGLenum target, GL return (HandleType)reinterpret_cast(image); } -EGLBoolean FrameBuffer::destroyClientImage(HandleType image) +EGLBoolean Renderer::destroyClientImage(HandleType image) { return s_egl.eglDestroyImageKHR(m_eglDisplay, reinterpret_cast(image)); @@ -922,7 +922,7 @@ EGLBoolean FrameBuffer::destroyClientImage(HandleType image) // // The framebuffer lock should be held when calling this function ! // -bool FrameBuffer::bind_locked() +bool Renderer::bind_locked() { EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); @@ -940,7 +940,7 @@ bool FrameBuffer::bind_locked() return true; } -bool FrameBuffer::bindWindow_locked(FrameBufferWindow *window) +bool Renderer::bindWindow_locked(RendererWindow *window) { EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); @@ -958,7 +958,7 @@ bool FrameBuffer::bindWindow_locked(FrameBufferWindow *window) return true; } -bool FrameBuffer::unbind_locked() +bool Renderer::unbind_locked() { if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, m_prevReadSurf, m_prevContext)) { @@ -971,7 +971,7 @@ bool FrameBuffer::unbind_locked() return true; } -bool FrameBuffer::post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock) +bool Renderer::post(RendererWindow *window, HandleType p_colorbuffer, bool needLock) { if (!window) return false; diff --git a/src/anbox/graphics/emugl/FrameBuffer.h b/src/anbox/graphics/emugl/Renderer.h similarity index 93% rename from src/anbox/graphics/emugl/FrameBuffer.h rename to src/anbox/graphics/emugl/Renderer.h index 1a4808d..e41c25b 100644 --- a/src/anbox/graphics/emugl/FrameBuffer.h +++ b/src/anbox/graphics/emugl/Renderer.h @@ -18,7 +18,7 @@ #include "ColorBuffer.h" #include "emugl/common/mutex.h" -#include "FbConfig.h" +#include "RendererConfig.h" #include "RenderContext.h" #include "TextureDraw.h" #include "WindowSurface.h" @@ -51,14 +51,14 @@ typedef std::map ColorBufferMap; // extension is supported. // |eglMajor| and |eglMinor| are the major and minor version numbers of // the underlying EGL implementation. -struct FrameBufferCaps { +struct RendererCaps { bool has_eglimage_texture_2d; bool has_eglimage_renderbuffer; EGLint eglMajor; EGLint eglMinor; }; -struct FrameBufferWindow; +struct RendererWindow; // The FrameBuffer class holds the global state of the emulation library on // top of the underlying EGL/GLES implementation. It should probably be @@ -67,7 +67,7 @@ struct FrameBufferWindow; // There is only one global instance, that can be retrieved with getFB(), // and which must be previously setup by calling initialize(). // -class FrameBuffer { +class Renderer { public: // Initialize the global instance. // |width| and |height| are the dimensions of the emulator GPU display @@ -78,22 +78,22 @@ public: // Returns true on success, false otherwise. static bool initialize(EGLNativeDisplayType nativeDisplay); - FrameBufferWindow* createWindow(int x, int y, int width, int height); - void updateWindow(FrameBufferWindow *window, int x, int y, int width, int height); - void destroyWindow(FrameBufferWindow *window); + RendererWindow* createWindow(int x, int y, int width, int height); + void updateWindow(RendererWindow *window, int x, int y, int width, int height); + void destroyWindow(RendererWindow *window); // Finalize the instance. void finalize(); // Return a pointer to the global instance. initialize() must be called // previously, or this will return NULL. - static FrameBuffer *getFB() { return s_theFrameBuffer; } + static Renderer *get() { return s_renderer; } // Return the capabilities of the underlying display. - const FrameBufferCaps &getCaps() const { return m_caps; } + const RendererCaps &getCaps() const { return m_caps; } // Return the list of configs available from this display. - const FbConfigList* getConfigs() const { return m_configs; } + const RendererConfigList* getConfigs() const { return m_configs; } // Set a callback that will be called each time the emulated GPU content // is updated. This can be relatively slow with host-based GPU emulation, @@ -232,7 +232,7 @@ public: // |needLock| is used to indicate whether the operation requires // acquiring/releasing the FrameBuffer instance's lock. It should be // false only when called internally. - bool post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock = true); + bool post(RendererWindow *window, HandleType p_colorbuffer, bool needLock = true); // Return the host EGLDisplay used by this instance. EGLDisplay getDisplay() const { return m_eglDisplay; } @@ -249,19 +249,19 @@ public: bool unbind_locked(); private: - FrameBuffer(); - ~FrameBuffer(); + Renderer(); + ~Renderer(); HandleType genHandle(); - bool bindWindow_locked(FrameBufferWindow *window); + bool bindWindow_locked(RendererWindow *window); private: - static FrameBuffer *s_theFrameBuffer; + static Renderer *s_renderer; static HandleType s_nextHandle; emugl::Mutex m_lock; - FbConfigList* m_configs; + RendererConfigList* m_configs; FBNativeWindowType m_nativeWindow; - FrameBufferCaps m_caps; + RendererCaps m_caps; EGLDisplay m_eglDisplay; RenderContextMap m_contexts; WindowSurfaceMap m_windows; diff --git a/src/anbox/graphics/emugl/FbConfig.cpp b/src/anbox/graphics/emugl/RendererConfig.cpp similarity index 93% rename from src/anbox/graphics/emugl/FbConfig.cpp rename to src/anbox/graphics/emugl/RendererConfig.cpp index a49a984..09f227a 100644 --- a/src/anbox/graphics/emugl/FbConfig.cpp +++ b/src/anbox/graphics/emugl/RendererConfig.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "FbConfig.h" +#include "RendererConfig.h" #include "OpenGLESDispatch/EGLDispatch.h" @@ -92,11 +92,11 @@ bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) { } // namespace -FbConfig::~FbConfig() { +RendererConfig::~RendererConfig() { delete [] mAttribValues; } -FbConfig::FbConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) : +RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) : mEglConfig(hostConfig), mAttribValues(NULL) { mAttribValues = new GLint[kConfigAttributesLen]; for (size_t i = 0; i < kConfigAttributesLen; ++i) { @@ -114,7 +114,7 @@ FbConfig::FbConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) : } } -FbConfigList::FbConfigList(EGLDisplay display) : +RendererConfigList::RendererConfigList(EGLDisplay display) : mCount(0), mConfigs(NULL), mDisplay(display) { if (display == EGL_NO_DISPLAY) { E("%s: Invalid display value %p (EGL_NO_DISPLAY)\n", @@ -130,27 +130,27 @@ FbConfigList::FbConfigList(EGLDisplay display) : EGLConfig* hostConfigs = new EGLConfig[numHostConfigs]; s_egl.eglGetConfigs(display, hostConfigs, numHostConfigs, &numHostConfigs); - mConfigs = new FbConfig*[numHostConfigs]; + mConfigs = new RendererConfig*[numHostConfigs]; for (EGLint i = 0; i < numHostConfigs; ++i) { // Filter out configs that are not compatible with our implementation. if (!isCompatibleHostConfig(hostConfigs[i], display)) { continue; } - mConfigs[mCount] = new FbConfig(hostConfigs[i], display); + mConfigs[mCount] = new RendererConfig(hostConfigs[i], display); mCount++; } delete [] hostConfigs; } -FbConfigList::~FbConfigList() { +RendererConfigList::~RendererConfigList() { for (int n = 0; n < mCount; ++n) { delete mConfigs[n]; } delete [] mConfigs; } -int FbConfigList::chooseConfig(const EGLint* attribs, +int RendererConfigList::chooseConfig(const EGLint* attribs, EGLint* configs, EGLint configsSize) const { EGLint numHostConfigs = 0; @@ -245,7 +245,7 @@ int FbConfigList::chooseConfig(const EGLint* attribs, } -void FbConfigList::getPackInfo(EGLint* numConfigs, +void RendererConfigList::getPackInfo(EGLint* numConfigs, EGLint* numAttributes) const { if (numConfigs) { *numConfigs = mCount; @@ -255,7 +255,7 @@ void FbConfigList::getPackInfo(EGLint* numConfigs, } } -EGLint FbConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) const { +EGLint RendererConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) const { GLuint numAttribs = static_cast(kConfigAttributesLen); GLuint kGLuintSize = static_cast(sizeof(GLuint)); GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize; diff --git a/src/anbox/graphics/emugl/FbConfig.h b/src/anbox/graphics/emugl/RendererConfig.h similarity index 91% rename from src/anbox/graphics/emugl/FbConfig.h rename to src/anbox/graphics/emugl/RendererConfig.h index 2a653e8..c49ee1a 100644 --- a/src/anbox/graphics/emugl/FbConfig.h +++ b/src/anbox/graphics/emugl/RendererConfig.h @@ -32,10 +32,10 @@ // One doesn't create an FbConfig instance. Instead, create and initialize // an FbConfigList from the host EGLDisplay, and use its size() and get() // methods to access it. -class FbConfig { +class RendererConfig { public: // Destructor - ~FbConfig(); + ~RendererConfig(); // Retrieve host EGLConfig. EGLConfig getEglConfig() const { return mEglConfig; } @@ -57,12 +57,12 @@ public: GLint getConfigId() const { return (GLint)getAttribValue(4); } private: - FbConfig(); - FbConfig(FbConfig& other); + RendererConfig(); + RendererConfig(RendererConfig& other); - explicit FbConfig(EGLConfig hostConfig, EGLDisplay hostDisplay); + explicit RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay); - friend class FbConfigList; + friend class RendererConfigList; GLuint getAttribValue(int n) const { return mAttribValues ? mAttribValues[n] : 0U; @@ -91,7 +91,7 @@ private: // // 5) Use getPackInfo() and packConfigs() to retrieve information about // available configs to the guest. -class FbConfigList { +class RendererConfigList { public: // Create a new list of FbConfig instance, by querying all compatible // host configs from |display|. A compatible config is one that supports @@ -99,10 +99,10 @@ public: // // After construction, call empty() to check if there are items. // An empty list means there was an error during construction. - explicit FbConfigList(EGLDisplay display); + explicit RendererConfigList(EGLDisplay display); // Destructor. - ~FbConfigList(); + ~RendererConfigList(); // Return true iff the list is empty. true means there was an error // during construction. @@ -116,7 +116,7 @@ public: // Retrieve the FbConfig instance associated with |guestId|, // which must be an integer between 0 and |size() - 1|. Returns // NULL in case of failure. - const FbConfig* get(int guestId) const { + const RendererConfig* get(int guestId) const { if (guestId >= 0 && guestId < mCount) { return mConfigs[guestId]; } else { @@ -152,11 +152,11 @@ public: EGLint packConfigs(GLuint bufferByteSize, GLuint* buffer) const; private: - FbConfigList(); - FbConfigList(const FbConfigList& other); + RendererConfigList(); + RendererConfigList(const RendererConfigList& other); int mCount; - FbConfig** mConfigs; + RendererConfig** mConfigs; EGLDisplay mDisplay; }; diff --git a/src/anbox/graphics/emugl/WindowSurface.cpp b/src/anbox/graphics/emugl/WindowSurface.cpp index 553b109..caf7609 100644 --- a/src/anbox/graphics/emugl/WindowSurface.cpp +++ b/src/anbox/graphics/emugl/WindowSurface.cpp @@ -16,7 +16,7 @@ #include "WindowSurface.h" #include "ErrorLog.h" -#include "FbConfig.h" +#include "RendererConfig.h" #include "OpenGLESDispatch/EGLDispatch.h" From fee19cc627518173959a47d97e11b63517331901 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 18 Nov 2016 18:45:53 +0100 Subject: [PATCH 42/54] Drop several debug statements to cleanup output at runtime --- src/anbox/graphics/emugl/RenderServer.cpp | 6 +----- src/anbox/qemu/bootanimation_message_processor.cpp | 1 - src/anbox/qemu/camera_message_processor.cpp | 2 -- src/anbox/qemu/gsm_message_processor.cpp | 1 - src/anbox/qemu/hwcontrol_message_processor.cpp | 4 ++++ src/anbox/qemu/null_message_processor.cpp | 2 +- src/anbox/qemu/pipe_connection_creator.cpp | 2 -- src/anbox/qemu/qemud_message_processor.cpp | 2 -- src/anbox/qemu/sensors_message_processor.cpp | 1 - 9 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/anbox/graphics/emugl/RenderServer.cpp b/src/anbox/graphics/emugl/RenderServer.cpp index 63e211c..5f23093 100644 --- a/src/anbox/graphics/emugl/RenderServer.cpp +++ b/src/anbox/graphics/emugl/RenderServer.cpp @@ -94,8 +94,6 @@ intptr_t RenderServer::main() continue; } - DBG("RenderServer: Got new stream!\n"); - // check if we have been requested to exit while waiting on accept if ((clientFlags & IOSTREAM_CLIENT_EXIT_SERVER) != 0) { m_exiting = true; @@ -133,10 +131,8 @@ intptr_t RenderServer::main() } // if the thread has been created and started, insert it to the list - if (rt) { + if (rt) threads.insert(rt); - DBG("Started new RenderThread\n"); - } } // diff --git a/src/anbox/qemu/bootanimation_message_processor.cpp b/src/anbox/qemu/bootanimation_message_processor.cpp index 398cbce..c166a21 100644 --- a/src/anbox/qemu/bootanimation_message_processor.cpp +++ b/src/anbox/qemu/bootanimation_message_processor.cpp @@ -32,7 +32,6 @@ BootAnimationMessageProcessor::~BootAnimationMessageProcessor() { } void BootAnimationMessageProcessor::handle_command(const std::string &command) { - DEBUG("command %s", command); if (command == "retrieve-icon") retrieve_icon(); } diff --git a/src/anbox/qemu/camera_message_processor.cpp b/src/anbox/qemu/camera_message_processor.cpp index c7c9c6b..c936044 100644 --- a/src/anbox/qemu/camera_message_processor.cpp +++ b/src/anbox/qemu/camera_message_processor.cpp @@ -28,8 +28,6 @@ CameraMessageProcessor::~CameraMessageProcessor() { } bool CameraMessageProcessor::process_data(const std::vector &data) { - DEBUG("Received: %s", utils::hex_dump(data.data(), data.size())); - for (const auto &byte : data) buffer_.push_back(byte); diff --git a/src/anbox/qemu/gsm_message_processor.cpp b/src/anbox/qemu/gsm_message_processor.cpp index 1973587..dc3c945 100644 --- a/src/anbox/qemu/gsm_message_processor.cpp +++ b/src/anbox/qemu/gsm_message_processor.cpp @@ -78,7 +78,6 @@ void GsmMessageProcessor::handle_ctec(const std::string &command) { } void GsmMessageProcessor::handle_cmgf(const std::string &command) { - DEBUG("command %s", command); if (command == "+CMGF=0") send_reply(""); } diff --git a/src/anbox/qemu/hwcontrol_message_processor.cpp b/src/anbox/qemu/hwcontrol_message_processor.cpp index 39f7a30..ebe0369 100644 --- a/src/anbox/qemu/hwcontrol_message_processor.cpp +++ b/src/anbox/qemu/hwcontrol_message_processor.cpp @@ -28,6 +28,7 @@ HwControlMessageProcessor::~HwControlMessageProcessor() { } void HwControlMessageProcessor::handle_command(const std::string &command) { +#if 0 if (command == "power:screen_state:wake") DEBUG("Got screen wake command"); else if (command == "power:screen_state:standby") @@ -36,6 +37,9 @@ void HwControlMessageProcessor::handle_command(const std::string &command) { DEBUG("Got LCD backligh brightness control command"); else DEBUG("Unknown command '%s'", command); +#else + (void) command; +#endif } } // namespace qemu } // namespace anbox diff --git a/src/anbox/qemu/null_message_processor.cpp b/src/anbox/qemu/null_message_processor.cpp index 798e2b7..90a211d 100644 --- a/src/anbox/qemu/null_message_processor.cpp +++ b/src/anbox/qemu/null_message_processor.cpp @@ -30,7 +30,7 @@ NullMessageProcessor::~NullMessageProcessor() { } bool NullMessageProcessor::process_data(const std::vector &data) { - DEBUG("Received: %s", utils::hex_dump(data.data(), data.size())); + (void) data; return true; } } // namespace qemu diff --git a/src/anbox/qemu/pipe_connection_creator.cpp b/src/anbox/qemu/pipe_connection_creator.cpp index 5d81e89..0273d86 100644 --- a/src/anbox/qemu/pipe_connection_creator.cpp +++ b/src/anbox/qemu/pipe_connection_creator.cpp @@ -109,8 +109,6 @@ PipeConnectionCreator::client_type PipeConnectionCreator::identify_client( std::string identifier_and_args = buffer.data(); - DEBUG("identifier %s", identifier_and_args); - if (utils::string_starts_with(identifier_and_args, "pipe:opengles")) return client_type::opengles; // Even if 'boot-properties' is an argument to the service 'qemud' here we diff --git a/src/anbox/qemu/qemud_message_processor.cpp b/src/anbox/qemu/qemud_message_processor.cpp index 80fa4b6..7a39afa 100644 --- a/src/anbox/qemu/qemud_message_processor.cpp +++ b/src/anbox/qemu/qemud_message_processor.cpp @@ -35,8 +35,6 @@ QemudMessageProcessor::~QemudMessageProcessor() { } bool QemudMessageProcessor::process_data(const std::vector &data) { - DEBUG("Received: %s", utils::hex_dump(data.data(), data.size())); - for (const auto &byte : data) buffer_.push_back(byte); diff --git a/src/anbox/qemu/sensors_message_processor.cpp b/src/anbox/qemu/sensors_message_processor.cpp index 4aca92b..5843164 100644 --- a/src/anbox/qemu/sensors_message_processor.cpp +++ b/src/anbox/qemu/sensors_message_processor.cpp @@ -28,7 +28,6 @@ SensorsMessageProcessor::~SensorsMessageProcessor() { } void SensorsMessageProcessor::handle_command(const std::string &command) { - DEBUG("command %s", command); if (command == "list-sensors") list_sensors(); } From d4b4a795c3948445892d095cba28d35b0547dc84 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Sun, 20 Nov 2016 17:08:05 +0100 Subject: [PATCH 43/54] Restructure window creation and mangement --- src/CMakeLists.txt | 8 +- src/anbox/bridge/platform_api_skeleton.cpp | 9 +- src/anbox/cmds/run.cpp | 11 +- src/anbox/graphics/emugl/ColorBuffer.h | 1 - src/anbox/graphics/emugl/LayerManager.cpp | 130 ------------------ src/anbox/graphics/emugl/LayerManager.h | 63 --------- src/anbox/graphics/emugl/NativeSubWindow.h | 68 --------- .../emugl/NativeSubWindow_delegate.cpp | 59 -------- src/anbox/graphics/emugl/RenderControl.cpp | 8 +- src/anbox/graphics/emugl/Renderable.cpp | 38 +++++ src/anbox/graphics/emugl/Renderable.h | 43 ++++++ src/anbox/graphics/emugl/Renderer.cpp | 93 ++++++++----- src/anbox/graphics/emugl/Renderer.h | 14 +- src/anbox/graphics/gl_renderer_server.cpp | 15 +- src/anbox/graphics/gl_renderer_server.h | 3 +- ...window_creator.cpp => platform_policy.cpp} | 75 ++++------ .../{window_creator.h => platform_policy.h} | 40 +++--- src/anbox/ubuntu/window.cpp | 65 ++++++++- src/anbox/ubuntu/window.h | 22 ++- src/anbox/wm/default_platform_policy.cpp | 11 +- src/anbox/wm/manager.cpp | 37 ++++- src/anbox/wm/manager.h | 3 + .../window_creator.cpp => wm/stack.cpp} | 17 +-- .../{graphics/window_creator.h => wm/stack.h} | 30 ++-- src/anbox/wm/window.cpp | 13 +- src/anbox/wm/window.h | 13 +- src/anbox/wm/window_state.cpp | 9 +- src/anbox/wm/window_state.h | 6 +- 28 files changed, 398 insertions(+), 506 deletions(-) delete mode 100644 src/anbox/graphics/emugl/LayerManager.cpp delete mode 100644 src/anbox/graphics/emugl/LayerManager.h delete mode 100644 src/anbox/graphics/emugl/NativeSubWindow.h delete mode 100644 src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp create mode 100644 src/anbox/graphics/emugl/Renderable.cpp create mode 100644 src/anbox/graphics/emugl/Renderable.h rename src/anbox/ubuntu/{window_creator.cpp => platform_policy.cpp} (78%) rename src/anbox/ubuntu/{window_creator.h => platform_policy.h} (56%) rename src/anbox/{graphics/window_creator.cpp => wm/stack.cpp} (74%) rename src/anbox/{graphics/window_creator.h => wm/stack.h} (55%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d00b7b..3d4130f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,17 +103,14 @@ set(SOURCES anbox/graphics/opengles_message_processor.cpp anbox/graphics/gl_renderer_server.cpp - anbox/graphics/window_creator.cpp anbox/graphics/density.h anbox/graphics/rect.cpp anbox/graphics/emugl/ColorBuffer.cpp anbox/graphics/emugl/DisplayManager.cpp anbox/graphics/emugl/RendererConfig.cpp + anbox/graphics/emugl/Renderable.cpp anbox/graphics/emugl/Renderer.cpp - anbox/graphics/emugl/LayerManager.cpp - anbox/graphics/emugl/NativeSubWindow_delegate.cpp - anbox/graphics/emugl/NativeSubWindow.h anbox/graphics/emugl/ReadBuffer.cpp anbox/graphics/emugl/RenderApi.cpp anbox/graphics/emugl/RenderContext.cpp @@ -132,6 +129,7 @@ set(SOURCES anbox/wm/display.cpp anbox/wm/task.cpp + anbox/wm/stack.cpp anbox/wm/manager.cpp anbox/wm/window_state.cpp anbox/wm/window.cpp @@ -158,9 +156,9 @@ set(SOURCES anbox/bridge/platform_api_skeleton.cpp anbox/bridge/android_api_stub.cpp - anbox/ubuntu/window_creator.cpp anbox/ubuntu/window.cpp anbox/ubuntu/keycode_converter.cpp + anbox/ubuntu/platform_policy.cpp anbox/dbus/interface.h anbox/dbus/skeleton/service.cpp diff --git a/src/anbox/bridge/platform_api_skeleton.cpp b/src/anbox/bridge/platform_api_skeleton.cpp index 34d87fb..9f0e724 100644 --- a/src/anbox/bridge/platform_api_skeleton.cpp +++ b/src/anbox/bridge/platform_api_skeleton.cpp @@ -51,12 +51,17 @@ void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowSta (void) response; auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdate_WindowState &window) { + DEBUG("Window: display=%d has_surface=%d frame={%d,%d,%d,%d} package=%s task=%d stack=-1", + window.display_id(), window.has_surface(), + window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom(), + window.package_name(), window.task_id()); return wm::WindowState( wm::Display::Id(window.display_id()), window.has_surface(), graphics::Rect(window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom()), window.package_name(), - wm::Task::Id(window.task_id())); + wm::Task::Id(window.task_id()), + wm::Stack::Id(wm::Stack::Invalid)); }; wm::WindowState::List updated; @@ -68,7 +73,7 @@ void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowSta wm::WindowState::List removed; for (int n = 0; n < request->removed_windows_size(); n++) { const auto window = request->removed_windows(n); - updated.push_back(convert_window_state(window)); + removed.push_back(convert_window_state(window)); } window_manager_->apply_window_state_update(updated, removed); diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 9ec3e0b..26c7c9d 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -33,11 +33,10 @@ #include "anbox/bridge/platform_message_processor.h" #include "anbox/bridge/android_api_stub.h" #include "anbox/bridge/platform_api_skeleton.h" -#include "anbox/ubuntu/window_creator.h" #include "anbox/dbus/skeleton/service.h" #include "anbox/container/client.h" #include "anbox/wm/manager.h" -#include "anbox/wm/default_platform_policy.h" +#include "anbox/ubuntu/platform_policy.h" #include @@ -90,11 +89,13 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto input_manager = std::make_shared(rt); - auto policy = std::make_shared(); + auto policy = std::make_shared(input_manager); + // FIXME this needs to be removed and solved differently behind the scenes + registerDisplayManager(policy); + auto window_manager = std::make_shared(policy); - auto window_creator = std::make_shared(input_manager); - auto renderer = std::make_shared(window_creator); + auto renderer = std::make_shared(); renderer->start(); // Socket which will be used by the qemud service inside the Android diff --git a/src/anbox/graphics/emugl/ColorBuffer.h b/src/anbox/graphics/emugl/ColorBuffer.h index a9ce3c5..152b16b 100644 --- a/src/anbox/graphics/emugl/ColorBuffer.h +++ b/src/anbox/graphics/emugl/ColorBuffer.h @@ -23,7 +23,6 @@ #include - class TextureDraw; class TextureResize; diff --git a/src/anbox/graphics/emugl/LayerManager.cpp b/src/anbox/graphics/emugl/LayerManager.cpp deleted file mode 100644 index ac3dd2f..0000000 --- a/src/anbox/graphics/emugl/LayerManager.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -#include "LayerManager.h" - -#include - -#include - -namespace { -std::string get_package_name(const std::string &name) { - return name; -} - -bool is_layer_blacklisted(const std::string &name) { - static std::vector blacklist = { - // The boot animation should be disabled already but we blacklist it - // here too to ensure it is never visible. - "BootAnimation", - "StatusBar", - "Sprite", - "KeyguardScrim", - "com.android.launcher/com.android.launcher2.Launcher", - "com.android.settings/com.android.settings.FallbackHome", - "com.android.systemui.ImageWallpaper", - "InputMethod", - "com.android.quicksearchbox/com.android.quicksearchbox.SearchActivity", - }; - return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end(); -} - -struct ActivityInfo { - ActivityInfo(const std::string &name) : - name(name) { - std::vector parts; - boost::split(parts, name, boost::is_any_of("/")); - if (parts.size() > 1) - package = parts[0]; - } - - std::string package; - std::string name; -}; - -bool from_same_package(const std::string &a, const std::string &b) { - return ActivityInfo(a).package == ActivityInfo(b).package; -} -} - -std::shared_ptr LayerManager::get() { - static auto self = std::shared_ptr{new LayerManager}; - return self; -} - -LayerManager::LayerManager() { -} - -LayerManager::~LayerManager() { -} - -void LayerManager::post_layer(const LayerInfo &layer) { - if (is_layer_blacklisted(layer.name)) - return; - - RendererWindow *window = nullptr; - for (auto &l : layers_) { - if (l.first == layer.name || from_same_package(l.first, layer.name)) { - window = l.second.window; - l.second.updated = true; - } - } - - auto width = layer.display_frame.right - layer.display_frame.left; - auto height = layer.display_frame.bottom - layer.display_frame.top; - - if (!window) { - printf("New layer '%s' display_frame={%d,%d,%d,%d} source_crop={%d,%d,%d,%d}\n", - layer.name.c_str(), - layer.display_frame.left, - layer.display_frame.top, - layer.display_frame.right, - layer.display_frame.bottom, - layer.source_crop.left, - layer.source_crop.top, - layer.source_crop.right, - layer.source_crop.bottom); - - window = Renderer::get()->createWindow(layer.display_frame.left, - layer.display_frame.top, - width, height); - if (!window) { - printf("Failed to create window for layer '%s'\n", layer.name.c_str()); - return; - } - - layers_.insert({ layer.name, Layer{window, true}}); - } - - Renderer::get()->updateWindow(window, - layer.display_frame.left, - layer.display_frame.top, - width, height); - Renderer::get()->post(window, layer.buffer_handle); -} - -void LayerManager::finish_cycle() { - for (auto iter = layers_.begin(); iter != layers_.end(); ++iter) { - if (!iter->second.updated) { - Renderer::get()->destroyWindow(iter->second.window); - layers_.erase(iter); - } - } - - for (auto &layer : layers_) - layer.second.updated = false; -} diff --git a/src/anbox/graphics/emugl/LayerManager.h b/src/anbox/graphics/emugl/LayerManager.h deleted file mode 100644 index 79b104e..0000000 --- a/src/anbox/graphics/emugl/LayerManager.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 Simon Fels - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - */ - -#ifndef LAYER_MANAGER_H_ -#define LAYER_MANAGER_H_ - -#include - -#include -#include -#include - -#include "Renderer.h" - -struct LayerRect { - int left; - int top; - int right; - int bottom; -}; - -struct LayerInfo { - std::string name; - LayerRect source_crop; - LayerRect display_frame; - HandleType buffer_handle; -}; - -class LayerManager { -public: - static std::shared_ptr get(); - - ~LayerManager(); - - void post_layer(const LayerInfo &layer); - void finish_cycle(); - -private: - LayerManager(); - - struct Layer { - RendererWindow *window; - bool updated; - }; - - std::map layers_; -}; - -#endif diff --git a/src/anbox/graphics/emugl/NativeSubWindow.h b/src/anbox/graphics/emugl/NativeSubWindow.h deleted file mode 100644 index bc3540c..0000000 --- a/src/anbox/graphics/emugl/NativeSubWindow.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (C) 2011 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. -*/ -#ifndef NATIVE_SUB_WINDOW_H -#define NATIVE_SUB_WINDOW_H - -#include "OpenglRender/render_api_platform_types.h" - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -class SubWindowHandler { -public: - virtual ~SubWindowHandler() { } - virtual EGLNativeWindowType create_window(int x, int y, int width, int height) = 0; - virtual void update_window(EGLNativeWindowType win, int x, int y, int width, int height) = 0; - virtual void destroy_window(EGLNativeWindowType win) = 0; -}; - -void registerSubWindowHandler(const std::shared_ptr &handler); - -// Create a new sub-window that will be used to display the content of the -// emulated GPU on top of the regular UI window. -// |p_window| is the platform-specific handle to the main UI window. -// |x|, |y| is the position sub-window relative to the top-left corner of the -// main window. -// |width| and |height| are the dimensions of the sub-window, as well as of -// the emulated framebuffer. -// |repaint_callback| may be invoked every time the window has to be repainted -// (such as receiving a WM_PAINT event on Windows). If the provided argument is -// NULL, nothing will be invoked. -// |repaint_callback_param| an additional parameter that will be passed to the -// repaint callback when/if it's invoked. -// On success, return a new platform-specific window handle, cast as an -// EGLNativeWindowType. Or 0/NULL in case of failure. -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height); - -void updateSubWindow(EGLNativeWindowType win, int x, int y, int width, int height); - -// Destroy a sub-window previously created through createSubWindow() above. -void destroySubWindow(EGLNativeWindowType win); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp b/src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp deleted file mode 100644 index 172e3da..0000000 --- a/src/anbox/graphics/emugl/NativeSubWindow_delegate.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (C) 2011 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 "NativeSubWindow.h" - -#include -#include -#include - -namespace { -static std::shared_ptr current_handler = nullptr; -} - -void registerSubWindowHandler(const std::shared_ptr &handler) { - if (current_handler) - throw std::runtime_error("A sub window handle is already registered"); - - current_handler = handler; -} - -EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, - int x, - int y, - int width, - int height) { - (void) p_window; - - if (!current_handler) - return (EGLNativeWindowType) 0; - - return current_handler->create_window(x, y, width, height); -} - -void updateSubWindow(EGLNativeWindowType win, int x, int y, int width, int height) { - if (!current_handler) - return; - - return current_handler->update_window(win, x, y, width, height); -} - -void destroySubWindow(EGLNativeWindowType win) { - if (!current_handler) - return; - - return current_handler->destroy_window(win); -} diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 9e36cc9..9c971cc 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -20,7 +20,6 @@ #include "Renderer.h" #include "RenderThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h" -#include "LayerManager.h" #include "DisplayManager.h" #include "OpenGLESDispatch/EGLDispatch.h" @@ -432,14 +431,9 @@ void rcPostLayer(const char *name, uint32_t color_buffer, int32_t displayFrameLeft, int32_t displayFrameTop, int32_t displayFrameRight, int32_t displayFrameBottom) { - LayerRect source_crop{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}; - LayerRect display_frame{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom}; - LayerManager::get()->post_layer({name, source_crop, display_frame, color_buffer}); } -void rcPostAllLayersDone() -{ - LayerManager::get()->finish_cycle(); +void rcPostAllLayersDone() { } void initRenderControlContext(renderControl_decoder_context_t *dec) diff --git a/src/anbox/graphics/emugl/Renderable.cpp b/src/anbox/graphics/emugl/Renderable.cpp new file mode 100644 index 0000000..b68b984 --- /dev/null +++ b/src/anbox/graphics/emugl/Renderable.cpp @@ -0,0 +1,38 @@ +/* +* Copyright (C) 2016 Simon Fels +* +* 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 "Renderable.h" + +Renderable::Renderable(const std::uint32_t &buffer, + const anbox::graphics::Rect &screen_position) : + buffer_(buffer), + screen_position_(screen_position) +{ +} + +Renderable::~Renderable() +{ +} + +std::uint32_t Renderable::buffer() const +{ + return buffer_; +} + +anbox::graphics::Rect Renderable::screen_position() const +{ + return screen_position_; +} diff --git a/src/anbox/graphics/emugl/Renderable.h b/src/anbox/graphics/emugl/Renderable.h new file mode 100644 index 0000000..164f59f --- /dev/null +++ b/src/anbox/graphics/emugl/Renderable.h @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2016 Simon Fels +* +* 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. +*/ + +#ifndef ANBOX_GRAPHICS_EMUGL_RENDERABLE_H_ +#define ANBOX_GRAPHICS_EMUGL_RENDERABLE_H_ + +#include "anbox/graphics/rect.h" + +#include + +#include + +class Renderable +{ +public: + Renderable(const std::uint32_t &buffer, + const anbox::graphics::Rect &screen_position); + ~Renderable(); + + std::uint32_t buffer() const; + anbox::graphics::Rect screen_position() const; + +private: + std::uint32_t buffer_; + anbox::graphics::Rect screen_position_; +}; + +typedef std::vector RenderableList; + +#endif diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index 3bce805..f6c67a0 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -17,7 +17,6 @@ #include "Renderer.h" #include "DispatchTables.h" -#include "NativeSubWindow.h" #include "RenderThreadInfo.h" #include "TimeUtils.h" #include "gles2_dec.h" @@ -456,40 +455,32 @@ Renderer::~Renderer() { struct RendererWindow { EGLNativeWindowType native_window = 0; EGLSurface surface = EGL_NO_SURFACE; - bool needViewportUpdate = false; - int width; - int height; }; -RendererWindow* Renderer::createWindow(int x, int y, int width, int height) { +RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window) +{ m_lock.lock(); - auto native_window = createSubWindow(0, x, y, width, height); - if (!native_window) { - m_lock.unlock(); - return nullptr; - } - auto window = new RendererWindow; window->native_window = native_window; - window->width = width; - window->height = height; - window->surface = s_egl.eglCreateWindowSurface( m_eglDisplay, m_eglConfig, window->native_window, nullptr); - if (window->surface == EGL_NO_SURFACE) { - destroyWindow(window); + if (window->surface == EGL_NO_SURFACE) + { + delete window; m_lock.unlock(); return nullptr; } - if (!bindWindow_locked(window)) { - destroyWindow(window); + if (!bindWindow_locked(window)) + { + s_egl.eglDestroySurface(m_eglDisplay, window->surface); + delete window; m_lock.unlock(); return nullptr; } - s_gles2.glViewport(0, 0, width, height); + // s_gles2.glViewport(0, 0, width, height); s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -497,35 +488,27 @@ RendererWindow* Renderer::createWindow(int x, int y, int width, int height) { unbind_locked(); + m_nativeWindows.insert({native_window, window}); + m_lock.unlock(); return window; } -void Renderer::updateWindow(RendererWindow *window, int x, int y, int width, int height) { - if (!window) - return; - - updateSubWindow(window->native_window, x, y, width, height); - window->width = width; - window->height = height; - window->needViewportUpdate = true; -} - -void Renderer::destroyWindow(RendererWindow *window) { - if (!window) +void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) { + auto w = m_nativeWindows.find(native_window); + if (w == m_nativeWindows.end()) return; m_lock.lock(); s_egl.eglMakeCurrent(m_eglDisplay, nullptr, nullptr, nullptr); - if (window->surface != EGL_NO_SURFACE) - s_egl.eglDestroySurface(m_eglDisplay, window->surface); + if (w->second->surface != EGL_NO_SURFACE) + s_egl.eglDestroySurface(m_eglDisplay, w->second->surface); - destroySubWindow(window->native_window); - - delete window; + delete w->second; + m_nativeWindows.erase(w); m_lock.unlock(); } @@ -990,10 +973,12 @@ bool Renderer::post(RendererWindow *window, HandleType p_colorbuffer, bool needL if (!bindWindow_locked(window)) goto EXIT; +#if 0 if (window->needViewportUpdate) { s_gles2.glViewport(0, 0, window->width, window->height); window->needViewportUpdate = false; } +#endif s_gles2.glClearColor(0.0, 0.0, 1.0, 0.0); s_gles2.glClear(GL_COLOR_BUFFER_BIT); @@ -1029,3 +1014,39 @@ EXIT: } return ret; } + +bool Renderer::draw(EGLNativeWindowType native_window, const RenderableList &renderables) +{ + auto w = m_nativeWindows.find(native_window); + if (w == m_nativeWindows.end()) + return false; + + if (!bindWindow_locked(w->second)) + { + m_lock.unlock(); + return false; + } + + s_gles2.glClearColor(0.0, 0.0, 1.0, 0.0); + s_gles2.glClear(GL_COLOR_BUFFER_BIT); + + for (const auto &renderable : renderables) + { + const auto &color_buffer = m_colorbuffers.find(renderable.buffer()); + if (color_buffer == m_colorbuffers.end()) + continue; + + color_buffer->second.cb->post(0.0f, + renderable.screen_position().left(), renderable.screen_position().top()); + } + + s_egl.eglSwapBuffers(m_eglDisplay, w->second->surface); + + unbind_locked(); + + m_lock.lock(); + + m_lock.unlock(); + + return false; +} diff --git a/src/anbox/graphics/emugl/Renderer.h b/src/anbox/graphics/emugl/Renderer.h index e41c25b..4ef0851 100644 --- a/src/anbox/graphics/emugl/Renderer.h +++ b/src/anbox/graphics/emugl/Renderer.h @@ -25,6 +25,8 @@ #include "OpenglRender/render_api.h" +#include "Renderable.h" + #include #include @@ -78,10 +80,6 @@ public: // Returns true on success, false otherwise. static bool initialize(EGLNativeDisplayType nativeDisplay); - RendererWindow* createWindow(int x, int y, int width, int height); - void updateWindow(RendererWindow *window, int x, int y, int width, int height); - void destroyWindow(RendererWindow *window); - // Finalize the instance. void finalize(); @@ -111,6 +109,10 @@ public: *version = m_glVersion; } + RendererWindow* createNativeWindow(EGLNativeWindowType native_window); + void destroyNativeWindow(RendererWindow *window); + void destroyNativeWindow(EGLNativeWindowType native_window); + // Create a new RenderContext instance for this display instance. // |p_config| is the index of one of the configs returned by getConfigs(). // |p_share| is either EGL_NO_CONTEXT or the handle of a shared context. @@ -234,6 +236,8 @@ public: // false only when called internally. bool post(RendererWindow *window, HandleType p_colorbuffer, bool needLock = true); + bool draw(EGLNativeWindowType native_window, const RenderableList &renderables); + // Return the host EGLDisplay used by this instance. EGLDisplay getDisplay() const { return m_eglDisplay; } @@ -286,5 +290,7 @@ private: const char* m_glVendor; const char* m_glRenderer; const char* m_glVersion; + + std::map m_nativeWindows; }; #endif diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index e7cc739..60d02cd 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -17,7 +17,6 @@ #include "anbox/logger.h" #include "anbox/graphics/gl_renderer_server.h" -#include "anbox/graphics/window_creator.h" #include "OpenglRender/render_api.h" @@ -27,8 +26,8 @@ namespace anbox { namespace graphics { -GLRendererServer::GLRendererServer(const std::shared_ptr &window_creator) : - window_creator_(window_creator) { +GLRendererServer::GLRendererServer() +{ if (utils::is_env_set("USE_HOST_GLES")) { // Force the host EGL/GLES libraries as translator implementation @@ -44,13 +43,9 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &window_ if (!initLibrary()) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); - - registerSubWindowHandler(window_creator_); - registerDisplayManager(window_creator_); } GLRendererServer::~GLRendererServer() { - // destroyOpenGLSubwindow(); stopOpenGLRenderer(); } @@ -70,15 +65,11 @@ void GLRendererServer::start() { log_funcs.coarse = logger_write; log_funcs.fine = logger_write; - auto display_info = window_creator_->display_info(); - const auto width = display_info.horizontal_resolution; - const auto height = display_info.vertical_resolution; - char server_addr[256] = { 0 }; // The width & height we supply here are the dimensions the internal framebuffer // will use. Making this static prevents us for now to resize the window we create // later for the actual display. - if (!initOpenGLRenderer(window_creator_->native_display(), server_addr, sizeof(server_addr), log_funcs, logger_write)) + if (!initOpenGLRenderer(0, server_addr, sizeof(server_addr), log_funcs, logger_write)) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); socket_path_ = server_addr; diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index 4b5fad9..f6159cf 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -29,7 +29,7 @@ namespace graphics { class WindowCreator; class GLRendererServer { public: - GLRendererServer(const std::shared_ptr &window_creator); + GLRendererServer(); ~GLRendererServer(); void start(); @@ -38,7 +38,6 @@ public: private: std::string socket_path_; - std::shared_ptr window_creator_; }; } // namespace graphics diff --git a/src/anbox/ubuntu/window_creator.cpp b/src/anbox/ubuntu/platform_policy.cpp similarity index 78% rename from src/anbox/ubuntu/window_creator.cpp rename to src/anbox/ubuntu/platform_policy.cpp index cad4160..b415a03 100644 --- a/src/anbox/ubuntu/window_creator.cpp +++ b/src/anbox/ubuntu/platform_policy.cpp @@ -15,7 +15,7 @@ * */ -#include "anbox/ubuntu/window_creator.h" +#include "anbox/ubuntu/platform_policy.h" #include "anbox/ubuntu/window.h" #include "anbox/ubuntu/keycode_converter.h" #include "anbox/input/manager.h" @@ -29,16 +29,14 @@ namespace anbox { namespace ubuntu { -WindowCreator::WindowCreator(const std::shared_ptr &input_manager) : - graphics::WindowCreator(input_manager), +PlatformPolicy::PlatformPolicy(const std::shared_ptr &input_manager) : input_manager_(input_manager), - event_thread_running_(false), - display_info_({1920, 1080}) { + event_thread_running_(false) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize SDL")); - event_thread_ = std::thread(&WindowCreator::process_events, this); + event_thread_ = std::thread(&PlatformPolicy::process_events, this); SDL_DisplayMode display_mode; // FIXME statically just check the first (primary) display for its mode; @@ -71,12 +69,12 @@ WindowCreator::WindowCreator(const std::shared_ptr &input_manage keyboard_->set_key_bit(KEY_OK); } -WindowCreator::~WindowCreator() { +PlatformPolicy::~PlatformPolicy() { event_thread_running_ = false; event_thread_.join(); } -void WindowCreator::process_events() { +void PlatformPolicy::process_events() { event_thread_running_ = true; while(event_thread_running_) { @@ -90,9 +88,11 @@ void WindowCreator::process_events() { break; case SDL_WINDOWEVENT: for (auto &iter : windows_) { - if (iter.second->id() == event.window.windowID) { - iter.second->process_event(event); - break; + if (auto w = iter.second.lock()) { + if (w->window_id() == event.window.windowID) { + w->process_event(event); + break; + } } } break; @@ -109,7 +109,7 @@ void WindowCreator::process_events() { } } -void WindowCreator::process_input_event(const SDL_Event &event) { +void PlatformPolicy::process_input_event(const SDL_Event &event) { std::vector mouse_events; std::vector keyboard_events; @@ -176,44 +176,29 @@ void WindowCreator::process_input_event(const SDL_Event &event) { keyboard_->send_events(keyboard_events); } -EGLNativeWindowType WindowCreator::create_window(int x, int y, int width, int height) -try { - auto window = std::make_shared(x, y, width, height); - if (not window) - BOOST_THROW_EXCEPTION(std::bad_alloc()); - - windows_.insert({window->native_window(), window}); - - return window->native_window(); -} -catch (std::exception &err) { - DEBUG("Failed to create window: %s", err.what()); - return 0; +Window::Id PlatformPolicy::next_window_id() { + static Window::Id next_id = 0; + return next_id++; } -void WindowCreator::update_window(EGLNativeWindowType win, int x, int y, int width, int height) { - auto iter = windows_.find(win); - if (iter == windows_.end()) +std::shared_ptr PlatformPolicy::create_window(const wm::WindowState &state) { + auto id = next_window_id(); + auto w = std::make_shared(id, shared_from_this(), state); + windows_.insert({id, w}); + return w; +} + +void PlatformPolicy::window_deleted(const Window::Id &id) { + auto w = windows_.find(id); + if (w == windows_.end()) { + WARNING("Got window removed event for unknown window (id %d)", id); return; - - iter->second->resize(width, height); - iter->second->update_position(x, y); + } + windows_.erase(w); } -void WindowCreator::destroy_window(EGLNativeWindowType win) { - auto iter = windows_.find(win); - if (iter == windows_.end()) - return; - - windows_.erase(iter); -} - -WindowCreator::DisplayInfo WindowCreator::display_info() const { +DisplayManager::DisplayInfo PlatformPolicy::display_info() const { return display_info_; } - -EGLNativeDisplayType WindowCreator::native_display() const { - return 0; -} -} // namespace bridge +} // namespace wm } // namespace anbox diff --git a/src/anbox/ubuntu/window_creator.h b/src/anbox/ubuntu/platform_policy.h similarity index 56% rename from src/anbox/ubuntu/window_creator.h rename to src/anbox/ubuntu/platform_policy.h index 4117aea..dd1083c 100644 --- a/src/anbox/ubuntu/window_creator.h +++ b/src/anbox/ubuntu/platform_policy.h @@ -15,15 +15,17 @@ * */ -#ifndef ANBOX_UBUNTU_WINDOW_CREATOR_H_ -#define ANBOX_UBUNTU_WINDOW_CREATOR_H_ +#ifndef ANBOX_UBUNTU_PLATFORM_POLICY_H_ +#define ANBOX_UBUNTU_PLATFORM_POLICY_H_ -#include "anbox/graphics/window_creator.h" +#include "anbox/wm/platform_policy.h" +#include "anbox/ubuntu/window.h" + +#include "anbox/graphics/emugl/DisplayManager.h" -#include #include +#include -#include #include namespace anbox { @@ -32,34 +34,38 @@ class Device; class Manager; } // namespace input namespace ubuntu { -class MirDisplayConnection; -class Window; -class WindowCreator : public graphics::WindowCreator { +class PlatformPolicy : public std::enable_shared_from_this, + public wm::PlatformPolicy, + public Window::Observer, + public DisplayManager { public: - WindowCreator(const std::shared_ptr &input_manager); - ~WindowCreator(); + PlatformPolicy(const std::shared_ptr &input_manager); + ~PlatformPolicy(); - EGLNativeWindowType create_window(int x, int y, int width, int height) override; - void update_window(EGLNativeWindowType win, int x, int y, int width, int height) override; - void destroy_window(EGLNativeWindowType win) override; + std::shared_ptr create_window(const wm::WindowState &state) override; + + void window_deleted(const Window::Id &id) override; DisplayInfo display_info() const override; - EGLNativeDisplayType native_display() const override; private: void process_events(); void process_input_event(const SDL_Event &event); + static Window::Id next_window_id(); + std::shared_ptr input_manager_; - std::map> windows_; + // We don't own the windows anymore after the got created by us so we + // need to be careful once we try to use them again. + std::map> windows_; std::shared_ptr current_window_; std::thread event_thread_; bool event_thread_running_; - graphics::WindowCreator::DisplayInfo display_info_; std::shared_ptr pointer_; std::shared_ptr keyboard_; + DisplayManager::DisplayInfo display_info_; }; -} // namespace ubuntu +} // namespace wm } // namespace anbox #endif diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index 1e68f3e..8ca34f1 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -16,15 +16,69 @@ */ #include "anbox/ubuntu/window.h" +#include "anbox/wm/window_state.h" #include "anbox/logger.h" #include #include +namespace { +constexpr const char* default_window_name{"anbox"}; +} + namespace anbox { namespace ubuntu { +Window::Id Window::Invalid{-1}; + +Window::Observer::~Observer() { +} + +Window::Window(const Id &id, + const std::shared_ptr &observer, + const wm::WindowState &state) : + wm::Window(state), + id_(id), + observer_(observer), + native_display_(0), + native_window_(0) { + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + + window_ = SDL_CreateWindow(default_window_name, + state.frame().left(), + state.frame().top(), + state.frame().width(), + state.frame().height(), + SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); + if (!window_) { + const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); + BOOST_THROW_EXCEPTION(std::runtime_error(message)); + } + + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + SDL_GetWindowWMInfo(window_, &info); + switch (info.subsystem) { + case SDL_SYSWM_X11: + DEBUG("Running on X11"); + native_display_ = static_cast(info.info.x11.display); + native_window_ = static_cast(info.info.x11.window); + break; + default: + ERROR("Unknown subsystem (%d)", info.subsystem); + BOOST_THROW_EXCEPTION(std::runtime_error("SDL subsystem not suported")); + } + + int actual_width = 0, actual_height = 0; + int actual_x = 0, actual_y = 0; + SDL_GetWindowSize(window_, &actual_width, &actual_height); + SDL_GetWindowPosition(window_, &actual_x, &actual_y); + DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height); +} + Window::Window(int x, int y, int width, int height) : + wm::Window(wm::WindowState()), native_display_(0), native_window_(0) { @@ -60,6 +114,9 @@ Window::Window(int x, int y, int width, int height) : Window::~Window() { if (window_) SDL_DestroyWindow(window_); + + if (observer_) + observer_->window_deleted(id_); } void Window::resize(int width, int height) { @@ -89,11 +146,15 @@ void Window::process_event(const SDL_Event &event) { } } -EGLNativeWindowType Window::native_window() const { +EGLNativeWindowType Window::native_handle() const { return native_window_; } -std::uint32_t Window::id() const { +Window::Id Window::id() const { + return id_; +} + +std::uint32_t Window::window_id() const { return SDL_GetWindowID(window_); } } // namespace bridge diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index 52fcb4a..ceb3bcb 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -18,6 +18,8 @@ #ifndef ANBOX_UBUNTU_WINDOW_H_ #define ANBOX_UBUNTU_WINDOW_H_ +#include "anbox/wm/window.h" + #include #include @@ -27,8 +29,19 @@ namespace anbox { namespace ubuntu { -class Window { +class Window : public std::enable_shared_from_this, + public wm::Window { public: + typedef std::int32_t Id; + static Id Invalid; + + class Observer { + public: + virtual ~Observer(); + virtual void window_deleted(const Id &id) = 0; + }; + + Window(const Id &id, const std::shared_ptr &observer, const wm::WindowState &state); Window(int x, int y, int width, int height); ~Window(); @@ -37,10 +50,13 @@ public: void process_event(const SDL_Event &event); - EGLNativeWindowType native_window() const; - std::uint32_t id() const; + EGLNativeWindowType native_handle() const override; + Id id() const; + std::uint32_t window_id() const; private: + Id id_; + std::shared_ptr observer_; EGLNativeDisplayType native_display_; EGLNativeWindowType native_window_; SDL_Window *window_; diff --git a/src/anbox/wm/default_platform_policy.cpp b/src/anbox/wm/default_platform_policy.cpp index 9c6cbc9..f37e1c2 100644 --- a/src/anbox/wm/default_platform_policy.cpp +++ b/src/anbox/wm/default_platform_policy.cpp @@ -17,11 +17,12 @@ #include "anbox/wm/default_platform_policy.h" #include "anbox/wm/window.h" +#include "anbox/logger.h" namespace { -class Window : public anbox::wm::Window { +class NullWindow : public anbox::wm::Window { public: - Window(const anbox::wm::WindowState &state) : + NullWindow(const anbox::wm::WindowState &state) : anbox::wm::Window(state) { } }; @@ -32,8 +33,10 @@ namespace wm { DefaultPlatformPolicy::DefaultPlatformPolicy() { } -std::shared_ptr DefaultPlatformPolicy::create_window(const WindowState &state) { - return std::make_shared<::Window>(state); +std::shared_ptr DefaultPlatformPolicy::create_window(const WindowState &state) +{ + DEBUG(""); + return std::make_shared<::NullWindow>(state); } } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp index 8ef817a..a6b9fa9 100644 --- a/src/anbox/wm/manager.cpp +++ b/src/anbox/wm/manager.cpp @@ -16,6 +16,7 @@ */ #include "anbox/wm/manager.h" +#include "anbox/wm/platform_policy.h" #include "anbox/logger.h" namespace anbox { @@ -28,11 +29,39 @@ Manager::~Manager() { } void Manager::apply_window_state_update(const WindowState::List &updated, - const WindowState::List &removed) { - (void) updated; - (void) removed; - + const WindowState::List &removed) +{ DEBUG("updated %d removed %d", updated.size(), removed.size()); + + // Base on the update we get from the Android WindowManagerService we will create + // different window instances with the properties supplied. Incoming layer updates + // from SurfaceFlinger will be mapped later into those windows and eventually + // composited there via GLES (e.g. for popups, ..) + + for (const auto &window : updated) { + auto w = windows_.find(window.task()); + if (w != windows_.end()) { + DEBUG("Found existing window for task %d", window.task()); + w->second->update_state(window); + continue; + } + DEBUG("Found new window for task %d", window.task()); + auto platform_window = platform_->create_window(window); + platform_window->attach(); + windows_.insert({window.task(), platform_window}); + } + + for (const auto &window : removed) { + auto w = windows_.find(window.task()); + if (w == windows_.end()) { + WARNING("Got remove request for window we don't know about (task id %d)", window.task()); + continue; + } + DEBUG("Removing window for task %d", window.task()); + auto platform_window = w->second; + platform_window->release(); + windows_.erase(w); + } } } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/manager.h b/src/anbox/wm/manager.h index ebaf4e9..69c66b0 100644 --- a/src/anbox/wm/manager.h +++ b/src/anbox/wm/manager.h @@ -19,8 +19,10 @@ #define ANBOX_WM_MANAGER_H_ #include "anbox/wm/window_state.h" +#include "anbox/wm/window.h" #include +#include namespace anbox { namespace wm { @@ -35,6 +37,7 @@ public: private: std::shared_ptr platform_; + std::map> windows_; }; } // namespace wm } // namespace anbox diff --git a/src/anbox/graphics/window_creator.cpp b/src/anbox/wm/stack.cpp similarity index 74% rename from src/anbox/graphics/window_creator.cpp rename to src/anbox/wm/stack.cpp index f93d73d..99af33f 100644 --- a/src/anbox/graphics/window_creator.cpp +++ b/src/anbox/wm/stack.cpp @@ -15,16 +15,13 @@ * */ -#include "anbox/graphics/window_creator.h" - +#include "anbox/wm/stack.h" namespace anbox { -namespace graphics { -WindowCreator::WindowCreator(const std::shared_ptr &input_manager) : - input_manager_(input_manager) { -} - -WindowCreator::~WindowCreator() { -} -} // namespace graphics +namespace wm { +Stack::Id Stack::Invalid = -1; +Stack::Id Stack::Default = 0; +Stack::Id Stack::Fullscreen = 1; +Stack::Id Stack::Freeform = 2; +} // namespace wm } // namespace anbox diff --git a/src/anbox/graphics/window_creator.h b/src/anbox/wm/stack.h similarity index 55% rename from src/anbox/graphics/window_creator.h rename to src/anbox/wm/stack.h index 9e1b79f..ea15985 100644 --- a/src/anbox/graphics/window_creator.h +++ b/src/anbox/wm/stack.h @@ -15,28 +15,26 @@ * */ -#ifndef ANBOX_GRAPHICS_WINDOW_CREATOR_H_ -#define ANBOX_GRAPHICS_WINDOW_CREATOR_H_ +#ifndef ANBOX_WM_STACK_H_ +#define ANBOX_WM_STACK_H_ -#include "anbox/graphics/emugl/NativeSubWindow.h" -#include "anbox/graphics/emugl/DisplayManager.h" +#include namespace anbox { -namespace input { -class Manager; -} // namespace input -namespace graphics { -class WindowCreator : public SubWindowHandler, - public DisplayManager { +namespace wm { +class Stack { public: - WindowCreator(const std::shared_ptr &input_manager); - virtual ~WindowCreator(); + typedef std::int32_t Id; - virtual EGLNativeDisplayType native_display() const = 0; + static Id Invalid; + static Id Default; + static Id Fullscreen; + static Id Freeform; -protected: - std::shared_ptr input_manager_; + Stack() = delete; + Stack(const Stack&) = delete; }; -} // namespace graphics +} // namespace wm } // namespace anbox + #endif diff --git a/src/anbox/wm/window.cpp b/src/anbox/wm/window.cpp index f8b8307..7b611e3 100644 --- a/src/anbox/wm/window.cpp +++ b/src/anbox/wm/window.cpp @@ -16,6 +16,7 @@ */ #include "anbox/wm/window.h" +#include "anbox/graphics/emugl/Renderer.h" namespace anbox { namespace wm { @@ -30,8 +31,16 @@ void Window::update_state(const WindowState &state) { state_ = state; } -void Window::render_layer(const Layer &layer) { - (void) layer; +EGLNativeWindowType Window::native_handle() const { + return 0; +} + +bool Window::attach() { + return Renderer::get()->createNativeWindow(native_handle()); +} + +void Window::release() { + Renderer::get()->destroyNativeWindow(native_handle()); } } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/window.h b/src/anbox/wm/window.h index 687aefd..cda1b0e 100644 --- a/src/anbox/wm/window.h +++ b/src/anbox/wm/window.h @@ -23,6 +23,8 @@ #include #include +#include + namespace anbox { namespace wm { // FIXME(morphis): move this somewhere else once we have the integration @@ -35,19 +37,20 @@ private: graphics::Rect frame_; }; -class Window { +class Window +{ public: typedef std::vector List; Window(const WindowState &state); virtual ~Window(); + bool attach(); + void release(); + void update_state(const WindowState &state); - // Render a layer into the window. The layer itself includes all - // necessary information for correct rendering. - void render_layer(const Layer &layer); - + virtual EGLNativeWindowType native_handle() const; WindowState state() const; private: diff --git a/src/anbox/wm/window_state.cpp b/src/anbox/wm/window_state.cpp index 1b357f8..7067da6 100644 --- a/src/anbox/wm/window_state.cpp +++ b/src/anbox/wm/window_state.cpp @@ -24,19 +24,22 @@ WindowState::WindowState() : has_surface_(false), frame_(graphics::Rect::Invalid), package_name_(""), - task_(Task::Invalid) { + task_(Task::Invalid), + stack_(Stack::Invalid) { } WindowState::WindowState(const Display::Id &display, bool has_surface, const graphics::Rect &frame, const std::string &package_name, - const Task::Id &task) : + const Task::Id &task, + const Stack::Id &stack) : display_(display), has_surface_(has_surface), frame_(frame), package_name_(package_name), - task_(task) { + task_(task), + stack_(stack) { } WindowState::~WindowState() { diff --git a/src/anbox/wm/window_state.h b/src/anbox/wm/window_state.h index f0c2ed0..603ed3a 100644 --- a/src/anbox/wm/window_state.h +++ b/src/anbox/wm/window_state.h @@ -21,6 +21,7 @@ #include "anbox/graphics/rect.h" #include "anbox/wm/display.h" #include "anbox/wm/task.h" +#include "anbox/wm/stack.h" #include #include @@ -36,7 +37,8 @@ public: bool has_surface, const graphics::Rect &frame, const std::string &package_name, - const Task::Id &task); + const Task::Id &task, + const Stack::Id &stack); ~WindowState(); Display::Id display() const { return display_; } @@ -44,6 +46,7 @@ public: graphics::Rect frame() const { return frame_; } std::string package_name() const { return package_name_; } Task::Id task() const { return task_; } + Stack::Id stack() const { return stack_; } private: Display::Id display_; @@ -51,6 +54,7 @@ private: graphics::Rect frame_; std::string package_name_; Task::Id task_; + Stack::Id stack_; }; } // namespace wm From 801894232302ee1d0052dfaf2b51c0c53df6e53f Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 23 Nov 2016 12:16:20 +0100 Subject: [PATCH 44/54] Implement renderer instance which composes multiple layers into a window --- src/CMakeLists.txt | 3 + src/anbox/cmds/run.cpp | 2 +- src/anbox/graphics/emugl/ColorBuffer.cpp | 10 +- src/anbox/graphics/emugl/ColorBuffer.h | 10 +- src/anbox/graphics/emugl/RenderControl.cpp | 38 +++- src/anbox/graphics/emugl/RenderControl.h | 9 + src/anbox/graphics/emugl/Renderable.cpp | 27 ++- src/anbox/graphics/emugl/Renderable.h | 16 +- src/anbox/graphics/emugl/Renderer.cpp | 249 +++++++++++++++------ src/anbox/graphics/emugl/Renderer.h | 44 +++- src/anbox/graphics/gl_renderer_server.cpp | 9 +- src/anbox/graphics/gl_renderer_server.h | 9 +- src/anbox/graphics/layer_composer.cpp | 63 ++++++ src/anbox/graphics/layer_composer.h | 43 ++++ src/anbox/graphics/primitives.h | 52 +++++ src/anbox/graphics/program_family.cpp | 107 +++++++++ src/anbox/graphics/program_family.h | 68 ++++++ src/anbox/wm/manager.cpp | 42 +++- src/anbox/wm/manager.h | 4 + src/anbox/wm/window.cpp | 29 ++- src/anbox/wm/window.h | 7 +- 21 files changed, 723 insertions(+), 118 deletions(-) create mode 100644 src/anbox/graphics/layer_composer.cpp create mode 100644 src/anbox/graphics/layer_composer.h create mode 100644 src/anbox/graphics/primitives.h create mode 100644 src/anbox/graphics/program_family.cpp create mode 100644 src/anbox/graphics/program_family.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d4130f..84d5209 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,6 +105,9 @@ set(SOURCES anbox/graphics/gl_renderer_server.cpp anbox/graphics/density.h anbox/graphics/rect.cpp + anbox/graphics/layer_composer.cpp + anbox/graphics/program_family.cpp + anbox/graphics/primitives.h anbox/graphics/emugl/ColorBuffer.cpp anbox/graphics/emugl/DisplayManager.cpp diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 26c7c9d..950fea8 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -95,7 +95,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto window_manager = std::make_shared(policy); - auto renderer = std::make_shared(); + auto renderer = std::make_shared(window_manager); renderer->start(); // Socket which will be used by the qemud service inside the Android diff --git a/src/anbox/graphics/emugl/ColorBuffer.cpp b/src/anbox/graphics/emugl/ColorBuffer.cpp index 270ccac..2537503 100644 --- a/src/anbox/graphics/emugl/ColorBuffer.cpp +++ b/src/anbox/graphics/emugl/ColorBuffer.cpp @@ -376,11 +376,6 @@ bool ColorBuffer::bindToRenderbuffer() { return true; } -bool ColorBuffer::post(float rotation, float dx, float dy) { - // NOTE: Do not call m_helper->setupContext() here! - return m_helper->getTextureDraw()->draw(m_resizer->update(m_tex)); -} - void ColorBuffer::readback(unsigned char* img) { ScopedHelperContext context(m_helper); if (!context.isOk()) { @@ -392,3 +387,8 @@ void ColorBuffer::readback(unsigned char* img) { unbindFbo(); } } + +void ColorBuffer::bind() { + const auto id = m_resizer->update(m_tex); + s_gles2.glBindTexture(GL_TEXTURE_2D, id); +} diff --git a/src/anbox/graphics/emugl/ColorBuffer.h b/src/anbox/graphics/emugl/ColorBuffer.h index 152b16b..6eb48a3 100644 --- a/src/anbox/graphics/emugl/ColorBuffer.h +++ b/src/anbox/graphics/emugl/ColorBuffer.h @@ -108,15 +108,6 @@ public: GLenum p_type, void *pixels); - // Draw a ColorBuffer instance, i.e. blit it to the current guest - // framebuffer object / window surface. This doesn't display anything. - bool draw(); - - // Post this ColorBuffer to the host native sub-window. - // |rotation| is the rotation angle in degrees, clockwise in the GL - // coordinate space. - bool post(float rotation, float dx, float dy); - // Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's // EGLImage. This is intended to implement glEGLImageTargetTexture2DOES() // for all GLES versions. @@ -136,6 +127,7 @@ public: // |img| must be a buffer large enough (i.e. width * height * 4). void readback(unsigned char* img); + void bind(); private: ColorBuffer(); // no default constructor. diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 9c971cc..ef32831 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -24,10 +24,19 @@ #include "OpenGLESDispatch/EGLDispatch.h" +#include "anbox/graphics/layer_composer.h" +#include "anbox/logger.h" + #include #include static const GLint rendererVersion = 1; +static std::shared_ptr composer; + +void registerLayerComposer(const std::shared_ptr &c) +{ + composer = c; +} static GLint rcGetRendererVersion() { @@ -305,12 +314,7 @@ static EGLint rcMakeCurrent(uint32_t context, static void rcFBPost(uint32_t colorBuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { - return; - } - - fb->post(nullptr, colorBuffer); + WARNING("Not implemented"); } static void rcFBSetSwapInterval(EGLint interval) @@ -425,15 +429,31 @@ int rcGetDisplayVsyncPeriod(uint32_t display_id) { return 1; } +static std::vector frame_layers; + +bool is_layer_blacklisted(const std::string &name) { + static std::vector blacklist = { + "Sprite", + }; + return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end(); +} + void rcPostLayer(const char *name, uint32_t color_buffer, int32_t sourceCropLeft, int32_t sourceCropTop, int32_t sourceCropRight, int32_t sourceCropBottom, int32_t displayFrameLeft, int32_t displayFrameTop, - int32_t displayFrameRight, int32_t displayFrameBottom) { - + int32_t displayFrameRight, int32_t displayFrameBottom) +{ + Renderable r{name, color_buffer, {displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom}}; + frame_layers.push_back(r); } -void rcPostAllLayersDone() { +void rcPostAllLayersDone() +{ + if (composer) + composer->submit_layers(frame_layers); + + frame_layers.clear(); } void initRenderControlContext(renderControl_decoder_context_t *dec) diff --git a/src/anbox/graphics/emugl/RenderControl.h b/src/anbox/graphics/emugl/RenderControl.h index 87fe1e0..2867acc 100644 --- a/src/anbox/graphics/emugl/RenderControl.h +++ b/src/anbox/graphics/emugl/RenderControl.h @@ -18,6 +18,15 @@ #include "renderControl_dec.h" +#include + +namespace anbox { +namespace graphics { +class LayerComposer; +} // namespace graphics +} // namespace anbox + void initRenderControlContext(renderControl_decoder_context_t *dec); +void registerLayerComposer(const std::shared_ptr &c); #endif diff --git a/src/anbox/graphics/emugl/Renderable.cpp b/src/anbox/graphics/emugl/Renderable.cpp index b68b984..f11f7be 100644 --- a/src/anbox/graphics/emugl/Renderable.cpp +++ b/src/anbox/graphics/emugl/Renderable.cpp @@ -16,10 +16,16 @@ #include "Renderable.h" -Renderable::Renderable(const std::uint32_t &buffer, - const anbox::graphics::Rect &screen_position) : +Renderable::Renderable(const std::string &name, + const std::uint32_t &buffer, + const anbox::graphics::Rect &screen_position, + const glm::mat4 &transformation, + const float &alpha) : + name_(name), buffer_(buffer), - screen_position_(screen_position) + screen_position_(screen_position), + transformation_(transformation), + alpha_(alpha) { } @@ -27,6 +33,11 @@ Renderable::~Renderable() { } +std::string Renderable::name() const +{ + return name_; +} + std::uint32_t Renderable::buffer() const { return buffer_; @@ -36,3 +47,13 @@ anbox::graphics::Rect Renderable::screen_position() const { return screen_position_; } + +glm::mat4 Renderable::transformation() const +{ + return transformation_; +} + +float Renderable::alpha() const +{ + return alpha_; +} diff --git a/src/anbox/graphics/emugl/Renderable.h b/src/anbox/graphics/emugl/Renderable.h index 164f59f..fd6874d 100644 --- a/src/anbox/graphics/emugl/Renderable.h +++ b/src/anbox/graphics/emugl/Renderable.h @@ -19,23 +19,35 @@ #include "anbox/graphics/rect.h" +#include #include #include +#include + class Renderable { public: - Renderable(const std::uint32_t &buffer, - const anbox::graphics::Rect &screen_position); + Renderable(const std::string &name, + const std::uint32_t &buffer, + const anbox::graphics::Rect &screen_position, + const glm::mat4 &transformation = {}, + const float &alpha = 1.0f); ~Renderable(); + std::string name() const; std::uint32_t buffer() const; anbox::graphics::Rect screen_position() const; + glm::mat4 transformation() const; + float alpha() const; private: + std::string name_; std::uint32_t buffer_; anbox::graphics::Rect screen_position_; + glm::mat4 transformation_; + float alpha_; }; typedef std::vector RenderableList; diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index f6c67a0..7c8eac2 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -25,8 +25,14 @@ #include "emugl/common/logging.h" +#include "anbox/logger.h" + #include +#include +#include +#include + namespace { // Helper class to call the bind_locked() / unbind_locked() properly. @@ -415,6 +421,9 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) return false; } + fb->m_defaultProgram = fb->m_family.add_program(vshader, defaultFShader); + fb->m_alphaProgram = fb->m_family.add_program(vshader, alphaFShader); + // release the FB context bind.release(); @@ -426,6 +435,19 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) return true; } +Renderer::Program::Program(GLuint program_id) +{ + id = program_id; + position_attr = s_gles2.glGetAttribLocation(id, "position"); + texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord"); + tex_uniform = s_gles2.glGetUniformLocation(id, "tex"); + centre_uniform = s_gles2.glGetUniformLocation(id, "centre"); + display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform"); + transform_uniform = s_gles2.glGetUniformLocation(id, "transform"); + screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords"); + alpha_uniform = s_gles2.glGetUniformLocation(id, "alpha"); +} + Renderer::Renderer() : m_configs(NULL), m_eglDisplay(EGL_NO_DISPLAY), @@ -455,6 +477,9 @@ Renderer::~Renderer() { struct RendererWindow { EGLNativeWindowType native_window = 0; EGLSurface surface = EGL_NO_SURFACE; + anbox::graphics::Rect viewport; + glm::mat4 screen_to_gl_coords; + glm::mat4 display_transform; }; RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window) @@ -480,7 +505,6 @@ RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window) return nullptr; } - // s_gles2.glViewport(0, 0, width, height); s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -954,68 +978,172 @@ bool Renderer::unbind_locked() return true; } -bool Renderer::post(RendererWindow *window, HandleType p_colorbuffer, bool needLock) +const GLchar* const Renderer::vshader = { - if (!window) - return false; + "attribute vec3 position;\n" + "attribute vec2 texcoord;\n" + "uniform mat4 screen_to_gl_coords;\n" + "uniform mat4 display_transform;\n" + "uniform mat4 transform;\n" + "uniform vec2 centre;\n" + "varying vec2 v_texcoord;\n" + "void main() {\n" + " vec4 mid = vec4(centre, 0.0, 0.0);\n" + " vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n" + " gl_Position = display_transform * screen_to_gl_coords * transformed;\n" + " v_texcoord = texcoord;\n" + "}\n" +}; - if (needLock) - m_lock.lock(); +const GLchar* const Renderer::alphaFShader = +{ + "precision mediump float;\n" + "uniform sampler2D tex;\n" + "uniform float alpha;\n" + "varying vec2 v_texcoord;\n" + "void main() {\n" + " vec4 frag = texture2D(tex, v_texcoord);\n" + " gl_FragColor = alpha*frag;\n" + "}\n" +}; - bool ret; +const GLchar* const Renderer::defaultFShader = +{ // This is the fastest fragment shader. Use it when you can. + "precision mediump float;\n" + "uniform sampler2D tex;\n" + "varying vec2 v_texcoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(tex, v_texcoord);\n" + "}\n" +}; - ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); - if (c == m_colorbuffers.end()) - goto EXIT; +void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect &rect) +{ + /* + * Here we provide a 3D perspective projection with a default 30 degrees + * vertical field of view. This projection matrix is carefully designed + * such that any vertices at depth z=0 will fit the screen coordinates. So + * client texels will fit screen pixels perfectly as long as the surface is + * at depth zero. But if you want to do anything fancy, you can also choose + * a different depth and it will appear to come out of or go into the + * screen. + */ + window->screen_to_gl_coords = glm::translate(glm::mat4(1.0f), glm::vec3{-1.0f, 1.0f, 0.0f}); - m_lastPostedColorBuffer = p_colorbuffer; + /* + * Perspective division is one thing that can't be done in a matrix + * multiplication. It happens after the matrix multiplications. GL just + * scales {x,y} by 1/w. So modify the final part of the projection matrix + * to set w ([3]) to be the incoming z coordinate ([2]). + */ + window->screen_to_gl_coords[2][3] = -1.0f; - if (!bindWindow_locked(window)) - goto EXIT; + float const vertical_fov_degrees = 30.0f; + float const near = + (rect.height() / 2.0f) / + std::tan((vertical_fov_degrees * M_PI / 180.0f) / 2.0f); + float const far = -near; -#if 0 - if (window->needViewportUpdate) { - s_gles2.glViewport(0, 0, window->width, window->height); - window->needViewportUpdate = false; - } -#endif + window->screen_to_gl_coords = glm::scale(window->screen_to_gl_coords, + glm::vec3{2.0f / rect.width(), + -2.0f / rect.height(), + 2.0f / (near - far)}); + window->screen_to_gl_coords = glm::translate(window->screen_to_gl_coords, + glm::vec3{-rect.left(), + -rect.top(), + 0.0f}); - s_gles2.glClearColor(0.0, 0.0, 1.0, 0.0); - s_gles2.glClear(GL_COLOR_BUFFER_BIT); - - ret = (*c).second.cb->post(0.0f, 0, 0); - if (ret) { - s_egl.eglSwapBuffers(m_eglDisplay, window->surface); - } - - // restore previous binding - unbind_locked(); - - // - // output FPS statistics - // - if (m_fpsStats) { - long long currTime = GetCurrentTimeMS(); - m_statsNumFrames++; - if (currTime - m_statsStartTime >= 1000) { - float dt = (float)(currTime - m_statsStartTime) / 1000.0f; - printf("FPS: %5.3f\n", (float)m_statsNumFrames / dt); - m_statsStartTime = currTime; - m_statsNumFrames = 0; - } - } - -EXIT: - if (!ret) - printf("post: FAILED\n"); - - if (needLock) { - m_lock.unlock(); - } - return ret; + window->viewport = rect; } -bool Renderer::draw(EGLNativeWindowType native_window, const RenderableList &renderables) +void Renderer::tessellate(std::vector& primitives, + const anbox::graphics::Rect &buf_size, + const Renderable &renderable) +{ + auto rect = renderable.screen_position(); + GLfloat left = rect.left(); + GLfloat right = rect.right(); + GLfloat top = rect.top(); + GLfloat bottom = rect.bottom(); + + anbox::graphics::Primitive rectangle; + rectangle.tex_id = 0; + rectangle.type = GL_TRIANGLE_STRIP; + + GLfloat tex_right = static_cast(rect.width()) / + buf_size.width(); + GLfloat tex_bottom = static_cast(rect.height()) / + buf_size.height(); + + auto& vertices = rectangle.vertices; + vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}}; + vertices[1] = {{left, bottom, 0.0f}, {0.0f, tex_bottom}}; + vertices[2] = {{right, top, 0.0f}, {tex_right, 0.0f}}; + vertices[3] = {{right, bottom, 0.0f}, {tex_right, tex_bottom}}; + + primitives.resize(1); + primitives[0] = rectangle; +} + +void Renderer::draw(RendererWindow *window, const Renderable &renderable, const Program &prog) +{ + const auto &color_buffer = m_colorbuffers.find(renderable.buffer()); + if (color_buffer == m_colorbuffers.end()) + return; + + const auto &cb = color_buffer->second.cb; + + s_gles2.glUseProgram(prog.id); + s_gles2.glUniform1i(prog.tex_uniform, 0); + s_gles2.glUniformMatrix4fv(prog.display_transform_uniform, 1, GL_FALSE, + glm::value_ptr(window->display_transform)); + s_gles2.glUniformMatrix4fv(prog.screen_to_gl_coords_uniform, 1, GL_FALSE, + glm::value_ptr(window->screen_to_gl_coords)); + + s_gles2.glActiveTexture(GL_TEXTURE0); + + auto const& rect = renderable.screen_position(); + GLfloat centrex = rect.left() + + rect.width() / 2.0f; + GLfloat centrey = rect.top() + + rect.height() / 2.0f; + s_gles2.glUniform2f(prog.centre_uniform, centrex, centrey); + + s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE, + glm::value_ptr(renderable.transformation())); + + if (prog.alpha_uniform >= 0) + s_gles2.glUniform1f(prog.alpha_uniform, renderable.alpha()); + + s_gles2.glEnableVertexAttribArray(prog.position_attr); + s_gles2.glEnableVertexAttribArray(prog.texcoord_attr); + + m_primitives.clear(); + tessellate(m_primitives, {cb->getWidth(), cb->getHeight()}, renderable); + + for (auto const& p : m_primitives) + { + cb->bind(); + + s_gles2.glVertexAttribPointer(prog.position_attr, 3, GL_FLOAT, + GL_FALSE, sizeof(anbox::graphics::Vertex), + &p.vertices[0].position); + s_gles2.glVertexAttribPointer(prog.texcoord_attr, 2, GL_FLOAT, + GL_FALSE, sizeof(anbox::graphics::Vertex), + &p.vertices[0].texcoord); + + s_gles2.glEnable(GL_BLEND); + s_gles2.glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, + GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + s_gles2.glDrawArrays(p.type, 0, p.nvertices); + } + + s_gles2.glDisableVertexAttribArray(prog.texcoord_attr); + s_gles2.glDisableVertexAttribArray(prog.position_attr); +} + +bool Renderer::draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables) { auto w = m_nativeWindows.find(native_window); if (w == m_nativeWindows.end()) @@ -1027,18 +1155,13 @@ bool Renderer::draw(EGLNativeWindowType native_window, const RenderableList &ren return false; } - s_gles2.glClearColor(0.0, 0.0, 1.0, 0.0); + setupViewport(w->second, window_frame); + s_gles2.glClearColor(0.0, 0.0, 0.0, 1.0); + s_gles2.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); s_gles2.glClear(GL_COLOR_BUFFER_BIT); - for (const auto &renderable : renderables) - { - const auto &color_buffer = m_colorbuffers.find(renderable.buffer()); - if (color_buffer == m_colorbuffers.end()) - continue; - - color_buffer->second.cb->post(0.0f, - renderable.screen_position().left(), renderable.screen_position().top()); - } + for (const auto &r : renderables) + draw(w->second, r, r.alpha() < 1.0f ? m_alphaProgram : m_defaultProgram); s_egl.eglSwapBuffers(m_eglDisplay, w->second->surface); diff --git a/src/anbox/graphics/emugl/Renderer.h b/src/anbox/graphics/emugl/Renderer.h index 4ef0851..525df05 100644 --- a/src/anbox/graphics/emugl/Renderer.h +++ b/src/anbox/graphics/emugl/Renderer.h @@ -27,6 +27,9 @@ #include "Renderable.h" +#include "anbox/graphics/program_family.h" +#include "anbox/graphics/primitives.h" + #include #include @@ -229,14 +232,7 @@ public: int x, int y, int width, int height, GLenum format, GLenum type, void *pixels); - // Display the content of a given ColorBuffer into the framebuffer's - // sub-window. |p_colorbuffer| is a handle value. - // |needLock| is used to indicate whether the operation requires - // acquiring/releasing the FrameBuffer instance's lock. It should be - // false only when called internally. - bool post(RendererWindow *window, HandleType p_colorbuffer, bool needLock = true); - - bool draw(EGLNativeWindowType native_window, const RenderableList &renderables); + bool draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables); // Return the host EGLDisplay used by this instance. EGLDisplay getDisplay() const { return m_eglDisplay; } @@ -259,6 +255,13 @@ private: bool bindWindow_locked(RendererWindow *window); + void setupViewport(RendererWindow *window, const anbox::graphics::Rect &rect); + struct Program; + void draw(RendererWindow *window, const Renderable &renderable, const Program &prog); + void tessellate(std::vector& primitives, + const anbox::graphics::Rect &buf_size, + const Renderable &renderable); + private: static Renderer *s_renderer; static HandleType s_nextHandle; @@ -292,5 +295,30 @@ private: const char* m_glVersion; std::map m_nativeWindows; + + anbox::graphics::ProgramFamily m_family; + struct Program + { + GLuint id = 0; + GLint tex_uniform = -1; + GLint position_attr = -1; + GLint texcoord_attr = -1; + GLint centre_uniform = -1; + GLint display_transform_uniform = -1; + GLint transform_uniform = -1; + GLint screen_to_gl_coords_uniform = -1; + GLint alpha_uniform = -1; + mutable long long last_used_frameno = 0; + + Program(GLuint program_id); + Program() {} + }; + Program m_defaultProgram, m_alphaProgram; + + std::vector m_primitives; + + static const GLchar* const vshader; + static const GLchar* const defaultFShader; + static const GLchar* const alphaFShader; }; #endif diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 60d02cd..e770c79 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -17,6 +17,9 @@ #include "anbox/logger.h" #include "anbox/graphics/gl_renderer_server.h" +#include "anbox/graphics/layer_composer.h" +#include "anbox/graphics/emugl/RenderControl.h" +#include "anbox/wm/manager.h" #include "OpenglRender/render_api.h" @@ -26,7 +29,9 @@ namespace anbox { namespace graphics { -GLRendererServer::GLRendererServer() +GLRendererServer::GLRendererServer(const std::shared_ptr &wm) : + wm_(wm), + composer_(std::make_shared(wm)) { if (utils::is_env_set("USE_HOST_GLES")) { @@ -43,6 +48,8 @@ GLRendererServer::GLRendererServer() if (!initLibrary()) BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); + + registerLayerComposer(composer_); } GLRendererServer::~GLRendererServer() { diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index f6159cf..7bee80d 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -25,11 +25,14 @@ namespace anbox { namespace input { class Manager; } // namespace input +namespace wm { +class Manager; +} // namespace wm namespace graphics { -class WindowCreator; +class LayerComposer; class GLRendererServer { public: - GLRendererServer(); + GLRendererServer(const std::shared_ptr &wm); ~GLRendererServer(); void start(); @@ -38,6 +41,8 @@ public: private: std::string socket_path_; + std::shared_ptr wm_; + std::shared_ptr composer_; }; } // namespace graphics diff --git a/src/anbox/graphics/layer_composer.cpp b/src/anbox/graphics/layer_composer.cpp new file mode 100644 index 0000000..a0cb6c1 --- /dev/null +++ b/src/anbox/graphics/layer_composer.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/graphics/layer_composer.h" +#include "anbox/graphics/emugl/Renderer.h" +#include "anbox/wm/manager.h" +#include "anbox/logger.h" + +namespace anbox { +namespace graphics { +LayerComposer::LayerComposer(const std::shared_ptr &wm) : + wm_(wm) +{ +} + +LayerComposer::~LayerComposer() +{ +} + +void LayerComposer::submit_layers(const RenderableList &renderables) +{ + std::map,RenderableList> win_layers; + for (const auto &renderable : renderables) + { + // Ignore all surfaces which are not meant for a task + if (!utils::string_starts_with(renderable.name(), "org.anbox.surface.")) + continue; + + wm::Task::Id task_id = 0; + if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) != 1 || !task_id) + continue; + + auto w = wm_->find_window_for_task(task_id); + if (!w) + continue; + + if (win_layers.find(w) == win_layers.end()) { + win_layers.insert({w, {renderable}}); + continue; + } + + win_layers[w].push_back(renderable); + } + + for (const auto &w : win_layers) + Renderer::get()->draw(w.first->native_handle(), w.first->state().frame(), w.second); +} +} // namespace graphics +} // namespace anbox diff --git a/src/anbox/graphics/layer_composer.h b/src/anbox/graphics/layer_composer.h new file mode 100644 index 0000000..9127b2d --- /dev/null +++ b/src/anbox/graphics/layer_composer.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_GRAPHICS_LAYER_COMPOSER_H_ +#define ANBOX_GRAPHICS_LAYER_COMPOSER_H_ + +#include "anbox/graphics/emugl/Renderable.h" + +#include + +namespace anbox { +namespace wm { +class Manager; +} // namespace wm +namespace graphics { +class LayerComposer { +public: + LayerComposer(const std::shared_ptr &wm); + ~LayerComposer(); + + void submit_layers(const RenderableList &renderables); + +private: + std::shared_ptr wm_; +}; +} // namespace graphics +} // namespace anbox + +#endif diff --git a/src/anbox/graphics/primitives.h b/src/anbox/graphics/primitives.h new file mode 100644 index 0000000..5529f95 --- /dev/null +++ b/src/anbox/graphics/primitives.h @@ -0,0 +1,52 @@ +/* + * Copyright © 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Daniel van Vugt + * Kevin DuBois + */ + + +#ifndef ANBOX_GRAPHICS_PRIMITIVES_H_ +#define ANBOX_GRAPHICS_PRIMITIVES_H_ + +#include + +namespace anbox { +namespace graphics { +struct Vertex +{ + GLfloat position[3]; + GLfloat texcoord[2]; +}; + +struct Primitive +{ + enum {max_vertices = 4}; + + Primitive() + : type(GL_TRIANGLE_FAN), nvertices(4) + { + // Default is a quad. Just need to assign vertices[] and tex_id. + } + + GLenum type; // GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES etc + GLuint tex_id; // GL texture ID (or 0 to represent the surface itself) + int nvertices; + Vertex vertices[max_vertices]; +}; +} // namespace graphics +} // namespace anbox + +#endif diff --git a/src/anbox/graphics/program_family.cpp b/src/anbox/graphics/program_family.cpp new file mode 100644 index 0000000..c47e49e --- /dev/null +++ b/src/anbox/graphics/program_family.cpp @@ -0,0 +1,107 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authored by: Daniel van Vugt + */ + +#include "anbox/graphics/program_family.h" + +#include "anbox/graphics/emugl/DispatchTables.h" + +namespace anbox { +namespace graphics { +void ProgramFamily::Shader::init(GLenum type, const GLchar* src) +{ + if (!id) + { + id = s_gles2.glCreateShader(type); + if (id) + { + s_gles2.glShaderSource(id, 1, &src, NULL); + s_gles2.glCompileShader(id); + GLint ok; + s_gles2.glGetShaderiv(id, GL_COMPILE_STATUS, &ok); + if (!ok) + { + GLchar log[1024]; + s_gles2.glGetShaderInfoLog(id, sizeof log - 1, NULL, log); + log[sizeof log - 1] = '\0'; + s_gles2.glDeleteShader(id); + id = 0; + throw std::runtime_error(std::string("Compile failed: ")+ + log + " for:\n" + src); + } + } + } +} + +ProgramFamily::~ProgramFamily() noexcept +{ + // shader and program lifetimes are managed manually, so that we don't + // need any reference counting or to worry about how many copy constructions + // might have been followed by destructor calls during container resizes. + + for (auto& p : program) + { + if (p.second.id) + s_gles2.glDeleteProgram(p.second.id); + } + + for (auto& v : vshader) + { + if (v.second.id) + s_gles2.glDeleteShader(v.second.id); + } + + for (auto& f : fshader) + { + if (f.second.id) + s_gles2.glDeleteShader(f.second.id); + } +} + +GLuint ProgramFamily::add_program(const GLchar* const vshader_src, + const GLchar* const fshader_src) +{ + auto& v = vshader[vshader_src]; + if (!v.id) v.init(GL_VERTEX_SHADER, vshader_src); + + auto& f = fshader[fshader_src]; + if (!f.id) f.init(GL_FRAGMENT_SHADER, fshader_src); + + auto& p = program[{v.id, f.id}]; + if (!p.id) + { + p.id = s_gles2.glCreateProgram(); + s_gles2.glAttachShader(p.id, v.id); + s_gles2.glAttachShader(p.id, f.id); + s_gles2.glLinkProgram(p.id); + GLint ok; + s_gles2.glGetProgramiv(p.id, GL_LINK_STATUS, &ok); + if (!ok) + { + GLchar log[1024]; + s_gles2.glGetProgramInfoLog(p.id, sizeof log - 1, NULL, log); + log[sizeof log - 1] = '\0'; + s_gles2.glDeleteShader(p.id); + p.id = 0; + throw std::runtime_error(std::string("Link failed: ")+log); + } + } + + return p.id; +} +} // namespace graphics +} // namespace anbox diff --git a/src/anbox/graphics/program_family.h b/src/anbox/graphics/program_family.h new file mode 100644 index 0000000..98e7f88 --- /dev/null +++ b/src/anbox/graphics/program_family.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authored by: Daniel van Vugt + */ + +#ifndef ANBOX_GRAPHICS_PROGRAM_FAMILY_H_ +#define ANBOX_GRAPHICS_PROGRAM_FAMILY_H_ + +#include +#include +#include + +#include + +namespace anbox { +namespace graphics { +/** + * ProgramFamily represents a set of GLSL programs that are closely + * related. Programs which point to the same shader source strings will be + * made to share the same compiled shader objects. + * A secondary intention is that this class may be extended to allow the + * different programs within the family to share common patterns of uniform + * usage too. + */ +class ProgramFamily +{ +public: + ProgramFamily() = default; + ProgramFamily(ProgramFamily const&) = delete; + ProgramFamily& operator=(ProgramFamily const&) = delete; + ~ProgramFamily() noexcept; + + GLuint add_program(const GLchar* const static_vshader_src, + const GLchar* const static_fshader_src); + +private: + struct Shader + { + GLuint id = 0; + void init(GLenum type, const GLchar* src); + }; + typedef std::unordered_map ShaderMap; + ShaderMap vshader, fshader; + + typedef std::pair ShaderPair; + struct Program + { + GLuint id = 0; + }; + std::map program; +}; +} // namespace graphics +} // namespace anbox + +#endif // MIR_RENDERER_GL_PROGRAM_FAMILY_H_ diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp index a6b9fa9..62a826a 100644 --- a/src/anbox/wm/manager.cpp +++ b/src/anbox/wm/manager.cpp @@ -19,6 +19,8 @@ #include "anbox/wm/platform_policy.h" #include "anbox/logger.h" +#include + namespace anbox { namespace wm { Manager::Manager(const std::shared_ptr &platform) : @@ -31,6 +33,8 @@ Manager::~Manager() { void Manager::apply_window_state_update(const WindowState::List &updated, const WindowState::List &removed) { + std::lock_guard l(mutex_); + DEBUG("updated %d removed %d", updated.size(), removed.size()); // Base on the update we get from the Android WindowManagerService we will create @@ -38,30 +42,46 @@ void Manager::apply_window_state_update(const WindowState::List &updated, // from SurfaceFlinger will be mapped later into those windows and eventually // composited there via GLES (e.g. for popups, ..) - for (const auto &window : updated) { + for (const auto &window : updated) + { auto w = windows_.find(window.task()); - if (w != windows_.end()) { - DEBUG("Found existing window for task %d", window.task()); + if (w != windows_.end()) + { w->second->update_state(window); continue; } - DEBUG("Found new window for task %d", window.task()); auto platform_window = platform_->create_window(window); + platform_window->ref(); platform_window->attach(); windows_.insert({window.task(), platform_window}); } - for (const auto &window : removed) { + for (const auto &window : removed) + { auto w = windows_.find(window.task()); - if (w == windows_.end()) { - WARNING("Got remove request for window we don't know about (task id %d)", window.task()); + if (w == windows_.end()) continue; + + w->second->unref(); + if (!w->second->still_used()) + { + auto platform_window = w->second; + platform_window->release(); + windows_.erase(w); } - DEBUG("Removing window for task %d", window.task()); - auto platform_window = w->second; - platform_window->release(); - windows_.erase(w); } } + +std::shared_ptr Manager::find_window_for_task(const Task::Id &task) +{ + std::lock_guard l(mutex_); + + for (const auto &w : windows_) + { + if (w.second->state().task() == task) + return w.second; + } + return nullptr; +} } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/manager.h b/src/anbox/wm/manager.h index 69c66b0..aa4eede 100644 --- a/src/anbox/wm/manager.h +++ b/src/anbox/wm/manager.h @@ -23,6 +23,7 @@ #include #include +#include namespace anbox { namespace wm { @@ -35,7 +36,10 @@ public: void apply_window_state_update(const WindowState::List &updated, const WindowState::List &removed); + std::shared_ptr find_window_for_task(const Task::Id &task); + private: + std::mutex mutex_; std::shared_ptr platform_; std::map> windows_; }; diff --git a/src/anbox/wm/window.cpp b/src/anbox/wm/window.cpp index 7b611e3..9bc5edc 100644 --- a/src/anbox/wm/window.cpp +++ b/src/anbox/wm/window.cpp @@ -17,18 +17,24 @@ #include "anbox/wm/window.h" #include "anbox/graphics/emugl/Renderer.h" +#include "anbox/logger.h" namespace anbox { namespace wm { Window::Window(const WindowState &state) : - state_(state) { + state_(state), + refcount_(0) { } Window::~Window() { } -void Window::update_state(const WindowState &state) { - state_ = state; +void Window::update_state(const WindowState &new_state) { + state_ = new_state; +} + +WindowState Window::state() const { + return state_; } EGLNativeWindowType Window::native_handle() const { @@ -42,6 +48,23 @@ bool Window::attach() { void Window::release() { Renderer::get()->destroyNativeWindow(native_handle()); } + +void Window::ref() { + refcount_++; +} + +void Window::unref() { + if (refcount_ == 0) { + WARNING("reference count is out of sync"); + return; + } + + refcount_--; +} + +bool Window::still_used() const { + return refcount_ > 0; +} } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/window.h b/src/anbox/wm/window.h index cda1b0e..32c323f 100644 --- a/src/anbox/wm/window.h +++ b/src/anbox/wm/window.h @@ -42,12 +42,16 @@ class Window public: typedef std::vector List; - Window(const WindowState &state); + Window(const WindowState &new_state); virtual ~Window(); bool attach(); void release(); + void ref(); + void unref(); + bool still_used() const; + void update_state(const WindowState &state); virtual EGLNativeWindowType native_handle() const; @@ -55,6 +59,7 @@ public: private: WindowState state_; + std::uint32_t refcount_; }; } // namespace wm } // namespace anbox From 64d56de677c62b1912f7e19ab1bee77cb2e29a9a Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 23 Nov 2016 12:17:05 +0100 Subject: [PATCH 45/54] Ignore certain layers SurfaceFlinger marks as such --- android/hwcomposer/hwcomposer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/hwcomposer/hwcomposer.cpp b/android/hwcomposer/hwcomposer.cpp index 3ab4d23..582e168 100644 --- a/android/hwcomposer/hwcomposer.cpp +++ b/android/hwcomposer/hwcomposer.cpp @@ -180,6 +180,10 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, for (size_t i = 0 ; i < displays[0]->numHwLayers ; i++) { const auto layer = &displays[0]->hwLayers[i]; + if (layer->flags & HWC_SKIP_LAYER || + layer->flags & HWC_IS_CURSOR_LAYER) + continue; + dump_layer(layer); // FIXME this is just dirty ... but layer->handle is a const native_handle_t and canBePosted From 08024962e0285589aa6c1dc38ff913d312fd1d45 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 23 Nov 2016 12:44:53 +0100 Subject: [PATCH 46/54] Set correct viewport for every window we render --- src/anbox/graphics/emugl/Renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index 7c8eac2..8f09af1 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -1156,6 +1156,7 @@ bool Renderer::draw(EGLNativeWindowType native_window, const anbox::graphics::Re } setupViewport(w->second, window_frame); + s_gles2.glViewport(0, 0, window_frame.width(), window_frame.height()); s_gles2.glClearColor(0.0, 0.0, 0.0, 1.0); s_gles2.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); s_gles2.glClear(GL_COLOR_BUFFER_BIT); From 76757fe0858571efad81e3c90c65b173cecc9aaa Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 23 Nov 2016 12:45:14 +0100 Subject: [PATCH 47/54] Add dirty hack to get rid of home window/task for now --- src/anbox/wm/manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp index 62a826a..83e9702 100644 --- a/src/anbox/wm/manager.cpp +++ b/src/anbox/wm/manager.cpp @@ -50,6 +50,11 @@ void Manager::apply_window_state_update(const WindowState::List &updated, w->second->update_state(window); continue; } + // HACK: We ignore the first task here which will be always the home + // stack of Android. This needs to be solved differently so that the + // Android side doesn't create this stack at all. + if (window.task() == 0) + continue; auto platform_window = platform_->create_window(window); platform_window->ref(); platform_window->attach(); From 627479abfee16289a7059f04cead8e69d74931be Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 25 Nov 2016 07:12:35 +0100 Subject: [PATCH 48/54] Drop various debug log output from hwcomposer implementation --- android/hwcomposer/hwcomposer.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/android/hwcomposer/hwcomposer.cpp b/android/hwcomposer/hwcomposer.cpp index 582e168..91b2945 100644 --- a/android/hwcomposer/hwcomposer.cpp +++ b/android/hwcomposer/hwcomposer.cpp @@ -88,8 +88,6 @@ static int hwc_prepare(hwc_composer_device_1_t* dev, size_t numDisplays, hwc_display_contents_1_t** displays) { auto context = reinterpret_cast(dev); - ALOGD("%s", __PRETTY_FUNCTION__); - if (displays == NULL || displays[0] == NULL) return -EINVAL; @@ -107,7 +105,9 @@ static int hwc_prepare(hwc_composer_device_1_t* dev, size_t numDisplays, for (; i < num_hw_layers; i++) { hwc_layer_1_t* layer = &displays[0]->hwLayers[num_hw_layers - 1 - i]; +#if 0 dump_layer(layer); +#endif if (layer->flags & HWC_SKIP_LAYER) { // All layers below and including this one will be drawn into the @@ -170,8 +170,6 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, hwc_display_contents_1_t** displays) { auto context = reinterpret_cast(dev); - ALOGD("%s", __PRETTY_FUNCTION__); - if (displays == NULL || displays[0] == NULL) return -EFAULT; @@ -184,7 +182,9 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, layer->flags & HWC_IS_CURSOR_LAYER) continue; +#if 0 dump_layer(layer); +#endif // FIXME this is just dirty ... but layer->handle is a const native_handle_t and canBePosted // can't be called with a const. @@ -217,30 +217,22 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, static int hwc_event_control(hwc_composer_device_1* dev, int disp, int event, int enabled) { - ALOGD("%s", __PRETTY_FUNCTION__); - return -EFAULT; } static void hwc_register_procs(hwc_composer_device_1* dev, hwc_procs_t const* procs) { - ALOGD("%s", __PRETTY_FUNCTION__); } static int hwc_blank(hwc_composer_device_1* dev, int disp, int blank) { - ALOGD("%s", __PRETTY_FUNCTION__); - return 0; } static int hwc_query(hwc_composer_device_1* dev, int what, int* value) { - ALOGD("%s", __PRETTY_FUNCTION__); - return 0; } static int hwc_device_close(hw_device_t* dev) { - ALOGD("%s", __PRETTY_FUNCTION__); auto context = reinterpret_cast(dev); delete context; return 0; @@ -248,8 +240,6 @@ static int hwc_device_close(hw_device_t* dev) { static int hwc_get_display_configs(hwc_composer_device_1* dev, int disp, uint32_t* configs, size_t* numConfigs) { - ALOGD("%s", __PRETTY_FUNCTION__); - if (disp != 0) { return -EINVAL; } @@ -267,8 +257,6 @@ static int hwc_get_display_attributes(hwc_composer_device_1* dev, int disp, uint32_t config, const uint32_t* attributes, int32_t* values) { - ALOGD("%s", __PRETTY_FUNCTION__); - if (disp != 0 || config != 0) { return -EINVAL; } From 06aacfe4df2520557bf8bb7bc47f70c55458d91c Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 25 Nov 2016 07:13:05 +0100 Subject: [PATCH 49/54] Pass stack id as part of the window state update --- src/anbox/bridge/platform_api_skeleton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/anbox/bridge/platform_api_skeleton.cpp b/src/anbox/bridge/platform_api_skeleton.cpp index 9f0e724..fafa473 100644 --- a/src/anbox/bridge/platform_api_skeleton.cpp +++ b/src/anbox/bridge/platform_api_skeleton.cpp @@ -61,7 +61,7 @@ void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowSta graphics::Rect(window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom()), window.package_name(), wm::Task::Id(window.task_id()), - wm::Stack::Id(wm::Stack::Invalid)); + wm::Stack::Id(window.stack_id())); }; wm::WindowState::List updated; From 53c2fac5d4f25e311cc0455666797a87397898d9 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 25 Nov 2016 07:14:20 +0100 Subject: [PATCH 50/54] Improve window/layer handling for less flickering and better window movement --- src/anbox/graphics/emugl/Renderable.cpp | 5 +++ src/anbox/graphics/emugl/Renderable.h | 2 + src/anbox/graphics/emugl/Renderer.cpp | 12 +++--- src/anbox/graphics/emugl/Renderer.h | 2 +- src/anbox/graphics/layer_composer.cpp | 40 ++++++++++++++++++- src/anbox/graphics/rect.cpp | 10 +++++ src/anbox/graphics/rect.h | 2 + src/anbox/ubuntu/platform_policy.cpp | 8 ++-- src/anbox/ubuntu/platform_policy.h | 2 +- src/anbox/ubuntu/window.h | 9 +++-- src/anbox/wm/default_platform_policy.cpp | 17 ++++++-- src/anbox/wm/default_platform_policy.h | 2 +- src/anbox/wm/manager.cpp | 50 +++++++++++++++++------- src/anbox/wm/platform_policy.h | 2 +- src/anbox/wm/window.cpp | 49 +++++++++++------------ src/anbox/wm/window.h | 20 +++++----- 16 files changed, 163 insertions(+), 69 deletions(-) diff --git a/src/anbox/graphics/emugl/Renderable.cpp b/src/anbox/graphics/emugl/Renderable.cpp index f11f7be..232f3a1 100644 --- a/src/anbox/graphics/emugl/Renderable.cpp +++ b/src/anbox/graphics/emugl/Renderable.cpp @@ -57,3 +57,8 @@ float Renderable::alpha() const { return alpha_; } + +void Renderable::set_screen_position(const anbox::graphics::Rect &screen_position) +{ + screen_position_ = screen_position; +} diff --git a/src/anbox/graphics/emugl/Renderable.h b/src/anbox/graphics/emugl/Renderable.h index fd6874d..819f1b7 100644 --- a/src/anbox/graphics/emugl/Renderable.h +++ b/src/anbox/graphics/emugl/Renderable.h @@ -42,6 +42,8 @@ public: glm::mat4 transformation() const; float alpha() const; + void set_screen_position(const anbox::graphics::Rect &screen_position); + private: std::string name_; std::uint32_t buffer_; diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index 8f09af1..3e26991 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -441,7 +441,7 @@ Renderer::Program::Program(GLuint program_id) position_attr = s_gles2.glGetAttribLocation(id, "position"); texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord"); tex_uniform = s_gles2.glGetUniformLocation(id, "tex"); - centre_uniform = s_gles2.glGetUniformLocation(id, "centre"); + center_uniform = s_gles2.glGetUniformLocation(id, "centre"); display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform"); transform_uniform = s_gles2.glGetUniformLocation(id, "transform"); screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords"); @@ -985,10 +985,10 @@ const GLchar* const Renderer::vshader = "uniform mat4 screen_to_gl_coords;\n" "uniform mat4 display_transform;\n" "uniform mat4 transform;\n" - "uniform vec2 centre;\n" + "uniform vec2 center;\n" "varying vec2 v_texcoord;\n" "void main() {\n" - " vec4 mid = vec4(centre, 0.0, 0.0);\n" + " vec4 mid = vec4(center, 0.0, 0.0);\n" " vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n" " gl_Position = display_transform * screen_to_gl_coords * transformed;\n" " v_texcoord = texcoord;\n" @@ -1103,11 +1103,11 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const s_gles2.glActiveTexture(GL_TEXTURE0); auto const& rect = renderable.screen_position(); - GLfloat centrex = rect.left() + + GLfloat centerx = rect.left() + rect.width() / 2.0f; - GLfloat centrey = rect.top() + + GLfloat centery = rect.top() + rect.height() / 2.0f; - s_gles2.glUniform2f(prog.centre_uniform, centrex, centrey); + s_gles2.glUniform2f(prog.center_uniform, centerx, centery); s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE, glm::value_ptr(renderable.transformation())); diff --git a/src/anbox/graphics/emugl/Renderer.h b/src/anbox/graphics/emugl/Renderer.h index 525df05..b0bc2c2 100644 --- a/src/anbox/graphics/emugl/Renderer.h +++ b/src/anbox/graphics/emugl/Renderer.h @@ -303,7 +303,7 @@ private: GLint tex_uniform = -1; GLint position_attr = -1; GLint texcoord_attr = -1; - GLint centre_uniform = -1; + GLint center_uniform = -1; GLint display_transform_uniform = -1; GLint transform_uniform = -1; GLint screen_to_gl_coords_uniform = -1; diff --git a/src/anbox/graphics/layer_composer.cpp b/src/anbox/graphics/layer_composer.cpp index a0cb6c1..9d31c3f 100644 --- a/src/anbox/graphics/layer_composer.cpp +++ b/src/anbox/graphics/layer_composer.cpp @@ -57,7 +57,45 @@ void LayerComposer::submit_layers(const RenderableList &renderables) } for (const auto &w : win_layers) - Renderer::get()->draw(w.first->native_handle(), w.first->state().frame(), w.second); + { + const auto &window = w.first; + const auto &renderables = w.second; + RenderableList final_renderables; + auto new_window_frame = Rect::Invalid; + + // As we get absolute display coordinates from the Android hwcomposer we + // need to recalculate all layer coordinates into relatives ones to the + // window they are drawn into. + for (auto &r : renderables) + { + if (new_window_frame == Rect::Invalid) + new_window_frame = r.screen_position(); + else + new_window_frame.merge(r.screen_position()); + } + + for (auto &r : renderables) + { + auto left = r.screen_position().left() - new_window_frame.left(); + auto top = r.screen_position().top() - new_window_frame.top(); + + auto rect = Rect{ + left, top, + r.screen_position().width() + left, + r.screen_position().height() + top, + }; + + auto new_renderable = r; + new_renderable.set_screen_position(rect); + final_renderables.push_back(new_renderable); + } + + w.first->update_frame(new_window_frame); + + Renderer::get()->draw(window->native_handle(), + Rect{0, 0, window->frame().width(), window->frame().height()}, + final_renderables); + } } } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/rect.cpp b/src/anbox/graphics/rect.cpp index 62d3e75..e8cbb13 100644 --- a/src/anbox/graphics/rect.cpp +++ b/src/anbox/graphics/rect.cpp @@ -17,9 +17,19 @@ #include "anbox/graphics/rect.h" +#include + namespace anbox { namespace graphics { const Rect Rect::Invalid{-1,-1,-1,-1}; const Rect Rect::Empty{0,0,0,0}; + +void Rect::merge(const Rect &rhs) +{ + left_ = std::min(left_, rhs.left()); + top_ = std::min(top_, rhs.top()); + right_ = std::max(right_, rhs.right()); + bottom_ = std::max(bottom_, rhs.bottom()); +} } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/rect.h b/src/anbox/graphics/rect.h index a9c994e..15949c2 100644 --- a/src/anbox/graphics/rect.h +++ b/src/anbox/graphics/rect.h @@ -89,6 +89,8 @@ public: return !operator == (rhs); } + void merge(const Rect &rhs); + private: std::int32_t left_; std::int32_t top_; diff --git a/src/anbox/ubuntu/platform_policy.cpp b/src/anbox/ubuntu/platform_policy.cpp index b415a03..0045b61 100644 --- a/src/anbox/ubuntu/platform_policy.cpp +++ b/src/anbox/ubuntu/platform_policy.cpp @@ -29,8 +29,10 @@ namespace anbox { namespace ubuntu { -PlatformPolicy::PlatformPolicy(const std::shared_ptr &input_manager) : +PlatformPolicy::PlatformPolicy(const std::shared_ptr &input_manager, + const std::shared_ptr &android_api) : input_manager_(input_manager), + android_api_(android_api), event_thread_running_(false) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) @@ -181,9 +183,9 @@ Window::Id PlatformPolicy::next_window_id() { return next_id++; } -std::shared_ptr PlatformPolicy::create_window(const wm::WindowState &state) { +std::shared_ptr PlatformPolicy::create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) { auto id = next_window_id(); - auto w = std::make_shared(id, shared_from_this(), state); + auto w = std::make_shared(id, task, shared_from_this(), frame); windows_.insert({id, w}); return w; } diff --git a/src/anbox/ubuntu/platform_policy.h b/src/anbox/ubuntu/platform_policy.h index dd1083c..242c5c8 100644 --- a/src/anbox/ubuntu/platform_policy.h +++ b/src/anbox/ubuntu/platform_policy.h @@ -42,7 +42,7 @@ public: PlatformPolicy(const std::shared_ptr &input_manager); ~PlatformPolicy(); - std::shared_ptr create_window(const wm::WindowState &state) override; + std::shared_ptr create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override; void window_deleted(const Window::Id &id) override; diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index ceb3bcb..a92ea85 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -41,19 +41,20 @@ public: virtual void window_deleted(const Id &id) = 0; }; - Window(const Id &id, const std::shared_ptr &observer, const wm::WindowState &state); + Window(const Id &id, const wm::Task::Id &task, const std::shared_ptr &observer, const graphics::Rect &frame); Window(int x, int y, int width, int height); ~Window(); - void resize(int width, int height); - int update_position(int x, int y); - void process_event(const SDL_Event &event); EGLNativeWindowType native_handle() const override; Id id() const; std::uint32_t window_id() const; +protected: + void resize(int width, int height) override; + void update_position(int x, int y) override; + private: Id id_; std::shared_ptr observer_; diff --git a/src/anbox/wm/default_platform_policy.cpp b/src/anbox/wm/default_platform_policy.cpp index f37e1c2..0dce9e8 100644 --- a/src/anbox/wm/default_platform_policy.cpp +++ b/src/anbox/wm/default_platform_policy.cpp @@ -22,8 +22,17 @@ namespace { class NullWindow : public anbox::wm::Window { public: - NullWindow(const anbox::wm::WindowState &state) : - anbox::wm::Window(state) { + NullWindow(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) : + anbox::wm::Window(0, frame) { + } + +protected: + void resize(int width, int height) override { + WARNING("Not implemented"); + } + + void update_position(int x, int y) override { + WARNING("Not implemented"); } }; } @@ -33,10 +42,10 @@ namespace wm { DefaultPlatformPolicy::DefaultPlatformPolicy() { } -std::shared_ptr DefaultPlatformPolicy::create_window(const WindowState &state) +std::shared_ptr DefaultPlatformPolicy::create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) { DEBUG(""); - return std::make_shared<::NullWindow>(state); + return std::make_shared<::NullWindow>(task, frame); } } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/default_platform_policy.h b/src/anbox/wm/default_platform_policy.h index e9af49c..9476050 100644 --- a/src/anbox/wm/default_platform_policy.h +++ b/src/anbox/wm/default_platform_policy.h @@ -25,7 +25,7 @@ namespace wm { class DefaultPlatformPolicy : public PlatformPolicy { public: DefaultPlatformPolicy(); - std::shared_ptr create_window(const WindowState &state) override; + std::shared_ptr create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override; }; } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/manager.cpp b/src/anbox/wm/manager.cpp index 83e9702..67c7a24 100644 --- a/src/anbox/wm/manager.cpp +++ b/src/anbox/wm/manager.cpp @@ -35,40 +35,63 @@ void Manager::apply_window_state_update(const WindowState::List &updated, { std::lock_guard l(mutex_); - DEBUG("updated %d removed %d", updated.size(), removed.size()); - // Base on the update we get from the Android WindowManagerService we will create // different window instances with the properties supplied. Incoming layer updates // from SurfaceFlinger will be mapped later into those windows and eventually // composited there via GLES (e.g. for popups, ..) + std::map task_updates; + for (const auto &window : updated) { + // Ignore all windows which are not part of the freeform task stack + if (window.stack() != Stack::Freeform) + continue; + + // And also those which don't have a surface mapped at the moment + if (!window.has_surface()) + continue; + + // If we know that task already we first collect all window updates + // for it so we can apply all of them together. auto w = windows_.find(window.task()); if (w != windows_.end()) { - w->second->update_state(window); + auto t = task_updates.find(window.task()); + if (t == task_updates.end()) + task_updates.insert({window.task(), {window}}); + else + task_updates[window.task()].push_back(window); continue; } - // HACK: We ignore the first task here which will be always the home - // stack of Android. This needs to be solved differently so that the - // Android side doesn't create this stack at all. - if (window.task() == 0) - continue; - auto platform_window = platform_->create_window(window); - platform_window->ref(); + + auto platform_window = platform_->create_window(window.task(), window.frame()); platform_window->attach(); windows_.insert({window.task(), platform_window}); } + // Send updates we collected per task down to the corresponding window + // so that they can update themself. + for (const auto &u : task_updates) + { + auto w = windows_.find(u.first); + if (w == windows_.end()) + continue; + + w->second->update_state(u.second); + } + + // As final step we process all windows we need to remove as they + // got killed on the other side. We need to respect here that we + // also get removals for windows which are part of a task which is + // still in use by other windows. for (const auto &window : removed) { auto w = windows_.find(window.task()); if (w == windows_.end()) continue; - w->second->unref(); - if (!w->second->still_used()) + if (task_updates.find(window.task()) == task_updates.end()) { auto platform_window = w->second; platform_window->release(); @@ -80,10 +103,9 @@ void Manager::apply_window_state_update(const WindowState::List &updated, std::shared_ptr Manager::find_window_for_task(const Task::Id &task) { std::lock_guard l(mutex_); - for (const auto &w : windows_) { - if (w.second->state().task() == task) + if (w.second->task() == task) return w.second; } return nullptr; diff --git a/src/anbox/wm/platform_policy.h b/src/anbox/wm/platform_policy.h index 7270ae0..f9261e3 100644 --- a/src/anbox/wm/platform_policy.h +++ b/src/anbox/wm/platform_policy.h @@ -30,7 +30,7 @@ class PlatformPolicy { public: virtual ~PlatformPolicy(); - virtual std::shared_ptr create_window(const WindowState &state) = 0; + virtual std::shared_ptr create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) = 0; }; } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/window.cpp b/src/anbox/wm/window.cpp index 9bc5edc..03968fb 100644 --- a/src/anbox/wm/window.cpp +++ b/src/anbox/wm/window.cpp @@ -21,20 +21,38 @@ namespace anbox { namespace wm { -Window::Window(const WindowState &state) : - state_(state), - refcount_(0) { +Window::Window(const Task::Id &task, const graphics::Rect &frame) : + task_(task), + frame_(frame) { } Window::~Window() { } -void Window::update_state(const WindowState &new_state) { - state_ = new_state; +void Window::update_state(const WindowState::List &states) +{ } -WindowState Window::state() const { - return state_; +void Window::update_frame(const graphics::Rect &frame) +{ + if (frame == frame_) + return; + + if (frame.width() != frame_.width() || frame.height() != frame_.height()) + resize(frame.width(), frame.height()); + + if (frame.top() != frame_.top() || frame.left() != frame_.left()) + update_position(frame.left(), frame.top()); + + frame_ = frame; +} + +Task::Id Window::task() const { + return task_; +} + +graphics::Rect Window::frame() const { + return frame_; } EGLNativeWindowType Window::native_handle() const { @@ -48,23 +66,6 @@ bool Window::attach() { void Window::release() { Renderer::get()->destroyNativeWindow(native_handle()); } - -void Window::ref() { - refcount_++; -} - -void Window::unref() { - if (refcount_ == 0) { - WARNING("reference count is out of sync"); - return; - } - - refcount_--; -} - -bool Window::still_used() const { - return refcount_ > 0; -} } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/window.h b/src/anbox/wm/window.h index 32c323f..687e90d 100644 --- a/src/anbox/wm/window.h +++ b/src/anbox/wm/window.h @@ -42,24 +42,26 @@ class Window public: typedef std::vector List; - Window(const WindowState &new_state); + Window(const Task::Id &task, const graphics::Rect &frame); virtual ~Window(); bool attach(); void release(); - void ref(); - void unref(); - bool still_used() const; - - void update_state(const WindowState &state); + void update_state(const WindowState::List &states); + void update_frame(const graphics::Rect &frame); virtual EGLNativeWindowType native_handle() const; - WindowState state() const; + graphics::Rect frame() const; + Task::Id task() const; + +protected: + virtual void resize(int width, int height) = 0; + virtual void update_position(int x, int y) = 0; private: - WindowState state_; - std::uint32_t refcount_; + Task::Id task_; + graphics::Rect frame_; }; } // namespace wm } // namespace anbox From a40fe5165415ab509a42ebd4282f5843a691f1b7 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 25 Nov 2016 08:50:43 +0100 Subject: [PATCH 51/54] Use events instead of method invokes for window state updates and others --- android/service/local_socket_connection.cpp | 2 +- android/service/platform_api_stub.cpp | 69 ++++++++----------- android/service/platform_api_stub.h | 33 ++++++--- android/service/platform_service.cpp | 42 ++++++----- android/service/platform_service.h | 12 +--- src/anbox/bridge/platform_api_skeleton.cpp | 39 ++++------- src/anbox/bridge/platform_api_skeleton.h | 17 ++--- .../bridge/platform_message_processor.cpp | 18 +++-- src/anbox/cmds/run.cpp | 3 +- src/anbox/protobuf/anbox_bridge.proto | 19 ++++- src/anbox/protobuf/anbox_rpc.proto | 1 + src/anbox/rpc/channel.cpp | 20 ++++-- src/anbox/rpc/channel.h | 4 +- src/anbox/rpc/message_processor.cpp | 6 +- 14 files changed, 152 insertions(+), 133 deletions(-) diff --git a/android/service/local_socket_connection.cpp b/android/service/local_socket_connection.cpp index 9b8dbea..c2ff040 100644 --- a/android/service/local_socket_connection.cpp +++ b/android/service/local_socket_connection.cpp @@ -23,7 +23,7 @@ #include #include -#define LOG_TAG "Anbox" +#define LOG_TAG "Anboxd" #include namespace { diff --git a/android/service/platform_api_stub.cpp b/android/service/platform_api_stub.cpp index e18e045..fd2d605 100644 --- a/android/service/platform_api_stub.cpp +++ b/android/service/platform_api_stub.cpp @@ -21,59 +21,44 @@ #include "anbox_rpc.pb.h" #include "anbox_bridge.pb.h" -#define LOG_TAG "Anbox" -#include - namespace anbox { PlatformApiStub::PlatformApiStub(const std::shared_ptr &rpc_channel) : rpc_channel_(rpc_channel) { } void PlatformApiStub::boot_finished() { - auto c = std::make_shared>(); + protobuf::bridge::EventSequence seq; + auto event = seq.mutable_boot_finished(); + (void) event; + rpc_channel_->send_event(seq); +} - ALOGI("Boot finished"); +void PlatformApiStub::update_window_state(const WindowStateUpdate &state) { + protobuf::bridge::EventSequence seq; + auto event = seq.mutable_window_state_update(); - { - std::lock_guard lock(mutex_); - boot_finished_wait_handle_.expect_result(); + auto convert_window = [](WindowStateUpdate::Window in, anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState *out) { + out->set_display_id(in.display_id); + out->set_has_surface(in.has_surface); + out->set_package_name(in.package_name); + out->set_frame_left(in.frame.left); + out->set_frame_top(in.frame.top); + out->set_frame_right(in.frame.right); + out->set_frame_bottom(in.frame.bottom); + out->set_task_id(in.task_id); + out->set_stack_id(in.stack_id); + }; + + for (const auto &window : state.updated_windows) { + auto w = event->add_windows(); + convert_window(window, w); } - protobuf::rpc::Void message; - - rpc_channel_->call_method( - "boot_finished", - &message, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiStub::handle_boot_finished_response, c.get())); - - boot_finished_wait_handle_.wait_for_all(); - - ALOGI("Boot finished sent successfully!"); -} - -void PlatformApiStub::handle_boot_finished_response(Request*) { - boot_finished_wait_handle_.result_received(); -} - -void PlatformApiStub::update_window_state(const anbox::protobuf::bridge::WindowStateUpdate &window_state) { - auto c = std::make_shared>(); - - ALOGI("Updating window state"); - - { - std::lock_guard lock(mutex_); - update_window_state_wait_handle_.expect_result(); + for (const auto &window : state.removed_windows) { + auto w = event->add_removed_windows(); + convert_window(window, w); } - rpc_channel_->call_method( - "update_window_state", - &window_state, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiStub::handle_update_window_state_response, c.get())); - - update_window_state_wait_handle_.wait_for_all(); -} - -void PlatformApiStub::handle_update_window_state_response(Request *request) { - update_window_state_wait_handle_.result_received(); + rpc_channel_->send_event(seq); } } // namespace anbox diff --git a/android/service/platform_api_stub.h b/android/service/platform_api_stub.h index e13a99c..436facf 100644 --- a/android/service/platform_api_stub.h +++ b/android/service/platform_api_stub.h @@ -21,16 +21,14 @@ #include "anbox/common/wait_handle.h" #include +#include +#include namespace anbox { namespace protobuf { namespace rpc { class Void; -class WindowStateUpdate; } // namespace rpc -namespace bridge { -class WindowStateUpdate; -} // namespace bridge } // namespace protobuf namespace rpc { class Channel; @@ -40,7 +38,27 @@ public: PlatformApiStub(const std::shared_ptr &rpc_channel); void boot_finished(); - void update_window_state(const anbox::protobuf::bridge::WindowStateUpdate &window_state); + + struct WindowStateUpdate { + struct Window { + int display_id; + bool has_surface; + std::string package_name; + struct Frame { + int left; + int top; + int right; + int bottom; + }; + Frame frame; + int task_id; + int stack_id; + }; + std::vector updated_windows; + std::vector removed_windows; + }; + + void update_window_state(const WindowStateUpdate &state); private: template @@ -50,12 +68,7 @@ private: bool success; }; - void handle_boot_finished_response(Request *request); - void handle_update_window_state_response(Request *request); - mutable std::mutex mutex_; - common::WaitHandle boot_finished_wait_handle_; - common::WaitHandle update_window_state_wait_handle_; std::shared_ptr rpc_channel_; }; diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp index 2c80f9b..8ab0013 100644 --- a/android/service/platform_service.cpp +++ b/android/service/platform_service.cpp @@ -16,7 +16,6 @@ */ #include "android/service/platform_service.h" -#include "android/service/platform_api_stub.h" #include "anbox/rpc/channel.h" #include "anbox_rpc.pb.h" @@ -39,8 +38,8 @@ status_t PlatformService::boot_finished() { return OK; } -void PlatformService::unpack_window_state(anbox::protobuf::bridge::WindowStateUpdate_WindowState *window, const Parcel &data) { - window->set_has_surface(data.readByte() != 0); +anbox::PlatformApiStub::WindowStateUpdate::Window PlatformService::unpack_window_state(const Parcel &data) { + bool has_surface = data.readByte() != 0; String8 package_name(data.readString16()); @@ -51,38 +50,45 @@ void PlatformService::unpack_window_state(anbox::protobuf::bridge::WindowStateUp auto task_id = data.readInt32(); auto stack_id = data.readInt32(); - window->set_package_name(package_name.string()); - window->set_frame_left(frame_left); - window->set_frame_top(frame_top); - window->set_frame_right(frame_right); - window->set_frame_bottom(frame_bottom); - window->set_task_id(task_id); - window->set_stack_id(stack_id); + ALOGI(" Window: package=%s frame={%d,%d,%d,%d} task=%d stack=%d", + package_name.string(), frame_left, frame_top, frame_right, frame_bottom, + task_id, stack_id); + + return anbox::PlatformApiStub::WindowStateUpdate::Window{ + -1, // Display id will be added by the caller + has_surface, + package_name.string(), + {frame_left, frame_top, frame_right, frame_bottom}, + task_id, + stack_id, + }; } status_t PlatformService::update_window_state(const Parcel &data) { - anbox::protobuf::bridge::WindowStateUpdate window_state; + anbox::PlatformApiStub::WindowStateUpdate state; + ALOGI("Udated windows:"); const auto num_displays = data.readInt32(); for (auto n = 0; n < num_displays; n++) { const auto display_id = data.readInt32(); const auto num_windows = data.readInt32(); + ALOGI(" Display: id=%d", display_id); for (auto m = 0; m < num_windows; m++) { - auto window = window_state.add_windows(); - window->set_display_id(display_id); - unpack_window_state(window, data); + auto window = unpack_window_state(data); + window.display_id = display_id; + state.updated_windows.push_back(window); } } + ALOGI("Removed windows:"); const auto num_removed_windows = data.readInt32(); for (auto n = 0; n < num_removed_windows; n++) { - auto window = window_state.add_removed_windows(); - window->set_display_id(0); - unpack_window_state(window, data); + auto window = unpack_window_state(data); + state.removed_windows.push_back(window); } - platform_api_stub_->update_window_state(window_state); + platform_api_stub_->update_window_state(state); return OK; } diff --git a/android/service/platform_service.h b/android/service/platform_service.h index 2578a58..8a4eadf 100644 --- a/android/service/platform_service.h +++ b/android/service/platform_service.h @@ -19,20 +19,12 @@ #define ANBOX_ANDROID_PLATFORM_SERVICE_H_ #include "android/service/platform_service_interface.h" +#include "android/service/platform_api_stub.h" #include #include -namespace anbox { -class PlatformApiStub; -namespace protobuf { -namespace bridge { -class WindowStateUpdate_WindowState; -} // namespace bridge -} // namespace protobuf -} // namespace anbox - namespace android { class PlatformService : public BnPlatformService { public: @@ -44,7 +36,7 @@ public: status_t update_window_state(const Parcel &data) override; private: - void unpack_window_state(anbox::protobuf::bridge::WindowStateUpdate_WindowState *window, const Parcel &data); + anbox::PlatformApiStub::WindowStateUpdate::Window unpack_window_state(const Parcel &data); std::shared_ptr platform_api_stub_; }; } // namespace android diff --git a/src/anbox/bridge/platform_api_skeleton.cpp b/src/anbox/bridge/platform_api_skeleton.cpp index fafa473..cb21e67 100644 --- a/src/anbox/bridge/platform_api_skeleton.cpp +++ b/src/anbox/bridge/platform_api_skeleton.cpp @@ -33,28 +33,15 @@ PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptrRun(); + if (boot_finished_handler_) + boot_finished_handler_(); } -void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done) { - (void) response; - - auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdate_WindowState &window) { - DEBUG("Window: display=%d has_surface=%d frame={%d,%d,%d,%d} package=%s task=%d stack=-1", - window.display_id(), window.has_surface(), - window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom(), - window.package_name(), window.task_id()); +void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event) { + auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState &window) { return wm::WindowState( wm::Display::Id(window.display_id()), window.has_surface(), @@ -65,24 +52,22 @@ void PlatformApiSkeleton::update_window_state(anbox::protobuf::bridge::WindowSta }; wm::WindowState::List updated; - for (int n = 0; n < request->windows_size(); n++) { - const auto window = request->windows(n); + for (int n = 0; n < event.windows_size(); n++) { + const auto window = event.windows(n); updated.push_back(convert_window_state(window)); } wm::WindowState::List removed; - for (int n = 0; n < request->removed_windows_size(); n++) { - const auto window = request->removed_windows(n); + for (int n = 0; n < event.removed_windows_size(); n++) { + const auto window = event.removed_windows(n); removed.push_back(convert_window_state(window)); } window_manager_->apply_window_state_update(updated, removed); - - done->Run(); } -void PlatformApiSkeleton::on_boot_finished(const std::function &action) { - on_boot_finished_action_ = action; +void PlatformApiSkeleton::register_boot_finished_handler(const std::function &action) { + boot_finished_handler_ = action; } } // namespace bridge } // namespace anbox diff --git a/src/anbox/bridge/platform_api_skeleton.h b/src/anbox/bridge/platform_api_skeleton.h index e18f42e..030e7ea 100644 --- a/src/anbox/bridge/platform_api_skeleton.h +++ b/src/anbox/bridge/platform_api_skeleton.h @@ -32,8 +32,8 @@ namespace rpc { class Void; } // namespace rpc namespace bridge { -class Notification; -class WindowStateUpdate; +class BootFinishedEvent; +class WindowStateUpdateEvent; } // namespace bridge } // namespace protobuf namespace rpc { @@ -49,20 +49,15 @@ public: const std::shared_ptr &window_manager); virtual ~PlatformApiSkeleton(); - void boot_finished(anbox::protobuf::rpc::Void const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done); + void handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event); + void handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event); - void update_window_state(anbox::protobuf::bridge::WindowStateUpdate const *request, - anbox::protobuf::rpc::Void *response, - google::protobuf::Closure *done); - - void on_boot_finished(const std::function &action); + void register_boot_finished_handler(const std::function &action); private: std::shared_ptr pending_calls_; std::shared_ptr window_manager_; - std::function on_boot_finished_action_; + std::function boot_finished_handler_; }; } // namespace bridge } // namespace anbox diff --git a/src/anbox/bridge/platform_message_processor.cpp b/src/anbox/bridge/platform_message_processor.cpp index 59d6f28..5b9892c 100644 --- a/src/anbox/bridge/platform_message_processor.cpp +++ b/src/anbox/bridge/platform_message_processor.cpp @@ -18,6 +18,7 @@ #include "anbox/bridge/platform_message_processor.h" #include "anbox/bridge/platform_api_skeleton.h" #include "anbox/rpc/template_message_processor.h" +#include "anbox/logger.h" #include "anbox_bridge.pb.h" @@ -34,13 +35,20 @@ PlatformMessageProcessor::~PlatformMessageProcessor() { } void PlatformMessageProcessor::dispatch(rpc::Invocation const& invocation) { - if (invocation.method_name() == "boot_finished") - invoke(this, server_.get(), &PlatformApiSkeleton::boot_finished, invocation); - else if (invocation.method_name() == "update_window_state") - invoke(this, server_.get(), &PlatformApiSkeleton::update_window_state, invocation); } -void PlatformMessageProcessor::process_event_sequence(const std::string&) { +void PlatformMessageProcessor::process_event_sequence(const std::string &raw_events) { + anbox::protobuf::bridge::EventSequence seq; + if (!seq.ParseFromString(raw_events)) { + WARNING("Failed to parse events from raw string"); + return; + } + + if (seq.has_window_state_update()) + server_->handle_window_state_update_event(seq.window_state_update()); + + if (seq.has_boot_finished()) + server_->handle_boot_finished_event(seq.boot_finished()); } } // namespace anbox } // namespace network diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 950fea8..d2841ca 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -130,7 +130,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) android_api_stub->set_rpc_channel(rpc_channel); auto server = std::make_shared(pending_calls, window_manager); - server->on_boot_finished([&]() { + server->register_boot_finished_handler([&]() { + DEBUG("Android successfully booted"); dispatcher->dispatch([&]() { // FIXME make this configurable or once we have a bridge let the host // act as a DNS proxy. diff --git a/src/anbox/protobuf/anbox_bridge.proto b/src/anbox/protobuf/anbox_bridge.proto index 0dce0df..0a3375a 100644 --- a/src/anbox/protobuf/anbox_bridge.proto +++ b/src/anbox/protobuf/anbox_bridge.proto @@ -2,6 +2,11 @@ option optimize_for = LITE_RUNTIME; package anbox.protobuf.bridge; +message StructuredError { + optional uint32 domain = 1; + optional uint32 code = 2; +} + message Notification { required string package_name = 1; required string category = 2; @@ -27,7 +32,11 @@ message SetDnsServers { repeated Server servers = 2; } -message WindowStateUpdate { + +message BootFinishedEvent { +} + +message WindowStateUpdateEvent { message WindowState { required int32 display_id = 1; required bool has_surface = 2; @@ -42,3 +51,11 @@ message WindowStateUpdate { repeated WindowState windows = 1; repeated WindowState removed_windows = 2; } + +message EventSequence { + optional BootFinishedEvent boot_finished = 1; + optional WindowStateUpdateEvent window_state_update = 2; + + optional string error = 127; + optional StructuredError structured_error = 128; +} diff --git a/src/anbox/protobuf/anbox_rpc.proto b/src/anbox/protobuf/anbox_rpc.proto index dddbd41..dc5f8a9 100644 --- a/src/anbox/protobuf/anbox_rpc.proto +++ b/src/anbox/protobuf/anbox_rpc.proto @@ -12,6 +12,7 @@ message Invocation { message Result { optional uint32 id = 1; optional bytes response = 2; + repeated bytes events = 3; } message StructuredError { diff --git a/src/anbox/rpc/channel.cpp b/src/anbox/rpc/channel.cpp index a99da5a..de52436 100644 --- a/src/anbox/rpc/channel.cpp +++ b/src/anbox/rpc/channel.cpp @@ -42,7 +42,17 @@ void Channel::call_method(std::string const& method_name, google::protobuf::Closure *complete) { auto const &invocation = invocation_for(method_name, parameters); pending_calls_->save_completion_details(invocation, response, complete); - send_message(invocation); + send_message(MessageType::invocation, invocation); +} + +void Channel::send_event(google::protobuf::MessageLite const& event) { + VariableLengthArray<2048> buffer{static_cast(event.ByteSize())}; + event.SerializeWithCachedSizesToArray(buffer.data()); + + anbox::protobuf::rpc::Result response; + response.add_events(buffer.data(), buffer.size()); + + send_message(MessageType::response, response); } protobuf::rpc::Invocation Channel::invocation_for(std::string const& method_name, @@ -62,17 +72,17 @@ protobuf::rpc::Invocation Channel::invocation_for(std::string const& method_name return invoke; } -void Channel::send_message(anbox::protobuf::rpc::Invocation const& invocation) { - const size_t size = invocation.ByteSize(); +void Channel::send_message(const std::uint8_t &type, google::protobuf::MessageLite const& message) { + const size_t size = message.ByteSize(); const unsigned char header_bytes[header_size] = { static_cast((size >> 8) & 0xff), static_cast((size >> 0) & 0xff), - MessageType::invocation, + type, }; std::vector send_buffer(sizeof(header_bytes) + size); std::copy(header_bytes, header_bytes + sizeof(header_bytes), send_buffer.begin()); - invocation.SerializeToArray(send_buffer.data() + sizeof(header_bytes), size); + message.SerializeToArray(send_buffer.data() + sizeof(header_bytes), size); try { std::lock_guard lock(write_mutex_); diff --git a/src/anbox/rpc/channel.h b/src/anbox/rpc/channel.h index 36a350b..8b71659 100644 --- a/src/anbox/rpc/channel.h +++ b/src/anbox/rpc/channel.h @@ -52,11 +52,13 @@ public: google::protobuf::MessageLite *response, google::protobuf::Closure *complete); + void send_event(google::protobuf::MessageLite const& event); + private: protobuf::rpc::Invocation invocation_for( std::string const& method_name, google::protobuf::MessageLite const* request); - void send_message(anbox::protobuf::rpc::Invocation const& invocation); + void send_message(const std::uint8_t &type, google::protobuf::MessageLite const& message); int next_id(); void notify_disconnected(); diff --git a/src/anbox/rpc/message_processor.cpp b/src/anbox/rpc/message_processor.cpp index e19066b..85d5d87 100644 --- a/src/anbox/rpc/message_processor.cpp +++ b/src/anbox/rpc/message_processor.cpp @@ -78,7 +78,11 @@ bool MessageProcessor::process_data(const std::vector &data) { buffer_.erase(buffer_.begin(), buffer_.begin() + message_size); - pending_calls_->complete_response(*result); + if (result->has_id()) + pending_calls_->complete_response(*result); + + for (int n = 0; n < result->events_size(); n++) + process_event_sequence(result->events(n)); } return true; From 161099057ba3c25cd1d4b18b488469a3feb7e6cb Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 25 Nov 2016 08:51:38 +0100 Subject: [PATCH 52/54] Add missing changes for window implementation --- src/anbox/ubuntu/window.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index 8ca34f1..b85f213 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -35,9 +35,10 @@ Window::Observer::~Observer() { } Window::Window(const Id &id, + const wm::Task::Id &task, const std::shared_ptr &observer, - const wm::WindowState &state) : - wm::Window(state), + const graphics::Rect &frame) : + wm::Window(task, frame), id_(id), observer_(observer), native_display_(0), @@ -46,10 +47,10 @@ Window::Window(const Id &id, SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); window_ = SDL_CreateWindow(default_window_name, - state.frame().left(), - state.frame().top(), - state.frame().width(), - state.frame().height(), + frame.left(), + frame.top(), + frame.width(), + frame.height(), SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); if (!window_) { const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); @@ -78,7 +79,7 @@ Window::Window(const Id &id, } Window::Window(int x, int y, int width, int height) : - wm::Window(wm::WindowState()), + wm::Window(0, graphics::Rect{x,y,x + width,y + height}), native_display_(0), native_window_(0) { @@ -123,7 +124,7 @@ void Window::resize(int width, int height) { SDL_SetWindowSize(window_, width, height); } -int Window::update_position(int x, int y) { +void Window::update_position(int x, int y) { SDL_SetWindowPosition(window_, x, y); } From 84b3fa430bf4b9d5c66bcf92582e76d73aedbf47 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Sat, 26 Nov 2016 13:04:50 +0100 Subject: [PATCH 53/54] Set focus to current active window --- Android.mk | 1 + android/CMakeLists.txt | 1 + .../service/activity_manager_interface.cpp | 35 +++++++++++++ android/service/activity_manager_interface.h | 50 +++++++++++++++++++ android/service/android_api_skeleton.cpp | 27 ++++++++++ android/service/android_api_skeleton.h | 11 ++++ android/service/message_processor.cpp | 2 + src/anbox/bridge/android_api_stub.cpp | 32 ++++++++++++ src/anbox/bridge/android_api_stub.h | 3 ++ src/anbox/cmds/run.cpp | 5 +- src/anbox/protobuf/anbox_bridge.proto | 3 ++ src/anbox/ubuntu/platform_policy.cpp | 10 ++++ src/anbox/ubuntu/platform_policy.h | 8 ++- src/anbox/ubuntu/window.cpp | 40 ++------------- src/anbox/ubuntu/window.h | 2 +- 15 files changed, 189 insertions(+), 41 deletions(-) create mode 100644 android/service/activity_manager_interface.cpp create mode 100644 android/service/activity_manager_interface.h diff --git a/Android.mk b/Android.mk index 7da57f7..d476f9e 100644 --- a/Android.mk +++ b/Android.mk @@ -29,6 +29,7 @@ LOCAL_SRC_FILES := \ android/service/host_connector.cpp \ android/service/local_socket_connection.cpp \ android/service/message_processor.cpp \ + android/service/activity_manager_interface.cpp \ android/service/android_api_skeleton.cpp \ android/service/platform_service_interface.cpp \ android/service/platform_service.cpp \ diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 3e86232..86103d8 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -7,6 +7,7 @@ set(ANBOXD_SOURCES ${CMAKE_SOURCE_DIR}/src/anbox/rpc/message_processor.cpp ${CMAKE_SOURCE_DIR}/src/anbox/rpc/pending_call_cache.cpp ${CMAKE_SOURCE_DIR}/src/anbox/common/fd.cpp + service/activity_manager_interface.cpp service/platform_service.cpp service/platform_service_interface.cpp service/platform_api_stub.cpp diff --git a/android/service/activity_manager_interface.cpp b/android/service/activity_manager_interface.cpp new file mode 100644 index 0000000..84dce86 --- /dev/null +++ b/android/service/activity_manager_interface.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#define LOG_TAG "Anboxd" + +#include "android/service/activity_manager_interface.h" + +namespace android { +BpActivityManager::BpActivityManager(const sp &binder) : + BpInterface(binder) { +} + +status_t BpActivityManager::setFocusedTask(int32_t id) { + Parcel data, reply; + data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); + data.writeInt32(id); + return remote()->transact(IActivityManager::SET_FOCUSED_TASK, data, &reply); +} + +IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager"); +} // namespace android diff --git a/android/service/activity_manager_interface.h b/android/service/activity_manager_interface.h new file mode 100644 index 0000000..655fdb6 --- /dev/null +++ b/android/service/activity_manager_interface.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#ifndef ANBOX_ANDROID_ACTIVITY_MANAGER_INTERFACE_H_ +#define ANBOX_ANDROID_ACTIVITY_MANAGER_INTERFACE_H_ + +#include +#include +#include + +#include +#include + +#include + +namespace android { +class IActivityManager : public IInterface { +public: + DECLARE_META_INTERFACE(ActivityManager); + + enum { + // This needs to stay synchronized with frameworks/base/core/java/android/app/IActivityManager.java + SET_FOCUSED_TASK = IBinder::FIRST_CALL_TRANSACTION + 130, + }; + + virtual status_t setFocusedTask(int32_t id) = 0; +}; + +class BpActivityManager : public BpInterface { +public: + BpActivityManager(const sp &binder); + + status_t setFocusedTask(int32_t id) override; +}; +} // namespace android +#endif diff --git a/android/service/android_api_skeleton.cpp b/android/service/android_api_skeleton.cpp index 3181787..f692721 100644 --- a/android/service/android_api_skeleton.cpp +++ b/android/service/android_api_skeleton.cpp @@ -15,6 +15,8 @@ * */ +#define LOG_TAG "Anboxd" + #include "android/service/android_api_skeleton.h" #include "anbox_rpc.pb.h" @@ -23,6 +25,8 @@ #include #include +#include + namespace { std::map common_env = { {"ANDROID_DATA", "/data"}, @@ -48,6 +52,14 @@ void AndroidApiSkeleton::wait_for_process(core::posix::ChildProcess &process, } } +void AndroidApiSkeleton::connect_services() { + if (!activity_manager_.get()) { + auto am = android::defaultServiceManager()->getService(android::String16("activity")); + if (am.get()) + activity_manager_ = new android::BpActivityManager(am); + } +} + void AndroidApiSkeleton::install_application(anbox::protobuf::bridge::InstallApplication const *request, anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) { @@ -106,4 +118,19 @@ void AndroidApiSkeleton::set_dns_servers(anbox::protobuf::bridge::SetDnsServers done->Run(); } + +void AndroidApiSkeleton::set_focused_task(anbox::protobuf::bridge::SetFocusedTask const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done) { + (void) response; + + connect_services(); + + if (activity_manager_.get()) + activity_manager_->setFocusedTask(request->id()); + else + response->set_error("ActivityManager is not available"); + + done->Run(); +} } // namespace anbox diff --git a/android/service/android_api_skeleton.h b/android/service/android_api_skeleton.h index 8e8787b..4cdd582 100644 --- a/android/service/android_api_skeleton.h +++ b/android/service/android_api_skeleton.h @@ -18,6 +18,8 @@ #ifndef ANBOX_PLATFORM_API_SKELETON_H_ #define ANBOX_PLATFORM_API_SKELETON_H_ +#include "android/service/activity_manager_interface.h" + namespace google { namespace protobuf { class Closure; @@ -36,6 +38,7 @@ namespace bridge { class InstallApplication; class LaunchApplication; class SetDnsServers; +class SetFocusedTask; } // namespace bridge namespace rpc { class Void; @@ -58,9 +61,17 @@ public: anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done); + void set_focused_task(anbox::protobuf::bridge::SetFocusedTask const *request, + anbox::protobuf::rpc::Void *response, + google::protobuf::Closure *done); + private: void wait_for_process(core::posix::ChildProcess &process, anbox::protobuf::rpc::Void *response); + + void connect_services(); + + android::sp activity_manager_; }; } // namespace anbox diff --git a/android/service/message_processor.cpp b/android/service/message_processor.cpp index 3a035be..4036917 100644 --- a/android/service/message_processor.cpp +++ b/android/service/message_processor.cpp @@ -41,6 +41,8 @@ void MessageProcessor::dispatch(rpc::Invocation const& invocation) { invoke(this, platform_api_.get(), &AndroidApiSkeleton::launch_application, invocation); else if (invocation.method_name() == "set_dns_servers") invoke(this, platform_api_.get(), &AndroidApiSkeleton::set_dns_servers, invocation); + else if (invocation.method_name() == "set_focused_task") + invoke(this, platform_api_.get(), &AndroidApiSkeleton::set_focused_task, invocation); } void MessageProcessor::process_event_sequence(const std::string&) { diff --git a/src/anbox/bridge/android_api_stub.cpp b/src/anbox/bridge/android_api_stub.cpp index e7bb5f7..92c4370 100644 --- a/src/anbox/bridge/android_api_stub.cpp +++ b/src/anbox/bridge/android_api_stub.cpp @@ -82,6 +82,7 @@ void AndroidApiStub::install(const std::string &path) { } void AndroidApiStub::application_installed(Request *request) { + (void) request; install_wait_handle_.result_received(); } @@ -110,6 +111,7 @@ void AndroidApiStub::launch(const std::string &package, const std::string &activ } void AndroidApiStub::application_launched(Request *request) { + (void) request; launch_wait_handle_.result_received(); } @@ -143,7 +145,37 @@ void AndroidApiStub::set_dns_servers(const std::string &domain, const std::vecto } void AndroidApiStub::dns_servers_set(Request *request) { + (void) request; set_dns_servers_wait_handle_.result_received(); } + +void AndroidApiStub::set_focused_task(const std::int32_t &id) { + ensure_rpc_channel(); + + auto c = std::make_shared>(); + + protobuf::bridge::SetFocusedTask message; + message.set_id(id); + + { + std::lock_guard lock(mutex_); + set_focused_task_handle_.expect_result(); + } + + channel_->call_method("set_focused_task", + &message, + c->response.get(), + google::protobuf::NewCallback(this, &AndroidApiStub::focused_task_set, c.get())); + + set_focused_task_handle_.wait_for_all(); + + if (c->response->has_error()) + throw std::runtime_error(c->response->error()); +} + +void AndroidApiStub::focused_task_set(Request *request) { + (void) request; + set_focused_task_handle_.result_received(); +} } // namespace bridge } // namespace anbox diff --git a/src/anbox/bridge/android_api_stub.h b/src/anbox/bridge/android_api_stub.h index 58e1a92..73cff7c 100644 --- a/src/anbox/bridge/android_api_stub.h +++ b/src/anbox/bridge/android_api_stub.h @@ -46,6 +46,7 @@ public: void launch(const std::string &package, const std::string &activity) override; void set_dns_servers(const std::string &domain, const std::vector &servers); + void set_focused_task(const std::int32_t &id); private: void ensure_rpc_channel(); @@ -60,12 +61,14 @@ private: void application_installed(Request *request); void application_launched(Request *request); void dns_servers_set(Request *request); + void focused_task_set(Request *request); mutable std::mutex mutex_; std::shared_ptr channel_; common::WaitHandle install_wait_handle_; common::WaitHandle launch_wait_handle_; common::WaitHandle set_dns_servers_wait_handle_; + common::WaitHandle set_focused_task_handle_; }; } // namespace bridge } // namespace anbox diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index d2841ca..f32c522 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -89,7 +89,9 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto input_manager = std::make_shared(rt); - auto policy = std::make_shared(input_manager); + auto android_api_stub = std::make_shared(); + + auto policy = std::make_shared(input_manager, android_api_stub); // FIXME this needs to be removed and solved differently behind the scenes registerDisplayManager(policy); @@ -116,7 +118,6 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) renderer->socket_path(), icon_)); - auto android_api_stub = std::make_shared(); auto bridge_connector = std::make_shared( utils::string_format("%s/anbox_bridge", config::socket_path()), diff --git a/src/anbox/protobuf/anbox_bridge.proto b/src/anbox/protobuf/anbox_bridge.proto index 0a3375a..382a2b8 100644 --- a/src/anbox/protobuf/anbox_bridge.proto +++ b/src/anbox/protobuf/anbox_bridge.proto @@ -32,6 +32,9 @@ message SetDnsServers { repeated Server servers = 2; } +message SetFocusedTask { + required int32 id = 1; +} message BootFinishedEvent { } diff --git a/src/anbox/ubuntu/platform_policy.cpp b/src/anbox/ubuntu/platform_policy.cpp index 0045b61..2eefe38 100644 --- a/src/anbox/ubuntu/platform_policy.cpp +++ b/src/anbox/ubuntu/platform_policy.cpp @@ -20,6 +20,7 @@ #include "anbox/ubuntu/keycode_converter.h" #include "anbox/input/manager.h" #include "anbox/input/device.h" +#include "anbox/bridge/android_api_stub.h" #include "anbox/logger.h" #include @@ -199,6 +200,15 @@ void PlatformPolicy::window_deleted(const Window::Id &id) { windows_.erase(w); } +void PlatformPolicy::window_wants_focus(const Window::Id &id) { + auto w = windows_.find(id); + if (w == windows_.end()) + return; + + if (auto window = w->second.lock()) + android_api_->set_focused_task(window->task()); +} + DisplayManager::DisplayInfo PlatformPolicy::display_info() const { return display_info_; } diff --git a/src/anbox/ubuntu/platform_policy.h b/src/anbox/ubuntu/platform_policy.h index 242c5c8..7bab173 100644 --- a/src/anbox/ubuntu/platform_policy.h +++ b/src/anbox/ubuntu/platform_policy.h @@ -33,18 +33,23 @@ namespace input { class Device; class Manager; } // namespace input +namespace bridge { +class AndroidApiStub; +} // namespace bridge namespace ubuntu { class PlatformPolicy : public std::enable_shared_from_this, public wm::PlatformPolicy, public Window::Observer, public DisplayManager { public: - PlatformPolicy(const std::shared_ptr &input_manager); + PlatformPolicy(const std::shared_ptr &input_manager, + const std::shared_ptr &android_api); ~PlatformPolicy(); std::shared_ptr create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override; void window_deleted(const Window::Id &id) override; + void window_wants_focus(const Window::Id &id) override; DisplayInfo display_info() const override; @@ -55,6 +60,7 @@ private: static Window::Id next_window_id(); std::shared_ptr input_manager_; + std::shared_ptr android_api_; // We don't own the windows anymore after the got created by us so we // need to be careful once we try to use them again. std::map> windows_; diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index b85f213..1864dcd 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -62,7 +62,6 @@ Window::Window(const Id &id, SDL_GetWindowWMInfo(window_, &info); switch (info.subsystem) { case SDL_SYSWM_X11: - DEBUG("Running on X11"); native_display_ = static_cast(info.info.x11.display); native_window_ = static_cast(info.info.x11.window); break; @@ -75,41 +74,6 @@ Window::Window(const Id &id, int actual_x = 0, actual_y = 0; SDL_GetWindowSize(window_, &actual_width, &actual_height); SDL_GetWindowPosition(window_, &actual_x, &actual_y); - DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height); -} - -Window::Window(int x, int y, int width, int height) : - wm::Window(0, graphics::Rect{x,y,x + width,y + height}), - native_display_(0), - native_window_(0) { - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); - - window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); - if (!window_) { - const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); - BOOST_THROW_EXCEPTION(std::runtime_error(message)); - } - - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - SDL_GetWindowWMInfo(window_, &info); - switch (info.subsystem) { - case SDL_SYSWM_X11: - DEBUG("Running on X11"); - native_display_ = static_cast(info.info.x11.display); - native_window_ = static_cast(info.info.x11.window); - break; - default: - ERROR("Unknown subsystem (%d)", info.subsystem); - BOOST_THROW_EXCEPTION(std::runtime_error("SDL subsystem not suported")); - } - - int actual_width = 0, actual_height = 0; - int actual_x = 0, actual_y = 0; - SDL_GetWindowSize(window_, &actual_width, &actual_height); - SDL_GetWindowPosition(window_, &actual_x, &actual_y); - DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height); } Window::~Window() { @@ -129,8 +93,10 @@ void Window::update_position(int x, int y) { } void Window::process_event(const SDL_Event &event) { - switch (event.window.type) { + switch (event.window.event) { case SDL_WINDOWEVENT_FOCUS_GAINED: + if (observer_) + observer_->window_wants_focus(id_); break; case SDL_WINDOWEVENT_FOCUS_LOST: break; diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index a92ea85..a2fb444 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -39,10 +39,10 @@ public: public: virtual ~Observer(); virtual void window_deleted(const Id &id) = 0; + virtual void window_wants_focus(const Id &id) = 0; }; Window(const Id &id, const wm::Task::Id &task, const std::shared_ptr &observer, const graphics::Rect &frame); - Window(int x, int y, int width, int height); ~Window(); void process_event(const SDL_Event &event); From ac8c4a93051c299989d82b6a485df86611a8f704 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Sat, 26 Nov 2016 13:05:24 +0100 Subject: [PATCH 54/54] Correct RPC message processing and invocation id assignment --- src/anbox/rpc/channel.cpp | 5 +-- src/anbox/rpc/channel.h | 3 +- src/anbox/rpc/message_processor.cpp | 54 ++++++++++++++--------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/anbox/rpc/channel.cpp b/src/anbox/rpc/channel.cpp index de52436..d613996 100644 --- a/src/anbox/rpc/channel.cpp +++ b/src/anbox/rpc/channel.cpp @@ -98,8 +98,9 @@ void Channel::notify_disconnected() { pending_calls_->force_completion(); } -int Channel::next_id() { - return next_message_id_.fetch_add(1); +std::uint32_t Channel::next_id() { + static std::uint32_t next_message_id = 0; + return next_message_id++; } } // namespace rpc } // namespace anbox diff --git a/src/anbox/rpc/channel.h b/src/anbox/rpc/channel.h index 8b71659..3dc9e11 100644 --- a/src/anbox/rpc/channel.h +++ b/src/anbox/rpc/channel.h @@ -59,10 +59,9 @@ private: std::string const& method_name, google::protobuf::MessageLite const* request); void send_message(const std::uint8_t &type, google::protobuf::MessageLite const& message); - int next_id(); + std::uint32_t next_id(); void notify_disconnected(); - std::atomic next_message_id_; std::shared_ptr pending_calls_; std::shared_ptr sender_; std::mutex write_mutex_; diff --git a/src/anbox/rpc/message_processor.cpp b/src/anbox/rpc/message_processor.cpp index 85d5d87..c3b190d 100644 --- a/src/anbox/rpc/message_processor.cpp +++ b/src/anbox/rpc/message_processor.cpp @@ -20,6 +20,7 @@ #include "anbox/rpc/make_protobuf_object.h" #include "anbox/rpc/constants.h" #include "anbox/common/variable_length_array.h" +#include "anbox/utils.h" #include "anbox_rpc.pb.h" @@ -50,39 +51,38 @@ bool MessageProcessor::process_data(const std::vector &data) { for (const auto &byte : data) buffer_.push_back(byte); - buffer_.shrink_to_fit(); + while (buffer_.size() > 0) { + const auto high = buffer_[0]; + const auto low = buffer_[1]; + size_t const message_size = (high << 8) + low; + const auto message_type = buffer_[2]; - const auto high = buffer_[0]; - const auto low = buffer_[1]; - size_t const message_size = (high << 8) + low; - const auto message_type = buffer_[2]; + // If we don't have yet all bytes for a new message return and wait + // until we have all. + if (buffer_.size() - header_size < message_size) { + WARNING("Don't have enough bytes yet (buffer %d header %d message %d)", + buffer_.size(), header_size, message_size); + break; + } - // If we don't have yet all bytes for a new message return and wait - // until we have all. - if (buffer_.size() - header_size < message_size) - return true; + if (message_type == MessageType::invocation) { + anbox::protobuf::rpc::Invocation raw_invocation; + raw_invocation.ParseFromArray(buffer_.data() + header_size, message_size); - buffer_.erase(buffer_.begin(), buffer_.begin() + header_size); + dispatch(Invocation(raw_invocation)); + } + else if (message_type == MessageType::response) { + auto result = make_protobuf_object(); + result->ParseFromArray(buffer_.data() + header_size, message_size); - if (message_type == MessageType::invocation) { - anbox::protobuf::rpc::Invocation raw_invocation; - raw_invocation.ParseFromArray(buffer_.data(), message_size); + if (result->has_id()) + pending_calls_->complete_response(*result); - buffer_.erase(buffer_.begin(), buffer_.begin() + message_size); + for (int n = 0; n < result->events_size(); n++) + process_event_sequence(result->events(n)); + } - dispatch(Invocation(raw_invocation)); - } - else if (message_type == MessageType::response) { - auto result = make_protobuf_object(); - result->ParseFromArray(buffer_.data(), message_size); - - buffer_.erase(buffer_.begin(), buffer_.begin() + message_size); - - if (result->has_id()) - pending_calls_->complete_response(*result); - - for (int n = 0; n < result->events_size(); n++) - process_event_sequence(result->events(n)); + buffer_.erase(buffer_.begin(), buffer_.begin() + header_size + message_size); } return true;