Merge pull request #31 from morphis/feature/better-gles-selector
Abstract selector of translator or host GL libs a bit more
This commit is contained in:
commit
928ebdba5a
13 changed files with 130 additions and 57 deletions
|
|
@ -42,12 +42,13 @@ LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DEFINE_TYPE)
|
||||||
|
|
||||||
// Define EGLDispatch structure.
|
// Define EGLDispatch structure.
|
||||||
struct EGLDispatch {
|
struct EGLDispatch {
|
||||||
|
bool initialized = false;
|
||||||
LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
|
LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
|
||||||
LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
|
LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_DECLARE_MEMBER)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize EGLDispatch function. Return true on success, false on failure.
|
// 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.
|
// Global EGLDispatch instance. Call init_egl_dispatch() before using it.
|
||||||
extern EGLDispatch s_egl;
|
extern EGLDispatch s_egl;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE,GLES1_DISPATCH_DEFINE_TYPE)
|
LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DEFINE_TYPE,GLES1_DISPATCH_DEFINE_TYPE)
|
||||||
|
|
||||||
struct GLESv1Dispatch {
|
struct GLESv1Dispatch {
|
||||||
|
bool initialized = false;
|
||||||
#define GLES1_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
|
#define GLES1_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
|
||||||
func_name ## _t func_name;
|
func_name ## _t func_name;
|
||||||
LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER,
|
LIST_GLES1_FUNCTIONS(GLES1_DISPATCH_DECLARE_POINTER,
|
||||||
|
|
@ -35,7 +36,7 @@ struct GLESv1Dispatch {
|
||||||
#undef GLES1_DISPATCH_DECLARE_POINTER
|
#undef GLES1_DISPATCH_DECLARE_POINTER
|
||||||
#undef GLES1_DISPATCH_DEFINE_TYPE
|
#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.
|
// Used to initialize the decoder.
|
||||||
void* gles1_dispatch_get_proc_func(const char* name, void* userData);
|
void* gles1_dispatch_get_proc_func(const char* name, void* userData);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DEFINE_TYPE,GLES2_DISPATCH_DEFINE_TYPE)
|
LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DEFINE_TYPE,GLES2_DISPATCH_DEFINE_TYPE)
|
||||||
|
|
||||||
struct GLESv2Dispatch {
|
struct GLESv2Dispatch {
|
||||||
|
bool initialized = false;
|
||||||
#define GLES2_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
|
#define GLES2_DISPATCH_DECLARE_POINTER(return_type,func_name,signature,callargs) \
|
||||||
func_name ## _t func_name;
|
func_name ## _t func_name;
|
||||||
LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DECLARE_POINTER,
|
LIST_GLES2_FUNCTIONS(GLES2_DISPATCH_DECLARE_POINTER,
|
||||||
|
|
@ -35,7 +36,7 @@ struct GLESv2Dispatch {
|
||||||
#undef GLES2_DISPATCH_DECLARE_POINTER
|
#undef GLES2_DISPATCH_DECLARE_POINTER
|
||||||
#undef GLES2_DISPATCH_DEFINE_TYPE
|
#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.
|
// Used to initialize the decoder.
|
||||||
void* gles2_dispatch_get_proc_func(const char* name, void* userData);
|
void* gles2_dispatch_get_proc_func(const char* name, void* userData);
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
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) \
|
#define RENDER_EGL_LOAD_FIELD(return_type, function_name, signature) \
|
||||||
s_egl. function_name = (function_name ## _t) lib->findSymbol(#function_name);
|
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) \
|
if (!s_egl.function_name || !s_egl.eglGetProcAddress) \
|
||||||
RENDER_EGL_LOAD_FIELD(return_type, function_name, signature)
|
RENDER_EGL_LOAD_FIELD(return_type, function_name, signature)
|
||||||
|
|
||||||
bool init_egl_dispatch()
|
bool init_egl_dispatch(const char *path) {
|
||||||
{
|
const char *libName = getenv(egl_lib_env_var);
|
||||||
|
if (!libName)
|
||||||
const char *libName = getenv("ANDROID_EGL_LIB");
|
libName = path;
|
||||||
if (!libName) libName = DEFAULT_EGL_LIB;
|
if (!libName)
|
||||||
|
return false;
|
||||||
|
|
||||||
char error[256];
|
char error[256];
|
||||||
emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
|
emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
|
||||||
if (!lib) {
|
if (!lib) {
|
||||||
printf("Failed to open %s: [%s]\n", libName, error);
|
printf("Failed to open %s: [%s]\n", libName, error);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_LOAD_FIELD)
|
LIST_RENDER_EGL_FUNCTIONS(RENDER_EGL_LOAD_FIELD)
|
||||||
LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_LOAD_OPTIONAL_FIELD)
|
LIST_RENDER_EGL_EXTENSIONS_FUNCTIONS(RENDER_EGL_LOAD_OPTIONAL_FIELD)
|
||||||
|
|
||||||
|
s_egl.initialized = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,16 @@ static void gles1_unimplemented() {
|
||||||
// any thread has been created - hence it should NOT be thread safe.
|
// 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) {
|
bool gles1_dispatch_init(const char *path, GLESv1Dispatch* dispatch_table) {
|
||||||
const char* libName = getenv("ANDROID_GLESv1_LIB");
|
const char* libName = getenv(glesv1_lib_env_var);
|
||||||
if (!libName) {
|
if (!libName)
|
||||||
libName = DEFAULT_GLES_CM_LIB;
|
libName = path;
|
||||||
}
|
if (!libName)
|
||||||
|
return false;
|
||||||
|
|
||||||
char error[256];
|
char error[256];
|
||||||
s_gles1_lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
|
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)
|
LIST_GLES1_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_EXT_SYMBOL)
|
||||||
|
|
||||||
|
dispatch_table->initialized = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ extern EGLDispatch s_egl;
|
||||||
|
|
||||||
static emugl::SharedLibrary *s_gles2_lib = NULL;
|
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.
|
// An unimplemented function which prints out an error message.
|
||||||
// To make it consistent with the guest, all GLES2 functions not supported by
|
// 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
|
// This function is called only once during initialiation before
|
||||||
// any thread has been created - hence it should NOT be thread safe.
|
// 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");
|
const char *libName = getenv(glesv2_lib_env_var);
|
||||||
if (!libName) {
|
if (!libName)
|
||||||
libName = DEFAULT_GLES_V2_LIB;
|
libName = path;
|
||||||
}
|
if (!libName)
|
||||||
|
return false;
|
||||||
|
|
||||||
char error[256];
|
char error[256];
|
||||||
s_gles2_lib = emugl::SharedLibrary::open(libName, error, sizeof(error));
|
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)
|
LIST_GLES2_FUNCTIONS(LOOKUP_SYMBOL,LOOKUP_EXT_SYMBOL)
|
||||||
|
|
||||||
|
dispatch_table->initialized = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ std::ostream& operator<<(std::ostream& out,
|
||||||
// We are imposing size constraints to ensure a consistent CLI layout.
|
// We are imposing size constraints to ensure a consistent CLI layout.
|
||||||
typedef SizeConstrainedString<20> Name;
|
typedef SizeConstrainedString<20> Name;
|
||||||
typedef SizeConstrainedString<60> Usage;
|
typedef SizeConstrainedString<60> Usage;
|
||||||
typedef SizeConstrainedString<60> Description;
|
typedef SizeConstrainedString<80> Description;
|
||||||
|
|
||||||
/// @brief Flag models an input parameter to a command.
|
/// @brief Flag models an input parameter to a command.
|
||||||
class Flag : public DoNotCopyOrMove {
|
class Flag : public DoNotCopyOrMove {
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,17 @@ class NullConnectionCreator : public anbox::network::ConnectionCreator<
|
||||||
socket->close();
|
socket->close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, anbox::graphics::GLRendererServer::Config::Driver& driver) {
|
||||||
|
std::string str(std::istreambuf_iterator<char>(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() {
|
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"},
|
flag(cli::make_flag(cli::Name{"desktop_file_hint"},
|
||||||
cli::Description{"Desktop file hint for QtMir/Unity8"},
|
cli::Description{"Desktop file hint for QtMir/Unity8"},
|
||||||
desktop_file_hint_));
|
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 &) {
|
action([this](const cli::Command::Context &) {
|
||||||
auto trap = core::posix::trap_signals_for_process(
|
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() / "applications" / "anbox",
|
||||||
xdg::data().home() / "anbox" / "icons");
|
xdg::data().home() / "anbox" / "icons");
|
||||||
|
|
||||||
auto gl_server =
|
auto gl_server = std::make_shared<graphics::GLRendererServer>(
|
||||||
std::make_shared<graphics::GLRendererServer>(window_manager);
|
graphics::GLRendererServer::Config{gles_driver_}, window_manager);
|
||||||
|
|
||||||
policy->set_renderer(gl_server->renderer());
|
policy->set_renderer(gl_server->renderer());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include <core/dbus/bus.h>
|
#include <core/dbus/bus.h>
|
||||||
|
|
||||||
|
#include "anbox/graphics/gl_renderer_server.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace cmds {
|
namespace cmds {
|
||||||
class Run : public cli::CommandWithFlagsAndAction {
|
class Run : public cli::CommandWithFlagsAndAction {
|
||||||
|
|
@ -39,6 +41,7 @@ class Run : public cli::CommandWithFlagsAndAction {
|
||||||
private:
|
private:
|
||||||
BusFactory bus_factory_;
|
BusFactory bus_factory_;
|
||||||
std::string desktop_file_hint_;
|
std::string desktop_file_hint_;
|
||||||
|
graphics::GLRendererServer::Config::Driver gles_driver_;
|
||||||
};
|
};
|
||||||
} // namespace cmds
|
} // namespace cmds
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,50 @@
|
||||||
GLESv2Dispatch s_gles2;
|
GLESv2Dispatch s_gles2;
|
||||||
GLESv1Dispatch s_gles1;
|
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 anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace emugl {
|
namespace emugl {
|
||||||
bool initialize(emugl_logger_struct log_funcs, emugl_crash_func_t crash_func) {
|
std::vector<GLLibrary> default_gl_libraries() {
|
||||||
|
return std::vector<GLLibrary>{
|
||||||
|
{GLLibrary::Type::EGL, default_egl_lib},
|
||||||
|
{GLLibrary::Type::GLESv1, default_glesv1_lib},
|
||||||
|
{GLLibrary::Type::GLESv2, default_glesv2_lib},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialize(const std::vector<GLLibrary> &libs, emugl_logger_struct log_funcs, emugl_crash_func_t crash_func) {
|
||||||
set_emugl_crash_reporter(crash_func);
|
set_emugl_crash_reporter(crash_func);
|
||||||
set_emugl_logger(log_funcs.coarse);
|
set_emugl_logger(log_funcs.coarse);
|
||||||
set_emugl_cxt_logger(log_funcs.fine);
|
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 (!s_egl.initialized || !s_gles1.initialized || !s_gles2.initialized)
|
||||||
|
return false;
|
||||||
if (!gles2_dispatch_init(&s_gles2)) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@
|
||||||
#ifndef RENDER_API_H
|
#ifndef RENDER_API_H
|
||||||
#define RENDER_API_H
|
#define RENDER_API_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
typedef void (*emugl_logger_func_t)(const char* fmt, ...);
|
typedef void (*emugl_logger_func_t)(const char* fmt, ...);
|
||||||
typedef void (*emugl_crash_func_t)(const char* format, ...);
|
typedef void (*emugl_crash_func_t)(const char* format, ...);
|
||||||
|
|
||||||
|
|
@ -28,7 +32,15 @@ typedef struct {
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
namespace emugl {
|
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<GLLibrary> default_gl_libraries();
|
||||||
|
|
||||||
|
bool initialize(const std::vector<GLLibrary> &libs, emugl_logger_struct log_funcs, emugl_crash_func_t crash_func);
|
||||||
} // namespace emugl
|
} // namespace emugl
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "anbox/wm/manager.h"
|
#include "anbox/wm/manager.h"
|
||||||
|
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -42,39 +43,27 @@ void logger_write(const char *format, ...) {
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm)
|
GLRendererServer::GLRendererServer(const Config &config, const std::shared_ptr<wm::Manager> &wm)
|
||||||
: renderer_(std::make_shared<::Renderer>()),
|
: renderer_(std::make_shared<::Renderer>()),
|
||||||
wm_(wm),
|
wm_(wm),
|
||||||
composer_(std::make_shared<LayerComposer>(renderer_, 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
|
std::vector<emugl::GLLibrary> gl_libs = emugl::default_gl_libraries();
|
||||||
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0);
|
|
||||||
::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0);
|
if (config.driver == Config::Driver::Translator) {
|
||||||
::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0);
|
DEBUG("Using GLES-to-GL translator for rendering");
|
||||||
} else {
|
boost::filesystem::path translator_dir = utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP");
|
||||||
auto translator_dir =
|
gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::EGL, (translator_dir / "libEGL_translator.so")});
|
||||||
utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP");
|
gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::GLESv1, (translator_dir / "libGLES_CM_translator.so")});
|
||||||
::setenv(
|
gl_libs.push_back(emugl::GLLibrary{emugl::GLLibrary::Type::GLESv2, (translator_dir / "libGLES_V2_translator.so")});
|
||||||
"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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emugl_logger_struct log_funcs;
|
emugl_logger_struct log_funcs;
|
||||||
log_funcs.coarse = logger_write;
|
log_funcs.coarse = logger_write;
|
||||||
log_funcs.fine = logger_write;
|
log_funcs.fine = logger_write;
|
||||||
|
|
||||||
if (!emugl::initialize(log_funcs, nullptr))
|
if (!emugl::initialize(gl_libs, log_funcs, nullptr))
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer"));
|
||||||
std::runtime_error("Failed to initialize OpenGL renderer"));
|
|
||||||
|
|
||||||
renderer_->initialize(0);
|
renderer_->initialize(0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,12 @@ namespace graphics {
|
||||||
class LayerComposer;
|
class LayerComposer;
|
||||||
class GLRendererServer {
|
class GLRendererServer {
|
||||||
public:
|
public:
|
||||||
GLRendererServer(const std::shared_ptr<wm::Manager> &wm);
|
struct Config {
|
||||||
|
enum class Driver { Translator, Host };
|
||||||
|
Driver driver;
|
||||||
|
};
|
||||||
|
|
||||||
|
GLRendererServer(const Config &config, const std::shared_ptr<wm::Manager> &wm);
|
||||||
~GLRendererServer();
|
~GLRendererServer();
|
||||||
|
|
||||||
std::shared_ptr<Renderer> renderer() const { return renderer_; }
|
std::shared_ptr<Renderer> renderer() const { return renderer_; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue