Get rid of renderer singleton
This commit is contained in:
parent
aeff6e35df
commit
9f69c580af
22 changed files with 186 additions and 212 deletions
|
|
@ -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"},
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue