From 9f69c580af6fbf80629e4edbbbeec773d10d9778 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Wed, 21 Dec 2016 10:02:02 +0100 Subject: [PATCH] Get rid of renderer singleton --- src/anbox/cmds/run.cpp | 15 +- src/anbox/graphics/emugl/RenderControl.cpp | 136 +++++++----------- src/anbox/graphics/emugl/RenderControl.h | 3 + src/anbox/graphics/emugl/RenderThread.cpp | 14 +- src/anbox/graphics/emugl/RenderThread.h | 9 +- src/anbox/graphics/emugl/Renderer.cpp | 110 +++++--------- src/anbox/graphics/emugl/Renderer.h | 11 +- src/anbox/graphics/gl_renderer_server.cpp | 12 +- src/anbox/graphics/gl_renderer_server.h | 5 +- src/anbox/graphics/layer_composer.cpp | 6 +- src/anbox/graphics/layer_composer.h | 5 +- .../graphics/opengles_message_processor.cpp | 9 +- .../graphics/opengles_message_processor.h | 4 +- src/anbox/qemu/pipe_connection_creator.cpp | 7 +- src/anbox/qemu/pipe_connection_creator.h | 5 +- src/anbox/ubuntu/platform_policy.cpp | 11 +- src/anbox/ubuntu/platform_policy.h | 5 + src/anbox/ubuntu/window.cpp | 5 +- src/anbox/ubuntu/window.h | 5 +- src/anbox/wm/default_platform_policy.cpp | 2 +- src/anbox/wm/window.cpp | 12 +- src/anbox/wm/window.h | 7 +- 22 files changed, 186 insertions(+), 212 deletions(-) diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index e23e6ea..6e32f09 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -110,25 +110,17 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory) auto launcher_storage = std::make_shared( xdg::data().home() / "applications"); - auto renderer = + auto gl_server = std::make_shared(window_manager); - renderer->start(); -// Socket which will be used by the qemud service inside the Android -// container for things like sensors, vibrtator etc. -#if 0 - auto qemud_connector = std::make_shared( - utils::string_format("%s/qemud", config::socket_path()), - rt, - std::make_shared()); -#endif + policy->set_renderer(gl_server->renderer()); // The qemu pipe is used as a very fast communication channel between guest // and host for things like the GLES emulation/translation, the RIL or ADB. auto qemu_pipe_connector = std::make_shared( utils::string_format("%s/qemu_pipe", config::socket_path()), rt, - std::make_shared(rt)); + std::make_shared(gl_server->renderer(), rt)); auto bridge_connector = std::make_shared( utils::string_format("%s/anbox_bridge", config::socket_path()), rt, @@ -154,7 +146,6 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory) container::Client container(rt); container::Configuration container_configuration; container_configuration.bind_mounts = { - // { 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"}, diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 9527c5b..9e877d8 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -32,32 +32,34 @@ static const GLint rendererVersion = 1; static std::shared_ptr composer; +static std::shared_ptr renderer; void registerLayerComposer( const std::shared_ptr &c) { composer = c; } +void registerRenderer(const std::shared_ptr &r) { + renderer = r; +} + static GLint rcGetRendererVersion() { return rendererVersion; } static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return EGL_FALSE; - } - *major = (EGLint)fb->getCaps().eglMajor; - *minor = (EGLint)fb->getCaps().eglMinor; + + *major = (EGLint)renderer->getCaps().eglMajor; + *minor = (EGLint)renderer->getCaps().eglMinor; return EGL_TRUE; } static EGLint rcQueryEGLString(EGLenum name, void *buffer, EGLint bufferSize) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } - const char *str = s_egl.eglQueryString(fb->getDisplay(), name); + const char *str = s_egl.eglQueryString(renderer->getDisplay(), name); if (!str) { return 0; } @@ -121,7 +123,7 @@ static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) { static EGLint rcGetNumConfigs(uint32_t *p_numAttribs) { int numConfigs = 0, numAttribs = 0; - Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs); + renderer->getConfigs()->getPackInfo(&numConfigs, &numAttribs); if (p_numAttribs) { *p_numAttribs = static_cast(numAttribs); } @@ -130,25 +132,21 @@ static EGLint rcGetNumConfigs(uint32_t *p_numAttribs) { static EGLint rcGetConfigs(uint32_t bufSize, GLuint *buffer) { GLuint bufferSize = (GLuint)bufSize; - return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer); + return renderer->getConfigs()->packConfigs(bufferSize, buffer); } static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size, uint32_t *configs, uint32_t configs_size) { - Renderer *fb = Renderer::get(); - if (!fb || attribs_size == 0) { + if (!renderer || attribs_size == 0) return 0; - } - return fb->getConfigs()->chooseConfig(attribs, (EGLint *)configs, + return renderer->getConfigs()->chooseConfig(attribs, (EGLint *)configs, (EGLint)configs_size); } static EGLint rcGetFBParam(EGLint param) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } EGLint ret = 0; @@ -183,62 +181,51 @@ static EGLint rcGetFBParam(EGLint param) { static uint32_t rcCreateContext(uint32_t config, uint32_t share, uint32_t glVersion) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } // To make it consistent with the guest, create GLES2 context when GL // version==2 or 3 HandleType ret = - fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3); + renderer->createRenderContext(config, share, glVersion == 2 || glVersion == 3); return ret; } static void rcDestroyContext(uint32_t context) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->DestroyRenderContext(context); + renderer->DestroyRenderContext(context); } static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width, uint32_t height) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } - return fb->createWindowSurface(config, width, height); + return renderer->createWindowSurface(config, width, height); } static void rcDestroyWindowSurface(uint32_t windowSurface) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->DestroyWindowSurface(windowSurface); + renderer->DestroyWindowSurface(windowSurface); } static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } - return fb->createColorBuffer(width, height, internalFormat); + return renderer->createColorBuffer(width, height, internalFormat); } static int rcOpenColorBuffer2(uint32_t colorbuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return -1; - } - return fb->openColorBuffer(colorbuffer); + + return renderer->openColorBuffer(colorbuffer); } // Deprecated, kept for compatibility with old system images only. @@ -248,41 +235,36 @@ static void rcOpenColorBuffer(uint32_t colorbuffer) { } static void rcCloseColorBuffer(uint32_t colorbuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->closeColorBuffer(colorbuffer); + + renderer->closeColorBuffer(colorbuffer); } static int rcFlushWindowColorBuffer(uint32_t windowSurface) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return -1; - } - if (!fb->flushWindowSurfaceColorBuffer(windowSurface)) { + + if (!renderer->flushWindowSurfaceColorBuffer(windowSurface)) return -1; - } + return 0; } static void rcSetWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer); + + renderer->setWindowSurfaceColorBuffer(windowSurface, colorBuffer); } static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf, uint32_t readSurf) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return EGL_FALSE; - } - bool ret = fb->bindContext(context, drawSurf, readSurf); + bool ret = renderer->bindContext(context, drawSurf, readSurf); return (ret ? EGL_TRUE : EGL_FALSE); } @@ -294,21 +276,17 @@ static void rcFBSetSwapInterval(EGLint interval) { } static void rcBindTexture(uint32_t colorBuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->bindColorBufferToTexture(colorBuffer); + renderer->bindColorBufferToTexture(colorBuffer); } static void rcBindRenderbuffer(uint32_t colorBuffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->bindColorBufferToRenderbuffer(colorBuffer); + renderer->bindColorBufferToRenderbuffer(colorBuffer); } static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount, @@ -320,43 +298,35 @@ static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount, static void rcReadColorBuffer(uint32_t colorBuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return; - } - fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); + renderer->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); } static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return -1; - } - fb->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); + renderer->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); return 0; } static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } - return fb->createClientImage(context, target, buffer); + return renderer->createClientImage(context, target, buffer); } static int rcDestroyClientImage(uint32_t image) { - Renderer *fb = Renderer::get(); - if (!fb) { + if (!renderer) return 0; - } - return fb->destroyClientImage(image); + return renderer->destroyClientImage(image); } static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) { diff --git a/src/anbox/graphics/emugl/RenderControl.h b/src/anbox/graphics/emugl/RenderControl.h index ba707bc..82f1635 100644 --- a/src/anbox/graphics/emugl/RenderControl.h +++ b/src/anbox/graphics/emugl/RenderControl.h @@ -20,6 +20,8 @@ #include +class Renderer; + namespace anbox { namespace graphics { class LayerComposer; @@ -29,5 +31,6 @@ class LayerComposer; void initRenderControlContext(renderControl_decoder_context_t *dec); void registerLayerComposer( const std::shared_ptr &c); +void registerRenderer(const std::shared_ptr &r); #endif diff --git a/src/anbox/graphics/emugl/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp index 6043030..750d6de 100644 --- a/src/anbox/graphics/emugl/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -30,13 +30,13 @@ #define STREAM_BUFFER_SIZE 4 * 1024 * 1024 -RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) - : emugl::Thread(), m_lock(lock), m_stream(stream) {} +RenderThread::RenderThread(const std::shared_ptr &renderer, IOStream *stream, emugl::Mutex *lock) + : emugl::Thread(), renderer_(renderer), m_lock(lock), m_stream(stream) {} RenderThread::~RenderThread() {} -RenderThread *RenderThread::create(IOStream *stream, emugl::Mutex *lock) { - return new RenderThread(stream, lock); +RenderThread *RenderThread::create(const std::shared_ptr &renderer, IOStream *stream, emugl::Mutex *lock) { + return new RenderThread(renderer, stream, lock); } void RenderThread::forceStop() { m_stream->forceStop(); } @@ -87,12 +87,12 @@ intptr_t RenderThread::main() { } // Release references to the current thread's context/surfaces if any - Renderer::get()->bindContext(0, 0, 0); + renderer_->bindContext(0, 0, 0); if (threadInfo.currContext || threadInfo.currDrawSurf || threadInfo.currReadSurf) ERROR("RenderThread exiting with current context/surfaces"); - Renderer::get()->drainWindowSurface(); - Renderer::get()->drainRenderContext(); + renderer_->drainWindowSurface(); + renderer_->drainRenderContext(); return 0; } diff --git a/src/anbox/graphics/emugl/RenderThread.h b/src/anbox/graphics/emugl/RenderThread.h index b2bbc71..a34fdec 100644 --- a/src/anbox/graphics/emugl/RenderThread.h +++ b/src/anbox/graphics/emugl/RenderThread.h @@ -21,6 +21,10 @@ #include "emugl/common/mutex.h" #include "emugl/common/thread.h" +#include + +class Renderer; + // A class used to model a thread of the RenderServer. Each one of them // handles a single guest client / protocol byte stream. class RenderThread : public emugl::Thread { @@ -32,7 +36,7 @@ class RenderThread : public emugl::Thread { // decoding operations between all threads. // TODO(digit): Why is this needed here? Shouldn't this be handled // by the decoders themselves or at a lower-level? - static RenderThread* create(IOStream* stream, emugl::Mutex* mutex); + static RenderThread* create(const std::shared_ptr &renderer, IOStream* stream, emugl::Mutex* mutex); // Destructor. virtual ~RenderThread(); @@ -47,10 +51,11 @@ class RenderThread : public emugl::Thread { private: RenderThread(); // No default constructor - RenderThread(IOStream* stream, emugl::Mutex* mutex); + RenderThread(const std::shared_ptr &renderer, IOStream* stream, emugl::Mutex* mutex); virtual intptr_t main(); + std::shared_ptr renderer_; emugl::Mutex* m_lock; IOStream* m_stream; }; diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index 03f6f75..a353848 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -41,7 +41,7 @@ class ScopedBind { // Constructor will call bind_locked() on |fb|. // Use isValid() to check for errors. ScopedBind(Renderer *fb) : mFb(fb) { - if (!mFb->bind_locked()) { + if (!fb->bind_locked()) { mFb = NULL; } } @@ -83,7 +83,6 @@ class ColorBufferHelper : public ColorBuffer::Helper { } // namespace -Renderer *Renderer::s_renderer = NULL; HandleType Renderer::s_nextHandle = 0; static char *getGLES1ExtensionString(EGLDisplay p_dpy) { @@ -150,41 +149,27 @@ void Renderer::finalize() { } bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { - GL_LOG("FrameBuffer::initialize"); - if (s_renderer != NULL) { - return true; - } - - // - // allocate space for the FrameBuffer object - // - Renderer *fb = new Renderer(); - if (!fb) { - ERR("Failed to create fb\n"); - return false; - } + GL_LOG("Renderer::initialize"); // // Initialize backend EGL display // - fb->m_eglDisplay = s_egl.eglGetDisplay(nativeDisplay); - if (fb->m_eglDisplay == EGL_NO_DISPLAY) { + m_eglDisplay = s_egl.eglGetDisplay(nativeDisplay); + if (m_eglDisplay == EGL_NO_DISPLAY) { ERR("Failed to Initialize backend EGL display\n"); - delete fb; return false; } GL_LOG("call eglInitialize"); - if (!s_egl.eglInitialize(fb->m_eglDisplay, &fb->m_caps.eglMajor, - &fb->m_caps.eglMinor)) { + if (!s_egl.eglInitialize(m_eglDisplay, &m_caps.eglMajor, + &m_caps.eglMinor)) { ERR("Failed to eglInitialize\n"); GL_LOG("Failed to eglInitialize"); - delete fb; return false; } - DBG("egl: %d %d\n", fb->m_caps.eglMajor, fb->m_caps.eglMinor); - GL_LOG("egl: %d %d", fb->m_caps.eglMajor, fb->m_caps.eglMinor); + DBG("egl: %d %d\n", m_caps.eglMajor, m_caps.eglMinor); + GL_LOG("egl: %d %d", m_caps.eglMajor, m_caps.eglMinor); s_egl.eglBindAPI(EGL_OPENGL_ES_API); // @@ -192,11 +177,10 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // get GLES2 extension string // char *gles1Extensions = NULL; - gles1Extensions = getGLES1ExtensionString(fb->m_eglDisplay); + gles1Extensions = getGLES1ExtensionString(m_eglDisplay); if (!gles1Extensions) { // Could not create GLES2 context - drop GL2 capability ERR("Failed to obtain GLES 2.x extensions string!\n"); - delete fb; return false; } @@ -217,11 +201,10 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { EGL_NONE}; int n; - if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, &fb->m_eglConfig, + if (!s_egl.eglChooseConfig(m_eglDisplay, configAttribs, &m_eglConfig, 1, &n)) { ERR("Failed on eglChooseConfig\n"); free(gles1Extensions); - delete fb; return false; } @@ -229,12 +212,11 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { EGL_NONE}; GL_LOG("attempting to create egl context"); - fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig, + m_eglContext = s_egl.eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, glContextAttribs); - if (fb->m_eglContext == EGL_NO_CONTEXT) { + if (m_eglContext == EGL_NO_CONTEXT) { ERR("Failed to create context 0x%x\n", s_egl.eglGetError()); free(gles1Extensions); - delete fb; return false; } @@ -247,12 +229,11 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // on Mac platform when switching binded drawable for a context however // it is more efficient on other platforms as well. // - fb->m_pbufContext = s_egl.eglCreateContext( - fb->m_eglDisplay, fb->m_eglConfig, fb->m_eglContext, glContextAttribs); - if (fb->m_pbufContext == EGL_NO_CONTEXT) { + m_pbufContext = s_egl.eglCreateContext( + m_eglDisplay, m_eglConfig, m_eglContext, glContextAttribs); + if (m_pbufContext == EGL_NO_CONTEXT) { ERR("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError()); free(gles1Extensions); - delete fb; return false; } @@ -264,36 +245,27 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; - fb->m_pbufSurface = s_egl.eglCreatePbufferSurface( - fb->m_eglDisplay, fb->m_eglConfig, pbufAttribs); - if (fb->m_pbufSurface == EGL_NO_SURFACE) { + m_pbufSurface = s_egl.eglCreatePbufferSurface( + m_eglDisplay, m_eglConfig, pbufAttribs); + if (m_pbufSurface == EGL_NO_SURFACE) { ERR("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError()); free(gles1Extensions); - delete fb; return false; } GL_LOG("attempting to make context current"); // Make the context current - ScopedBind bind(fb); + ScopedBind bind(this); if (!bind.isValid()) { ERR("Failed to make current\n"); free(gles1Extensions); - delete fb; return false; } GL_LOG("context-current successful"); - // // Initilize framebuffer capabilities - // - // const char* gles2Extensions = (const char - // *)s_gles2.glGetString(GL_EXTENSIONS); bool has_gl_oes_image = false; - // printf("GLES1 [%s]\n", gles1Extensions); - // printf("GLES2 [%s]\n", gles2Extensions); - has_gl_oes_image = true; if (has_gl_oes_image) { @@ -303,16 +275,16 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { gles1Extensions = NULL; const char *eglExtensions = - s_egl.eglQueryString(fb->m_eglDisplay, EGL_EXTENSIONS); + s_egl.eglQueryString(m_eglDisplay, EGL_EXTENSIONS); if (eglExtensions && has_gl_oes_image) { - fb->m_caps.has_eglimage_texture_2d = + m_caps.has_eglimage_texture_2d = strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL; - fb->m_caps.has_eglimage_renderbuffer = + m_caps.has_eglimage_renderbuffer = strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL; } else { - fb->m_caps.has_eglimage_texture_2d = false; - fb->m_caps.has_eglimage_renderbuffer = false; + m_caps.has_eglimage_texture_2d = false; + m_caps.has_eglimage_renderbuffer = false; } // @@ -321,10 +293,9 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // EGL_KHR_gl_texture_2d_image // GL_OES_EGL_IMAGE (by both GLES implementations [1 and 2]) // - if (!fb->m_caps.has_eglimage_texture_2d) { + if (!m_caps.has_eglimage_texture_2d) { ERR("Failed: Missing egl_image related extension(s)\n"); bind.release(); - delete fb; return false; } @@ -332,22 +303,21 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // // Initialize set of configs // - fb->m_configs = new RendererConfigList(fb->m_eglDisplay); - if (fb->m_configs->empty()) { + m_configs = new RendererConfigList(m_eglDisplay); + if (m_configs->empty()) { ERR("Failed: Initialize set of configs\n"); bind.release(); - delete fb; return false; } // // Check that we have config for each GLES and GLES2 // - size_t nConfigs = fb->m_configs->size(); + size_t nConfigs = m_configs->size(); int nGLConfigs = 0; int nGL2Configs = 0; for (size_t i = 0; i < nConfigs; ++i) { - GLint rtype = fb->m_configs->get(i)->getRenderableType(); + GLint rtype = m_configs->get(i)->getRenderableType(); if (0 != (rtype & EGL_OPENGL_ES_BIT)) { nGLConfigs++; } @@ -361,7 +331,6 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // if (nGLConfigs == 0) { bind.release(); - delete fb; return false; } @@ -371,7 +340,6 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { if (nGL2Configs == 0) { ERR("Failed: No GLES 2.x configs found!\n"); bind.release(); - delete fb; return false; } @@ -381,29 +349,25 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) { // Cache the GL strings so we don't have to think about threading or // current-context when asked for them. // - fb->m_glVendor = (const char *)s_gles2.glGetString(GL_VENDOR); - fb->m_glRenderer = (const char *)s_gles2.glGetString(GL_RENDERER); - fb->m_glVersion = (const char *)s_gles2.glGetString(GL_VERSION); + m_glVendor = (const char *)s_gles2.glGetString(GL_VENDOR); + m_glRenderer = (const char *)s_gles2.glGetString(GL_RENDERER); + m_glVersion = (const char *)s_gles2.glGetString(GL_VERSION); - fb->m_textureDraw = new TextureDraw(fb->m_eglDisplay); - if (!fb->m_textureDraw) { + m_textureDraw = new TextureDraw(m_eglDisplay); + if (!m_textureDraw) { ERR("Failed: creation of TextureDraw instance\n"); bind.release(); - delete fb; return false; } - fb->m_defaultProgram = fb->m_family.add_program(vshader, defaultFShader); - fb->m_alphaProgram = fb->m_family.add_program(vshader, alphaFShader); + m_defaultProgram = m_family.add_program(vshader, defaultFShader); + m_alphaProgram = m_family.add_program(vshader, alphaFShader); // release the FB context bind.release(); - // - // Keep the singleton framebuffer pointer - // - s_renderer = fb; GL_LOG("basic EGL initialization successful"); + return true; } diff --git a/src/anbox/graphics/emugl/Renderer.h b/src/anbox/graphics/emugl/Renderer.h index 694bd4d..973c8ae 100644 --- a/src/anbox/graphics/emugl/Renderer.h +++ b/src/anbox/graphics/emugl/Renderer.h @@ -73,6 +73,9 @@ struct RendererWindow; // class Renderer { public: + Renderer(); + ~Renderer(); + // Initialize the global instance. // |width| and |height| are the dimensions of the emulator GPU display // in pixels. |useSubWindow| is true to indicate that the caller @@ -80,15 +83,11 @@ class Renderer { // 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); + bool initialize(EGLNativeDisplayType nativeDisplay); // Finalize the instance. void finalize(); - // Return a pointer to the global instance. initialize() must be called - // previously, or this will return NULL. - static Renderer* get() { return s_renderer; } - // Return the capabilities of the underlying display. const RendererCaps& getCaps() const { return m_caps; } @@ -242,8 +241,6 @@ class Renderer { bool unbind_locked(); private: - Renderer(); - ~Renderer(); HandleType genHandle(); bool bindWindow_locked(RendererWindow* window); diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index cee82c4..24049aa 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -43,7 +43,10 @@ void logger_write(const char *format, ...) { namespace anbox { namespace graphics { GLRendererServer::GLRendererServer(const std::shared_ptr &wm) - : wm_(wm), composer_(std::make_shared(wm)) { + : renderer_(std::make_shared()), + wm_(wm), + composer_(std::make_shared(renderer_, wm)) { + if (utils::is_env_set("USE_HOST_GLES")) { // Force the host EGL/GLES libraries as translator implementation ::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0); @@ -74,13 +77,14 @@ GLRendererServer::GLRendererServer(const std::shared_ptr &wm) BOOST_THROW_EXCEPTION( std::runtime_error("Failed to initialize OpenGL renderer")); + renderer_->initialize(0); + + registerRenderer(renderer_); registerLayerComposer(composer_); } GLRendererServer::~GLRendererServer() { - if (const auto r = Renderer::get()) r->finalize(); + renderer_->finalize(); } - -void GLRendererServer::start() { Renderer::initialize(0); } } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index bd1370b..096cbfc 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -21,6 +21,8 @@ #include #include +class Renderer; + namespace anbox { namespace input { class Manager; @@ -35,9 +37,10 @@ class GLRendererServer { GLRendererServer(const std::shared_ptr &wm); ~GLRendererServer(); - void start(); + std::shared_ptr renderer() const { return renderer_; } private: + std::shared_ptr renderer_; std::shared_ptr wm_; std::shared_ptr composer_; }; diff --git a/src/anbox/graphics/layer_composer.cpp b/src/anbox/graphics/layer_composer.cpp index b716db8..1f5b838 100644 --- a/src/anbox/graphics/layer_composer.cpp +++ b/src/anbox/graphics/layer_composer.cpp @@ -22,8 +22,8 @@ namespace anbox { namespace graphics { -LayerComposer::LayerComposer(const std::shared_ptr &wm) - : wm_(wm) {} +LayerComposer::LayerComposer(const std::shared_ptr renderer, const std::shared_ptr &wm) + : renderer_(renderer), wm_(wm) {} LayerComposer::~LayerComposer() {} @@ -82,7 +82,7 @@ void LayerComposer::submit_layers(const RenderableList &renderables) { final_renderables.push_back(new_renderable); } - Renderer::get()->draw( + renderer_->draw( window->native_handle(), Rect{0, 0, window->frame().width(), window->frame().height()}, final_renderables); diff --git a/src/anbox/graphics/layer_composer.h b/src/anbox/graphics/layer_composer.h index ff6498a..3b8ded0 100644 --- a/src/anbox/graphics/layer_composer.h +++ b/src/anbox/graphics/layer_composer.h @@ -22,6 +22,8 @@ #include +class Renderer; + namespace anbox { namespace wm { class Manager; @@ -29,12 +31,13 @@ class Manager; namespace graphics { class LayerComposer { public: - LayerComposer(const std::shared_ptr &wm); + LayerComposer(const std::shared_ptr renderer, const std::shared_ptr &wm); ~LayerComposer(); void submit_layers(const RenderableList &renderables); private: + std::shared_ptr renderer_; std::shared_ptr wm_; }; } // namespace graphics diff --git a/src/anbox/graphics/opengles_message_processor.cpp b/src/anbox/graphics/opengles_message_processor.cpp index 27bee0f..bd06793 100644 --- a/src/anbox/graphics/opengles_message_processor.cpp +++ b/src/anbox/graphics/opengles_message_processor.cpp @@ -32,6 +32,7 @@ namespace graphics { emugl::Mutex OpenGlesMessageProcessor::global_lock{}; OpenGlesMessageProcessor::OpenGlesMessageProcessor( + const std::shared_ptr &renderer, const std::shared_ptr &messenger) : messenger_(messenger), stream_(std::make_shared(messenger_)) { @@ -42,15 +43,15 @@ OpenGlesMessageProcessor::OpenGlesMessageProcessor( boost::asio::buffer(&client_flags, sizeof(unsigned int))); if (err) ERROR("%s", err.message()); - renderer_.reset(RenderThread::create(stream_.get(), &global_lock)); - if (!renderer_->start()) + render_thread_.reset(RenderThread::create(renderer, stream_.get(), &global_lock)); + if (!render_thread_->start()) BOOST_THROW_EXCEPTION( std::runtime_error("Failed to start renderer thread")); } OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { - renderer_->forceStop(); - renderer_->wait(nullptr); + render_thread_->forceStop(); + render_thread_->wait(nullptr); } bool OpenGlesMessageProcessor::process_data( diff --git a/src/anbox/graphics/opengles_message_processor.h b/src/anbox/graphics/opengles_message_processor.h index 85f14ee..45f4c01 100644 --- a/src/anbox/graphics/opengles_message_processor.h +++ b/src/anbox/graphics/opengles_message_processor.h @@ -31,12 +31,14 @@ class IOStream; class RenderThread; +class Renderer; namespace anbox { namespace graphics { class OpenGlesMessageProcessor : public network::MessageProcessor { public: OpenGlesMessageProcessor( + const std::shared_ptr &renderer, const std::shared_ptr &messenger); ~OpenGlesMessageProcessor(); @@ -47,7 +49,7 @@ class OpenGlesMessageProcessor : public network::MessageProcessor { std::shared_ptr messenger_; std::shared_ptr stream_; - std::shared_ptr renderer_; + std::shared_ptr render_thread_; }; } // namespace graphics } // namespace anbox diff --git a/src/anbox/qemu/pipe_connection_creator.cpp b/src/anbox/qemu/pipe_connection_creator.cpp index e59c6b4..06b9dde 100644 --- a/src/anbox/qemu/pipe_connection_creator.cpp +++ b/src/anbox/qemu/pipe_connection_creator.cpp @@ -63,8 +63,9 @@ std::string client_type_to_string( } namespace anbox { namespace qemu { -PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &rt) - : runtime_(rt), +PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr &renderer, const std::shared_ptr &rt) + : renderer_(renderer), + runtime_(rt), next_connection_id_(0), connections_( std::make_shared>()) { @@ -137,7 +138,7 @@ 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_, messenger); else if (type == client_type::qemud_boot_properties) return std::make_shared(messenger); else if (type == client_type::qemud_hw_control) diff --git a/src/anbox/qemu/pipe_connection_creator.h b/src/anbox/qemu/pipe_connection_creator.h index a8c04f9..cbfadd3 100644 --- a/src/anbox/qemu/pipe_connection_creator.h +++ b/src/anbox/qemu/pipe_connection_creator.h @@ -29,12 +29,14 @@ #include "anbox/network/socket_messenger.h" #include "anbox/runtime.h" +class Renderer; + namespace anbox { namespace qemu { class PipeConnectionCreator : public network::ConnectionCreator { public: - PipeConnectionCreator(const std::shared_ptr &rt); + PipeConnectionCreator(const std::shared_ptr &renderer, const std::shared_ptr &rt); ~PipeConnectionCreator() noexcept; void create_connection_for( @@ -63,6 +65,7 @@ class PipeConnectionCreator const client_type &type, const std::shared_ptr &messenger); + std::shared_ptr renderer_; std::shared_ptr runtime_; std::atomic next_connection_id_; std::shared_ptr> const diff --git a/src/anbox/ubuntu/platform_policy.cpp b/src/anbox/ubuntu/platform_policy.cpp index 8698358..3d717d0 100644 --- a/src/anbox/ubuntu/platform_policy.cpp +++ b/src/anbox/ubuntu/platform_policy.cpp @@ -91,6 +91,10 @@ PlatformPolicy::~PlatformPolicy() { } } +void PlatformPolicy::set_renderer(const std::shared_ptr &renderer) { + renderer_ = renderer; +} + void PlatformPolicy::process_events() { event_thread_running_ = true; @@ -196,8 +200,13 @@ Window::Id PlatformPolicy::next_window_id() { std::shared_ptr PlatformPolicy::create_window( const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) { + if (!renderer_) { + ERROR("Can't create window without a renderer set"); + return nullptr; + } + auto id = next_window_id(); - auto w = std::make_shared(id, task, shared_from_this(), frame); + auto w = std::make_shared(renderer_, 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 c1bbea3..0679aa9 100644 --- a/src/anbox/ubuntu/platform_policy.h +++ b/src/anbox/ubuntu/platform_policy.h @@ -28,6 +28,8 @@ #include +class Renderer; + namespace anbox { namespace input { class Device; @@ -59,12 +61,15 @@ class PlatformPolicy : public std::enable_shared_from_this, DisplayInfo display_info() const override; + void set_renderer(const std::shared_ptr &renderer); + private: void process_events(); void process_input_event(const SDL_Event &event); static Window::Id next_window_id(); + std::shared_ptr renderer_; 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 diff --git a/src/anbox/ubuntu/window.cpp b/src/anbox/ubuntu/window.cpp index 9f22821..68ce319 100644 --- a/src/anbox/ubuntu/window.cpp +++ b/src/anbox/ubuntu/window.cpp @@ -33,10 +33,11 @@ Window::Id Window::Invalid{-1}; Window::Observer::~Observer() {} -Window::Window(const Id &id, const wm::Task::Id &task, +Window::Window(const std::shared_ptr &renderer, + const Id &id, const wm::Task::Id &task, const std::shared_ptr &observer, const graphics::Rect &frame) - : wm::Window(task, frame), + : wm::Window(renderer, task, frame), id_(id), observer_(observer), native_display_(0), diff --git a/src/anbox/ubuntu/window.h b/src/anbox/ubuntu/window.h index 271a16c..686a49b 100644 --- a/src/anbox/ubuntu/window.h +++ b/src/anbox/ubuntu/window.h @@ -27,6 +27,8 @@ #include +class Renderer; + namespace anbox { namespace ubuntu { class Window : public std::enable_shared_from_this, public wm::Window { @@ -45,7 +47,8 @@ class Window : public std::enable_shared_from_this, public wm::Window { const std::int32_t &y) = 0; }; - Window(const Id &id, const wm::Task::Id &task, + Window(const std::shared_ptr &renderer, + const Id &id, const wm::Task::Id &task, const std::shared_ptr &observer, const graphics::Rect &frame); ~Window(); diff --git a/src/anbox/wm/default_platform_policy.cpp b/src/anbox/wm/default_platform_policy.cpp index 31adf59..8ab33b5 100644 --- a/src/anbox/wm/default_platform_policy.cpp +++ b/src/anbox/wm/default_platform_policy.cpp @@ -24,7 +24,7 @@ class NullWindow : public anbox::wm::Window { public: NullWindow(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) - : anbox::wm::Window(0, frame) {} + : anbox::wm::Window(nullptr, 0, frame) {} }; } diff --git a/src/anbox/wm/window.cpp b/src/anbox/wm/window.cpp index 70fb60d..81dfd90 100644 --- a/src/anbox/wm/window.cpp +++ b/src/anbox/wm/window.cpp @@ -21,8 +21,8 @@ namespace anbox { namespace wm { -Window::Window(const Task::Id &task, const graphics::Rect &frame) - : task_(task), frame_(frame) {} +Window::Window(const std::shared_ptr &renderer, const Task::Id &task, const graphics::Rect &frame) + : renderer_(renderer), task_(task), frame_(frame) {} Window::~Window() {} @@ -51,11 +51,15 @@ graphics::Rect Window::frame() const { return frame_; } EGLNativeWindowType Window::native_handle() const { return 0; } bool Window::attach() { - return Renderer::get()->createNativeWindow(native_handle()); + if (!renderer_) + return false; + return renderer_->createNativeWindow(native_handle()); } void Window::release() { - Renderer::get()->destroyNativeWindow(native_handle()); + if (!renderer_) + return; + renderer_->destroyNativeWindow(native_handle()); } } // namespace wm } // namespace anbox diff --git a/src/anbox/wm/window.h b/src/anbox/wm/window.h index aba0d26..fc9634d 100644 --- a/src/anbox/wm/window.h +++ b/src/anbox/wm/window.h @@ -25,6 +25,10 @@ #include +#include + +class Renderer; + namespace anbox { namespace wm { // FIXME(morphis): move this somewhere else once we have the integration @@ -41,7 +45,7 @@ class Window { public: typedef std::vector List; - Window(const Task::Id &task, const graphics::Rect &frame); + Window(const std::shared_ptr &renderer, const Task::Id &task, const graphics::Rect &frame); virtual ~Window(); bool attach(); @@ -55,6 +59,7 @@ class Window { Task::Id task() const; private: + std::shared_ptr renderer_; Task::Id task_; graphics::Rect frame_; };