Get rid of renderer singleton

This commit is contained in:
Simon Fels 2016-12-21 10:02:02 +01:00
commit 9f69c580af
22 changed files with 186 additions and 212 deletions

View file

@ -110,25 +110,17 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory)
auto launcher_storage = std::make_shared<application::LauncherStorage>(
xdg::data().home() / "applications");
auto renderer =
auto gl_server =
std::make_shared<graphics::GLRendererServer>(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<network::PublishedSocketConnector>(
utils::string_format("%s/qemud", config::socket_path()),
rt,
std::make_shared<NullConnectionCreator>());
#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<network::PublishedSocketConnector>(
utils::string_format("%s/qemu_pipe", config::socket_path()), rt,
std::make_shared<qemu::PipeConnectionCreator>(rt));
std::make_shared<qemu::PipeConnectionCreator>(gl_server->renderer(), rt));
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
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"},

View file

@ -32,32 +32,34 @@
static const GLint rendererVersion = 1;
static std::shared_ptr<anbox::graphics::LayerComposer> composer;
static std::shared_ptr<Renderer> renderer;
void registerLayerComposer(
const std::shared_ptr<anbox::graphics::LayerComposer> &c) {
composer = c;
}
void registerRenderer(const std::shared_ptr<Renderer> &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<uint32_t>(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) {

View file

@ -20,6 +20,8 @@
#include <memory>
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<anbox::graphics::LayerComposer> &c);
void registerRenderer(const std::shared_ptr<Renderer> &r);
#endif

View file

@ -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> &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> &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;
}

View file

@ -21,6 +21,10 @@
#include "emugl/common/mutex.h"
#include "emugl/common/thread.h"
#include <memory>
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> &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> &renderer, IOStream* stream, emugl::Mutex* mutex);
virtual intptr_t main();
std::shared_ptr<Renderer> renderer_;
emugl::Mutex* m_lock;
IOStream* m_stream;
};

View file

@ -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;
}

View file

@ -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);

View file

@ -43,7 +43,10 @@ void logger_write(const char *format, ...) {
namespace anbox {
namespace graphics {
GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm)
: wm_(wm), composer_(std::make_shared<LayerComposer>(wm)) {
: renderer_(std::make_shared<Renderer>()),
wm_(wm),
composer_(std::make_shared<LayerComposer>(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::Manager> &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

View file

@ -21,6 +21,8 @@
#include <memory>
#include <string>
class Renderer;
namespace anbox {
namespace input {
class Manager;
@ -35,9 +37,10 @@ class GLRendererServer {
GLRendererServer(const std::shared_ptr<wm::Manager> &wm);
~GLRendererServer();
void start();
std::shared_ptr<Renderer> renderer() const { return renderer_; }
private:
std::shared_ptr<Renderer> renderer_;
std::shared_ptr<wm::Manager> wm_;
std::shared_ptr<LayerComposer> composer_;
};

View file

@ -22,8 +22,8 @@
namespace anbox {
namespace graphics {
LayerComposer::LayerComposer(const std::shared_ptr<wm::Manager> &wm)
: wm_(wm) {}
LayerComposer::LayerComposer(const std::shared_ptr<Renderer> renderer, const std::shared_ptr<wm::Manager> &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);

View file

@ -22,6 +22,8 @@
#include <memory>
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::Manager> &wm);
LayerComposer(const std::shared_ptr<Renderer> renderer, const std::shared_ptr<wm::Manager> &wm);
~LayerComposer();
void submit_layers(const RenderableList &renderables);
private:
std::shared_ptr<Renderer> renderer_;
std::shared_ptr<wm::Manager> wm_;
};
} // namespace graphics

View file

@ -32,6 +32,7 @@ namespace graphics {
emugl::Mutex OpenGlesMessageProcessor::global_lock{};
OpenGlesMessageProcessor::OpenGlesMessageProcessor(
const std::shared_ptr<Renderer> &renderer,
const std::shared_ptr<network::SocketMessenger> &messenger)
: messenger_(messenger),
stream_(std::make_shared<BufferedIOStream>(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(

View file

@ -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> &renderer,
const std::shared_ptr<network::SocketMessenger> &messenger);
~OpenGlesMessageProcessor();
@ -47,7 +49,7 @@ class OpenGlesMessageProcessor : public network::MessageProcessor {
std::shared_ptr<network::SocketMessenger> messenger_;
std::shared_ptr<IOStream> stream_;
std::shared_ptr<RenderThread> renderer_;
std::shared_ptr<RenderThread> render_thread_;
};
} // namespace graphics
} // namespace anbox

View file

@ -63,8 +63,9 @@ std::string client_type_to_string(
}
namespace anbox {
namespace qemu {
PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr<Runtime> &rt)
: runtime_(rt),
PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr<Renderer> &renderer, const std::shared_ptr<Runtime> &rt)
: renderer_(renderer),
runtime_(rt),
next_connection_id_(0),
connections_(
std::make_shared<network::Connections<network::SocketConnection>>()) {
@ -137,7 +138,7 @@ PipeConnectionCreator::create_processor(
const client_type &type,
const std::shared_ptr<network::SocketMessenger> &messenger) {
if (type == client_type::opengles)
return std::make_shared<graphics::OpenGlesMessageProcessor>(messenger);
return std::make_shared<graphics::OpenGlesMessageProcessor>(renderer_, messenger);
else if (type == client_type::qemud_boot_properties)
return std::make_shared<qemu::BootPropertiesMessageProcessor>(messenger);
else if (type == client_type::qemud_hw_control)

View file

@ -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<boost::asio::local::stream_protocol> {
public:
PipeConnectionCreator(const std::shared_ptr<Runtime> &rt);
PipeConnectionCreator(const std::shared_ptr<Renderer> &renderer, const std::shared_ptr<Runtime> &rt);
~PipeConnectionCreator() noexcept;
void create_connection_for(
@ -63,6 +65,7 @@ class PipeConnectionCreator
const client_type &type,
const std::shared_ptr<network::SocketMessenger> &messenger);
std::shared_ptr<Renderer> renderer_;
std::shared_ptr<Runtime> runtime_;
std::atomic<int> next_connection_id_;
std::shared_ptr<network::Connections<network::SocketConnection>> const

View file

@ -91,6 +91,10 @@ PlatformPolicy::~PlatformPolicy() {
}
}
void PlatformPolicy::set_renderer(const std::shared_ptr<Renderer> &renderer) {
renderer_ = renderer;
}
void PlatformPolicy::process_events() {
event_thread_running_ = true;
@ -196,8 +200,13 @@ Window::Id PlatformPolicy::next_window_id() {
std::shared_ptr<wm::Window> 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<Window>(id, task, shared_from_this(), frame);
auto w = std::make_shared<Window>(renderer_, id, task, shared_from_this(), frame);
windows_.insert({id, w});
return w;
}

View file

@ -28,6 +28,8 @@
#include <SDL.h>
class Renderer;
namespace anbox {
namespace input {
class Device;
@ -59,12 +61,15 @@ class PlatformPolicy : public std::enable_shared_from_this<PlatformPolicy>,
DisplayInfo display_info() const override;
void set_renderer(const std::shared_ptr<Renderer> &renderer);
private:
void process_events();
void process_input_event(const SDL_Event &event);
static Window::Id next_window_id();
std::shared_ptr<Renderer> renderer_;
std::shared_ptr<input::Manager> input_manager_;
std::shared_ptr<bridge::AndroidApiStub> android_api_;
// We don't own the windows anymore after the got created by us so we

View file

@ -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> &renderer,
const Id &id, const wm::Task::Id &task,
const std::shared_ptr<Observer> &observer,
const graphics::Rect &frame)
: wm::Window(task, frame),
: wm::Window(renderer, task, frame),
id_(id),
observer_(observer),
native_display_(0),

View file

@ -27,6 +27,8 @@
#include <SDL.h>
class Renderer;
namespace anbox {
namespace ubuntu {
class Window : public std::enable_shared_from_this<Window>, public wm::Window {
@ -45,7 +47,8 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
const std::int32_t &y) = 0;
};
Window(const Id &id, const wm::Task::Id &task,
Window(const std::shared_ptr<Renderer> &renderer,
const Id &id, const wm::Task::Id &task,
const std::shared_ptr<Observer> &observer,
const graphics::Rect &frame);
~Window();

View file

@ -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) {}
};
}

View file

@ -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> &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

View file

@ -25,6 +25,10 @@
#include <EGL/egl.h>
#include <memory>
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<Window> List;
Window(const Task::Id &task, const graphics::Rect &frame);
Window(const std::shared_ptr<Renderer> &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> renderer_;
Task::Id task_;
graphics::Rect frame_;
};