From 30c218682641befac3c561156e3d32d03ad11013 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Fri, 20 Jan 2017 18:05:40 +0100 Subject: [PATCH] Abstract selector of translator or host GL libs a bit more --- .../include/OpenGLESDispatch/EGLDispatch.h | 3 +- .../include/OpenGLESDispatch/GLESv1Dispatch.h | 3 +- .../include/OpenGLESDispatch/GLESv2Dispatch.h | 3 +- .../libs/libOpenGLESDispatch/EGLDispatch.cpp | 22 ++++++---- .../libOpenGLESDispatch/GLESv1Dispatch.cpp | 17 +++++--- .../libOpenGLESDispatch/GLESv2Dispatch.cpp | 17 +++++--- src/anbox/cli.h | 2 +- src/anbox/cmds/run.cpp | 18 +++++++- src/anbox/cmds/run.h | 3 ++ src/anbox/graphics/emugl/RenderApi.cpp | 41 ++++++++++++++++--- src/anbox/graphics/emugl/RenderApi.h | 14 ++++++- src/anbox/graphics/gl_renderer_server.cpp | 37 ++++++----------- src/anbox/graphics/gl_renderer_server.h | 7 +++- 13 files changed, 130 insertions(+), 57 deletions(-) diff --git a/external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h b/external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h index a361954..b70773a 100644 --- a/external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h +++ b/external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h @@ -42,12 +42,13 @@ LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DEFINE_TYPE) // Define EGLDispatch structure. struct EGLDispatch { + bool initialized = false; LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER) LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER) }; // Initialize EGLDispatch function. Return true on success, false on failure. -bool init_egl_dispatch(); +bool init_egl_dispatch(const char *path); // Global EGLDispatch instance. Call init_egl_dispatch() before using it. extern EGLDispatch s_egl; diff --git a/external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h b/external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h index 0260e52..464fa39 100644 --- a/external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h +++ b/external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h @@ -26,6 +26,7 @@ LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE,GLES1_DISPATCH_DEFINE_TYPE) struct GLESv1Dispatch { + bool initialized = false; #define GLES1_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \ func_name ## _t func_name; LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER, @@ -35,7 +36,7 @@ struct GLESv1Dispatch { #undef GLES1_DISPATCH_DECLARE_POINTER #undef GLES1_DISPATCH_DEFINE_TYPE -bool gles1_dispatch_init(GLESv1Dispatch* dispatch_table); +bool gles1_dispatch_init(const char *path, GLESv1Dispatch* dispatch_table); // Used to initialize the decoder. void* gles1_dispatch_get_proc_func(const char* name, void* userData); diff --git a/external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h b/external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h index 511e7b8..f58b31c 100644 --- a/external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h +++ b/external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h @@ -26,6 +26,7 @@ LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DEFINE_TYPE,GLES2_DISPATCH_DEFINE_TYPE) struct GLESv2Dispatch { + bool initialized = false; #define GLES2_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \ func_name ## _t func_name; LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DECLARE_POINTER, @@ -35,7 +36,7 @@ struct GLESv2Dispatch { #undef GLES2_DISPATCH_DECLARE_POINTER #undef GLES2_DISPATCH_DEFINE_TYPE -bool gles2_dispatch_init(GLESv2Dispatch* dispatch_table); +bool gles2_dispatch_init(const char *path, GLESv2Dispatch* dispatch_table); // Used to initialize the decoder. void* gles2_dispatch_get_proc_func(const char* name, void* userData); diff --git a/external/android-emugl/host/libs/libOpenGLESDispatch/EGLDispatch.cpp b/external/android-emugl/host/libs/libOpenGLESDispatch/EGLDispatch.cpp index 2ad9028..d942f5b 100644 --- a/external/android-emugl/host/libs/libOpenGLESDispatch/EGLDispatch.cpp +++ b/external/android-emugl/host/libs/libOpenGLESDispatch/EGLDispatch.cpp @@ -20,9 +20,11 @@ #include #include -EGLDispatch s_egl; +namespace { +constexpr const char *egl_lib_env_var{"ANBOX_EGL_LIB"}; +} -#define DEFAULT_EGL_LIB EMUGL_LIBNAME("EGL_translator") +EGLDispatch s_egl; #define RENDER_EGL_LOAD_FIELD(return_type, function_name, signature) \ s_egl. function_name = (function_name ## _t) lib->findSymbol(#function_name); @@ -33,20 +35,24 @@ EGLDispatch s_egl; if (!s_egl.function_name || !s_egl.eglGetProcAddress) \ RENDER_EGL_LOAD_FIELD(return_type, function_name, signature) -bool init_egl_dispatch() -{ - - const char *libName = getenv("ANDROID_EGL_LIB"); - if (!libName) libName = DEFAULT_EGL_LIB; +bool init_egl_dispatch(const char *path) { + const char *libName = getenv(egl_lib_env_var); + if (!libName) + libName = path; + if (!libName) + return false; char error[256]; emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName, error, sizeof(error)); if (!lib) { printf("Failed to open %s: [%s]\n", libName, error); - return NULL; + return false; } + LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_LOAD_FIELD) LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_LOAD_OPTIONAL_FIELD) + s_egl.initialized = true; + return true; } diff --git a/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv1Dispatch.cpp b/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv1Dispatch.cpp index 8d5433a..b7e43dd 100644 --- a/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv1Dispatch.cpp +++ b/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv1Dispatch.cpp @@ -38,13 +38,16 @@ static void gles1_unimplemented() { // any thread has been created - hence it should NOT be thread safe. // -#define DEFAULT_GLES_CM_LIB EMUGL_LIBNAME("GLES_CM_translator") +namespace { +constexpr const char *glesv1_lib_env_var{"ANBOX_GLESv1_LIB"}; +} -bool gles1_dispatch_init(GLESv1Dispatch* dispatch_table) { - const char* libName = getenv("ANDROID_GLESv1_LIB"); - if (!libName) { - libName = DEFAULT_GLES_CM_LIB; - } +bool gles1_dispatch_init(const char *path, GLESv1Dispatch* dispatch_table) { + const char* libName = getenv(glesv1_lib_env_var); + if (!libName) + libName = path; + if (!libName) + return false; char error[256]; s_gles1_lib = emugl::SharedLibrary::open(libName, error, sizeof(error)); @@ -67,6 +70,8 @@ bool gles1_dispatch_init(GLESv1Dispatch* dispatch_table) { LIST_GLES1_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_EXT_SYMBOL) + dispatch_table->initialized = true; + return true; } diff --git a/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv2Dispatch.cpp b/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv2Dispatch.cpp index 6bc0fa6..ec6b610 100644 --- a/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv2Dispatch.cpp +++ b/external/android-emugl/host/libs/libOpenGLESDispatch/GLESv2Dispatch.cpp @@ -25,7 +25,9 @@ extern EGLDispatch s_egl; static emugl::SharedLibrary *s_gles2_lib = NULL; -#define DEFAULT_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator") +namespace { +constexpr const char *glesv2_lib_env_var{"ANDROID_GLESv2_LIB"}; +} // An unimplemented function which prints out an error message. // To make it consistent with the guest, all GLES2 functions not supported by @@ -39,12 +41,13 @@ static void gles2_unimplemented() { // This function is called only once during initialiation before // any thread has been created - hence it should NOT be thread safe. // -bool gles2_dispatch_init(GLESv2Dispatch* dispatch_table) +bool gles2_dispatch_init(const char *path, GLESv2Dispatch *dispatch_table) { - const char *libName = getenv("ANDROID_GLESv2_LIB"); - if (!libName) { - libName = DEFAULT_GLES_V2_LIB; - } + const char *libName = getenv(glesv2_lib_env_var); + if (!libName) + libName = path; + if (!libName) + return false; char error[256]; s_gles2_lib = emugl::SharedLibrary::open(libName, error, sizeof(error)); @@ -67,6 +70,8 @@ bool gles2_dispatch_init(GLESv2Dispatch* dispatch_table) LIST_GLES2_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_EXT_SYMBOL) + dispatch_table->initialized = true; + return true; } diff --git a/src/anbox/cli.h b/src/anbox/cli.h index 500ef00..64b2951 100644 --- a/src/anbox/cli.h +++ b/src/anbox/cli.h @@ -71,7 +71,7 @@ std::ostream& operator<<(std::ostream& out, // We are imposing size constraints to ensure a consistent CLI layout. typedef SizeConstrainedString<20> Name; typedef SizeConstrainedString<60> Usage; -typedef SizeConstrainedString<60> Description; +typedef SizeConstrainedString<80> Description; /// @brief Flag models an input parameter to a command. class Flag : public DoNotCopyOrMove { diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index dc701db..64cd13e 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -63,6 +63,17 @@ class NullConnectionCreator : public anbox::network::ConnectionCreator< socket->close(); } }; + +std::istream& operator>>(std::istream& in, anbox::graphics::GLRendererServer::Config::Driver& driver) { + std::string str(std::istreambuf_iterator(in), {}); + if (str.empty() || str == "translator") + driver = anbox::graphics::GLRendererServer::Config::Driver::Translator; + else if (str == "host") + driver = anbox::graphics::GLRendererServer::Config::Driver::Host; + else + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid GLES driver value provided")); + return in; +} } anbox::cmds::Run::BusFactory anbox::cmds::Run::session_bus_factory() { @@ -81,6 +92,9 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory) flag(cli::make_flag(cli::Name{"desktop_file_hint"}, cli::Description{"Desktop file hint for QtMir/Unity8"}, desktop_file_hint_)); + flag(cli::make_flag(cli::Name{"gles-driver"}, + cli::Description{"Which GLES driver to use. Possible values are 'host' or'translator'"}, + gles_driver_)); action([this](const cli::Command::Context &) { auto trap = core::posix::trap_signals_for_process( @@ -119,8 +133,8 @@ anbox::cmds::Run::Run(const BusFactory &bus_factory) xdg::data().home() / "applications" / "anbox", xdg::data().home() / "anbox" / "icons"); - auto gl_server = - std::make_shared(window_manager); + auto gl_server = std::make_shared( + graphics::GLRendererServer::Config{gles_driver_}, window_manager); policy->set_renderer(gl_server->renderer()); diff --git a/src/anbox/cmds/run.h b/src/anbox/cmds/run.h index d0b3ec3..d9ddeae 100644 --- a/src/anbox/cmds/run.h +++ b/src/anbox/cmds/run.h @@ -26,6 +26,8 @@ #include +#include "anbox/graphics/gl_renderer_server.h" + namespace anbox { namespace cmds { class Run : public cli::CommandWithFlagsAndAction { @@ -39,6 +41,7 @@ class Run : public cli::CommandWithFlagsAndAction { private: BusFactory bus_factory_; std::string desktop_file_hint_; + graphics::GLRendererServer::Config::Driver gles_driver_; }; } // namespace cmds } // namespace anbox diff --git a/src/anbox/graphics/emugl/RenderApi.cpp b/src/anbox/graphics/emugl/RenderApi.cpp index 15db906..fb46083 100644 --- a/src/anbox/graphics/emugl/RenderApi.cpp +++ b/src/anbox/graphics/emugl/RenderApi.cpp @@ -30,19 +30,50 @@ GLESv2Dispatch s_gles2; GLESv1Dispatch s_gles1; +namespace { +constexpr const char *default_egl_lib{"libEGL.so.1"}; +constexpr const char *default_glesv1_lib{"libGLESv1_CM.so.1"}; +constexpr const char *default_glesv2_lib{"libGLESv2.so.2"}; +} + namespace anbox { namespace graphics { namespace emugl { -bool initialize(emugl_logger_struct log_funcs, emugl_crash_func_t crash_func) { +std::vector default_gl_libraries() { + return std::vector{ + {GLLibrary::Type::EGL, default_egl_lib}, + {GLLibrary::Type::GLESv1, default_glesv1_lib}, + {GLLibrary::Type::GLESv2, default_glesv2_lib}, + }; +} + +bool initialize(const std::vector &libs, emugl_logger_struct log_funcs, emugl_crash_func_t crash_func) { set_emugl_crash_reporter(crash_func); set_emugl_logger(log_funcs.coarse); set_emugl_cxt_logger(log_funcs.fine); - if (!init_egl_dispatch()) return false; + for (const auto &lib : libs) { + const auto path = lib.path.c_str(); + switch (lib.type) { + case GLLibrary::Type::EGL: + if (!init_egl_dispatch(path)) + return false; + break; + case GLLibrary::Type::GLESv1: + if (!gles1_dispatch_init(path, &s_gles1)) + return false; + break; + case GLLibrary::Type::GLESv2: + if (!gles2_dispatch_init(path, &s_gles2)) + return false; + break; + default: + break; + } + } - if (!gles1_dispatch_init(&s_gles1)) return false; - - if (!gles2_dispatch_init(&s_gles2)) return false; + if (!s_egl.initialized || !s_gles1.initialized || !s_gles2.initialized) + return false; return true; } diff --git a/src/anbox/graphics/emugl/RenderApi.h b/src/anbox/graphics/emugl/RenderApi.h index 8b6edbb..c5164d0 100644 --- a/src/anbox/graphics/emugl/RenderApi.h +++ b/src/anbox/graphics/emugl/RenderApi.h @@ -17,6 +17,10 @@ #ifndef RENDER_API_H #define RENDER_API_H +#include + +#include + typedef void (*emugl_logger_func_t)(const char* fmt, ...); typedef void (*emugl_crash_func_t)(const char* format, ...); @@ -28,7 +32,15 @@ typedef struct { namespace anbox { namespace graphics { namespace emugl { -bool initialize(emugl_logger_struct log_funcs, emugl_crash_func_t crash_func); +struct GLLibrary { + enum class Type { EGL, GLESv1, GLESv2 }; + Type type; + boost::filesystem::path path; +}; + +std::vector default_gl_libraries(); + +bool initialize(const std::vector &libs, emugl_logger_struct log_funcs, emugl_crash_func_t crash_func); } // namespace emugl } // namespace graphics } // namespace anbox diff --git a/src/anbox/graphics/gl_renderer_server.cpp b/src/anbox/graphics/gl_renderer_server.cpp index 54ead08..933ba77 100644 --- a/src/anbox/graphics/gl_renderer_server.cpp +++ b/src/anbox/graphics/gl_renderer_server.cpp @@ -24,6 +24,7 @@ #include "anbox/wm/manager.h" #include +#include #include #include @@ -42,39 +43,27 @@ void logger_write(const char *format, ...) { namespace anbox { namespace graphics { -GLRendererServer::GLRendererServer(const std::shared_ptr &wm) +GLRendererServer::GLRendererServer(const Config &config, const std::shared_ptr &wm) : renderer_(std::make_shared<::Renderer>()), 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); - ::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0); - ::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0); - } else { - auto translator_dir = - utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP"); - ::setenv( - "ANDROID_EGL_LIB", - utils::string_format("%s/libEGL_translator.so", translator_dir).c_str(), - 0); - ::setenv("ANDROID_GLESv1_LIB", - utils::string_format("%s/libGLES_CM_translator.so", translator_dir) - .c_str(), - 0); - ::setenv("ANDROID_GLESv2_LIB", - utils::string_format("%s/libGLES_V2_translator.so", translator_dir) - .c_str(), - 0); + + std::vector gl_libs = emugl::default_gl_libraries(); + + if (config.driver == Config::Driver::Translator) { + DEBUG("Using GLES-to-GL translator for rendering"); + boost::filesystem::path translator_dir = utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP"); + gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::EGL, (translator_dir / "libEGL_translator.so")}); + gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::GLESv1, (translator_dir / "libGLES_CM_translator.so")}); + gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::GLESv2, (translator_dir / "libGLES_V2_translator.so")}); } emugl_logger_struct log_funcs; log_funcs.coarse = logger_write; log_funcs.fine = logger_write; - if (!emugl::initialize(log_funcs, nullptr)) - BOOST_THROW_EXCEPTION( - std::runtime_error("Failed to initialize OpenGL renderer")); + if (!emugl::initialize(gl_libs, log_funcs, nullptr)) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); renderer_->initialize(0); diff --git a/src/anbox/graphics/gl_renderer_server.h b/src/anbox/graphics/gl_renderer_server.h index 096cbfc..f07e960 100644 --- a/src/anbox/graphics/gl_renderer_server.h +++ b/src/anbox/graphics/gl_renderer_server.h @@ -34,7 +34,12 @@ namespace graphics { class LayerComposer; class GLRendererServer { public: - GLRendererServer(const std::shared_ptr &wm); + struct Config { + enum class Driver { Translator, Host }; + Driver driver; + }; + + GLRendererServer(const Config &config, const std::shared_ptr &wm); ~GLRendererServer(); std::shared_ptr renderer() const { return renderer_; }