Merge branch 'master' into master

This commit is contained in:
Simon Fels 2018-05-16 08:06:05 +02:00 • committed by GitHub
commit 5a8e5e5817
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 279 additions and 149 deletions

View file

@ -5,8 +5,8 @@ include(CTest)
include(GNUInstallDirs) include(GNUInstallDirs)
if (NOT CMAKE_BUILD_TYPE) if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to release") message(STATUS "No build type selected, default to RelWithDebInfo")
set(CMAKE_BUILD_TYPE "release") set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif() endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

View file

@ -75,7 +75,7 @@ $ anbox-installer
This will guide you through the installation process. This will guide you through the installation process.
**NOTE:** Anbox is currently in a **pre-alpha development state**. Don't expect a **NOTE:** Anbox is currently in a **alpha development state**. Don't expect a
fully working system for a production system with all features you need. You will fully working system for a production system with all features you need. You will
for sure see bugs and crashes. If you do so, please don't hestitate and report them! for sure see bugs and crashes. If you do so, please don't hestitate and report them!

View file

@ -49,6 +49,7 @@ anbox::PlatformApiStub::WindowStateUpdate::Window PlatformService::unpack_window
auto frame_bottom = data.readInt32(); auto frame_bottom = data.readInt32();
auto task_id = data.readInt32(); auto task_id = data.readInt32();
auto stack_id = data.readInt32(); auto stack_id = data.readInt32();
auto rotation_angle = data.readInt32();
return anbox::PlatformApiStub::WindowStateUpdate::Window{ return anbox::PlatformApiStub::WindowStateUpdate::Window{
-1, // Display id will be added by the caller -1, // Display id will be added by the caller

2
debian/compat vendored
View file

@ -1 +1 @@
7 9

4
debian/control vendored
View file

@ -2,8 +2,8 @@ Source: anbox
Section: misc Section: misc
Priority: optional Priority: optional
Maintainer: Simon Fels <morphis@gravedo.de> Maintainer: Simon Fels <morphis@gravedo.de>
Build-Depends: debhelper (>= 7), dkms, dh-systemd Build-Depends: debhelper (>= 9), dkms, dh-systemd
Standards-Version: 3.9.7 Standards-Version: 4.1.3
Homepage: http://anbox.io Homepage: http://anbox.io
Vcs-Browser: https://github.com/anbox/anbox Vcs-Browser: https://github.com/anbox/anbox
Vcs-Git: https://github.com/anbox/anbox.git Vcs-Git: https://github.com/anbox/anbox.git

View file

@ -1048,8 +1048,10 @@ GL_APICALL void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params){
if (ctx->glGetIntegerv(pname,params)) if (ctx->glGetIntegerv(pname,params))
{ {
if (destroyCtx) if (destroyCtx)
{
deleteGLESContext(ctx); deleteGLESContext(ctx);
return; return;
}
} }
bool es2 = ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY; bool es2 = ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY;

View file

@ -753,6 +753,10 @@ int ApiGen::genDecoderHeader(const std::string &filename)
fprintf(fp, "#include \"IOStream.h\" \n"); fprintf(fp, "#include \"IOStream.h\" \n");
fprintf(fp, "#include \"%s_%s_context.h\"\n\n\n", m_basename.c_str(), sideString(SERVER_SIDE)); fprintf(fp, "#include \"%s_%s_context.h\"\n\n\n", m_basename.c_str(), sideString(SERVER_SIDE));
if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0) {
fprintf(fp, "\n#include <map>\n");
fprintf(fp, "\n#include <mutex>\n");
}
fprintf(fp, "\n#include \"emugl/common/logging.h\"\n"); fprintf(fp, "\n#include \"emugl/common/logging.h\"\n");
for (size_t i = 0; i < m_decoderHeaders.size(); i++) { for (size_t i = 0; i < m_decoderHeaders.size(); i++) {
@ -763,6 +767,17 @@ int ApiGen::genDecoderHeader(const std::string &filename)
fprintf(fp, "struct %s : public %s_%s_context_t {\n\n", fprintf(fp, "struct %s : public %s_%s_context_t {\n\n",
classname.c_str(), m_basename.c_str(), sideString(SERVER_SIDE)); classname.c_str(), m_basename.c_str(), sideString(SERVER_SIDE));
fprintf(fp, "\tsize_t decode(void *buf, size_t bufsize, IOStream *stream);\n"); fprintf(fp, "\tsize_t decode(void *buf, size_t bufsize, IOStream *stream);\n");
if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0){
fprintf(fp,
"\tvoid freeShader(); \n\
\tvoid freeProgram(); \n\
\tstd::map<GLuint, GLuint> m_programs; \n\
\tstd::map<GLuint, GLuint> m_shaders; \n\
\tstd::mutex m_lock; \n\
");
}
fprintf(fp, "\n};\n\n"); fprintf(fp, "\n};\n\n");
fprintf(fp, "#endif // GUARD_%s\n", classname.c_str()); fprintf(fp, "#endif // GUARD_%s\n", classname.c_str());
@ -835,6 +850,35 @@ int ApiGen::genDecoderImpl(const std::string &filename)
// helper templates // helper templates
fprintf(fp, "using namespace emugl;\n\n"); fprintf(fp, "using namespace emugl;\n\n");
// glsl shader/program free;
if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0) {
fprintf(fp, "void %s::freeShader(){\n", classname.c_str());
fprintf(fp,
" \n\
\tauto it = m_shaders.begin();\n\
\tm_lock.lock();\n\
\twhile(it != m_shaders.end()) \n\
\t{\n\
\t\tthis->glDeleteShader(it->first);\n\
\t\tit++;\n\
\t}\n\
\tm_lock.unlock();\n\
}\n\n");
fprintf(fp, "void %s::freeProgram(){\n", classname.c_str());
fprintf(fp,
" \n\
\tauto it = m_programs.begin(); \n\
\tm_lock.lock();\n\
\twhile(it != m_programs.end()) \n\
\t{\n\
\t\tthis->glDeleteProgram(it->first);\n\
\t\tit++;\n\
\t}\n\
\tm_lock.unlock();\n\
}\n\n");
}
// decoder switch; // decoder switch;
fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str()); fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str());
fprintf(fp, fprintf(fp,
@ -1114,8 +1158,7 @@ int ApiGen::genDecoderImpl(const std::string &filename)
varoffset.c_str(), varoffset.c_str(),
varoffset.c_str(), varoffset.c_str(),
varoffset.c_str(), varoffset.c_str(),
classname.c_str(), classname.c_str()
e->name().c_str()
); );
varoffset += " + 4"; varoffset += " + 4";
@ -1161,6 +1204,37 @@ int ApiGen::genDecoderImpl(const std::string &filename)
} // pass; } // pass;
fprintf(fp, "\t\t\tSET_LASTCALL(\"%s\");\n", e->name().c_str()); fprintf(fp, "\t\t\tSET_LASTCALL(\"%s\");\n", e->name().c_str());
if (strcmp(m_basename.c_str(), "gles2") == 0) {
if (strcmp(e->name().c_str(), "glAttachShader") == 0){
fprintf(fp, "\n\
\t\t\tm_lock.lock();\n\
m_shaders.insert({var_shader, 1});\n\
m_lock.unlock();\n");
} else if(strcmp(e->name().c_str(), "glDeleteProgram") == 0){
fprintf(fp,
"\t\t\tm_lock.lock(); \n"
"\t\t\tauto pro = m_programs.find(var_program); \n"
"\t\t\tif (pro != m_programs.end()) \n"
"\t\t\t{ \n"
"\t\t\t\tm_programs.erase(pro); \n"
"\t\t\t}\n"
"\t\t\tm_lock.unlock();\n");
} else if(strcmp(e->name().c_str(), "glDeleteShader") == 0){
fprintf(fp,
"\t\t\tm_lock.lock(); \n\
\t\t\tauto shader = m_shaders.find(var_shader); \n\
\t\t\tif (shader != m_shaders.end()) \n\
\t\t\t{ \n\
\t\t\t\tm_shaders.erase(shader); \n\
\t\t\t} \n\
\t\t\tm_lock.unlock(); \n");
} else if(strcmp(e->name().c_str(), "glLinkProgram") == 0){
fprintf(fp, " \n\
\t\t\tm_lock.lock();\n\
\t\t\tm_programs.insert({var_program, 1});\n\
\t\t\tm_lock.unlock();\n");
}
}
fprintf(fp, "\t\t\tbreak;\n"); fprintf(fp, "\t\t\tbreak;\n");
fprintf(fp, "\t\t}\n"); fprintf(fp, "\t\t}\n");

View file

@ -99,7 +99,7 @@ bool EntryPoint::parse(unsigned int lc, const std::string & str)
std::string vartype, varname; std::string vartype, varname;
if (!parseParameterDeclaration(field, &vartype, &varname, &error)) { if (!parseParameterDeclaration(field, &vartype, &varname, &error)) {
fprintf(stderr, fprintf(stderr,
"line: %d: Parsing error in field <%s>\n", "line: %d: Parsing error in field <%s>, error: %s\n",
lc, lc,
field.c_str(), field.c_str(),
error.c_str()); error.c_str());

View file

@ -204,7 +204,7 @@ private:
} }
std::shared_ptr<core::posix::SignalTrap> core::posix::trap_signals_for_process( std::shared_ptr<core::posix::SignalTrap> core::posix::trap_signals_for_process(
std::initializer_list<core::posix::Signal> blocked_signals) std::initializer_list<core::posix::Signal> blocked_signals)
{ {
return std::make_shared<impl::SignalTrap>( return std::make_shared<impl::SignalTrap>(
impl::SignalTrap::Scope::process, impl::SignalTrap::Scope::process,

View file

@ -312,8 +312,14 @@ static ssize_t ashmem_read(struct file *file, char __user *buf,
* once asma->file is set it will never be changed, and will not * once asma->file is set it will never be changed, and will not
* be destroyed until all references to the file are dropped and * be destroyed until all references to the file are dropped and
* ashmem_release is called. * ashmem_release is called.
*
* kernel_read supersedes vfs_read from kernel version 3.9
*/ */
ret = __vfs_read(asma->file, buf, len, pos); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
ret = __vfs_read(asma->file, buf, len, pos);
#else
ret = kernel_read(asma->file, buf, len, pos);
#endif
if (ret >= 0) if (ret >= 0)
/** Update backing file pos, since f_ops->read() doesn't */ /** Update backing file pos, since f_ops->read() doesn't */
asma->file->f_pos = *pos; asma->file->f_pos = *pos;

View file

@ -137,7 +137,11 @@ static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
static int binder_stop_on_user_error; static int binder_stop_on_user_error;
static int binder_set_stop_on_user_error(const char *val, static int binder_set_stop_on_user_error(const char *val,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
const struct kernel_param *kp)
#else
struct kernel_param *kp) struct kernel_param *kp)
#endif
{ {
int ret; int ret;

View file

@ -56,8 +56,8 @@ cleanup
mkdir build || rm -rf build/* mkdir build || rm -rf build/*
cd build cd build
cmake .. cmake ..
make -j10 VERBOSE=1 make -j10
make test VERBOSE=1 make test
cd .. cd ..
cleanup cleanup

View file

@ -25,6 +25,7 @@
# #
# Anything else is an error. # Anything else is an error.
from __future__ import print_function
import re import re
import sys import sys
import argparse import argparse
@ -32,6 +33,9 @@ import argparse
re_func = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)\((.*)\);$""") re_func = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)\((.*)\);$""")
re_param = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)$""") re_param = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)$""")
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
class Entry: class Entry:
"""Small class used to model a single DLL entry point.""" """Small class used to model a single DLL entry point."""
def __init__(self, func_name, return_type, parameters): def __init__(self, func_name, return_type, parameters):
@ -128,28 +132,28 @@ def gen_functions_header(entries, prefix_name, verbatim, filename, with_args):
""" """
prefix_name = prefix_name.upper() prefix_name = prefix_name.upper()
print "// Auto-generated with: %s" % banner_command(sys.argv) print("// Auto-generated with: %s" % banner_command(sys.argv))
print "// DO NOT EDIT THIS FILE" print("// DO NOT EDIT THIS FILE")
print "" print("")
print "#ifndef %s_FUNCTIONS_H" % prefix_name print("#ifndef %s_FUNCTIONS_H" % prefix_name)
print "#define %s_FUNCTIONS_H" % prefix_name print("#define %s_FUNCTIONS_H" % prefix_name)
print "" print("")
for line in verbatim: for line in verbatim:
print line print(line)
print "#define LIST_%s_FUNCTIONS(X) \\" % prefix_name print("#define LIST_%s_FUNCTIONS(X) \\" % prefix_name)
for entry in entries: for entry in entries:
if with_args: if with_args:
print " X(%s, %s, (%s), (%s)) \\" % \ print(" X(%s, %s, (%s), (%s)) \\" % \
(entry.return_type, entry.func_name, entry.parameters, (entry.return_type, entry.func_name, entry.parameters,
entry.call) entry.call))
else: else:
print " X(%s, %s, (%s)) \\" % \ print(" X(%s, %s, (%s)) \\" % \
(entry.return_type, entry.func_name, entry.parameters) (entry.return_type, entry.func_name, entry.parameters))
print "" print("")
print "" print("")
print "#endif // %s_FUNCTIONS_H" % prefix_name print("#endif // %s_FUNCTIONS_H" % prefix_name)
@ -199,10 +203,10 @@ def gen_translator(entries):
"glProgramUniform3ui": 1, "glProgramUniform3ui": 1,
"glProgramUniform4ui": 1, "glProgramUniform4ui": 1,
"glBindVertexBuffer": 1, "glBindVertexBuffer": 1,
}; }
translator_nocontext_fail_codes = { translator_nocontext_fail_codes = {
"glClientWaitSync" : "GL_WAIT_FAILED", "glClientWaitSync" : "GL_WAIT_FAILED",
}; }
def needExternC(entry): def needExternC(entry):
if translator_needexternc.has_key(entry.func_name): if translator_needexternc.has_key(entry.func_name):
return "extern \"C\" " return "extern \"C\" "
@ -210,14 +214,14 @@ def gen_translator(entries):
return "" return ""
def get_fail_code(entry): def get_fail_code(entry):
if translator_nocontext_fail_codes.has_key(entry.func_name): if translator_nocontext_fail_codes.has_key(entry.func_name):
return translator_nocontext_fail_codes[entry.func_name]; return translator_nocontext_fail_codes[entry.func_name]
else: else:
return "0" return "0"
def gen_cxt_getter(entry): def gen_cxt_getter(entry):
if (entry.return_type == "void"): if (entry.return_type == "void"):
print " GET_CTX_V2();" print(" GET_CTX_V2();")
else: else:
print " GET_CTX_V2_RET(%s);" % get_fail_code(entry) print(" GET_CTX_V2_RET(%s);" % get_fail_code(entry))
def gen_validations_custom_impl(entry): def gen_validations_custom_impl(entry):
isGen = entry.func_name.startswith("glGen") isGen = entry.func_name.startswith("glGen")
@ -231,14 +235,14 @@ def gen_translator(entries):
if entry.return_type == "void": if entry.return_type == "void":
return "SET_ERROR_IF(%s,%s)" % (condition, glerr); return "SET_ERROR_IF(%s,%s)" % (condition, glerr);
else: else:
return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry)); return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry))
if (isGen or isDelete) and ("n" in entry.varnames): if (isGen or isDelete) and ("n" in entry.varnames):
print " %s;" % mySetError("n < 0", "GL_INVALID_VALUE"); print(" %s;" % mySetError("n < 0", "GL_INVALID_VALUE"))
if (isBufferOp and hasTargetArg): if (isBufferOp and hasTargetArg):
print " %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM"); print(" %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM"))
if translator_custom_pre.has_key(entry.func_name): if translator_custom_pre.has_key(entry.func_name):
print translator_custom_pre[entry.func_name], print(translator_custom_pre[entry.func_name],)
def gen_call_ret(entry): def gen_call_ret(entry):
globalNameTypes = { globalNameTypes = {
@ -262,53 +266,53 @@ def gen_translator(entries):
needsShareGroup = True needsShareGroup = True
if needsShareGroup: if needsShareGroup:
print " if (ctx->shareGroup().get()) {" print(" if (ctx->shareGroup().get()) {")
for key in zip(entry.vartypes, entry.varnames): for key in zip(entry.vartypes, entry.varnames):
vartype, varname = key vartype, varname = key
if globalNames.has_key(key): if globalNames.has_key(key):
print " const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname) print(" const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname))
globalCall = ", ".join(map(lambda k: globalNames.get(k, k[1]), zip(entry.vartypes, entry.varnames))) globalCall = ", ".join(map(lambda k: globalNames.get(k, k[1]), zip(entry.vartypes, entry.varnames)))
if needsShareGroup and translator_custom_share_processing.has_key(entry.func_name): if needsShareGroup and translator_custom_share_processing.has_key(entry.func_name):
print translator_custom_share_processing[entry.func_name], print(translator_custom_share_processing[entry.func_name])
if (entry.return_type == "void"): if (entry.return_type == "void"):
if (needsShareGroup): if (needsShareGroup):
print " ", print(" "),
if not translator_no_passthrough.has_key(entry.func_name): if not translator_no_passthrough.has_key(entry.func_name):
print " ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall) print(" ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall))
if needsShareGroup: if needsShareGroup:
print " }" print(" }")
if translator_custom_post.has_key(entry.func_name): if translator_custom_post.has_key(entry.func_name):
print translator_custom_post[entry.func_name]; print(translator_custom_post[entry.func_name])
else: else:
if (needsShareGroup): if (needsShareGroup):
print " ", print(" "),
if not translator_no_passthrough.has_key(entry.func_name): if not translator_no_passthrough.has_key(entry.func_name):
print " %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall) print(" %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall))
else: else:
print " %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry)) print(") %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry)))
if translator_custom_post.has_key(entry.func_name): if translator_custom_post.has_key(entry.func_name):
print translator_custom_post[entry.func_name]; print(translator_custom_post[entry.func_name])
print " return %s;" % (entry.func_name + "RET"); print(" return %s;" % (entry.func_name + "RET"))
if needsShareGroup: if needsShareGroup:
print " } else return %s;" % (get_fail_code(entry)) print(" } else return %s;" % (get_fail_code(entry)))
print "// Auto-generated with: %s" % banner_command(sys.argv) print("// Auto-generated with: %s" % banner_command(sys.argv))
print "// This file is best left unedited." print("// This file is best left unedited.")
print "// Try to make changes through gen_translator in gen-entries.py," print("// Try to make changes through gen_translator in gen-entries.py,")
print "// and/or parcel out custom functionality in separate code." print("// and/or parcel out custom functionality in separate code.")
for entry in entries: for entry in entries:
print "%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters) print("%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters))
gen_cxt_getter(entry); gen_cxt_getter(entry)
gen_validations_custom_impl(entry); gen_validations_custom_impl(entry)
gen_call_ret(entry); gen_call_ret(entry)
print "}\n" print("}\n")
def gen_dll_wrapper(entries, prefix_name, verbatim, filename): def gen_dll_wrapper(entries, prefix_name, verbatim, filename):
"""Generate a C source file that contains functions that act as wrappers """Generate a C source file that contains functions that act as wrappers
@ -322,77 +326,77 @@ def gen_dll_wrapper(entries, prefix_name, verbatim, filename):
ENTRY_PREFIX = "__dll_" ENTRY_PREFIX = "__dll_"
print "// Auto-generated with: %s" % banner_command(sys.argv) print("// Auto-generated with: %s" % banner_command(sys.argv))
print "// DO NOT EDIT THIS FILE" print("// DO NOT EDIT THIS FILE")
print "" print("")
print "#include <dlfcn.h>" print("#include <dlfcn.h>")
for line in verbatim: for line in verbatim:
print line print(line)
print "" print("")
print "///" print("///")
print "/// W R A P P E R P O I N T E R S" print("/// W R A P P E R P O I N T E R S")
print "///" print("///")
print "" print("")
for entry in entries: for entry in entries:
ptr_name = ENTRY_PREFIX + entry.func_name ptr_name = ENTRY_PREFIX + entry.func_name
print "static %s (*%s)(%s) = 0;" % \ print("static %s (*%s)(%s) = 0;" % \
(entry.return_type, ptr_name, entry.parameters) (entry.return_type, ptr_name, entry.parameters))
print "" print("")
print "///" print("///")
print "/// W R A P P E R F U N C T I O N S" print("/// W R A P P E R F U N C T I O N S")
print "///" print("///")
print "" print("")
for entry in entries: for entry in entries:
print "%s %s(%s) {" % \ print ("%s %s(%s) {" % \
(entry.return_type, entry.func_name, entry.parameters) (entry.return_type, entry.func_name, entry.parameters))
ptr_name = ENTRY_PREFIX + entry.func_name ptr_name = ENTRY_PREFIX + entry.func_name
if entry.return_type != "void": if entry.return_type != "void":
print " return %s(%s);" % (ptr_name, entry.call) print(" return %s(%s);" % (ptr_name, entry.call))
else: else:
print " %s(%s);" % (ptr_name, entry.call) print(" %s(%s);" % (ptr_name, entry.call))
print "}\n" print("}\n")
print "" print("")
print "///" print("///")
print "/// I N I T I A L I Z A T I O N F U N C T I O N" print("/// I N I T I A L I Z A T I O N F U N C T I O N")
print "///" print("///")
print "" print("")
print "int %s_dynlink_init(void* lib) {" % prefix_name print("int %s_dynlink_init(void* lib) {" % prefix_name)
for entry in entries: for entry in entries:
ptr_name = ENTRY_PREFIX + entry.func_name ptr_name = ENTRY_PREFIX + entry.func_name
print " %s = (%s(*)(%s))dlsym(lib, \"%s\");" % \ print(" %s = (%s(*)(%s))dlsym(lib, \"%s\");" % \
(ptr_name, (ptr_name,
entry.return_type, entry.return_type,
entry.parameters, entry.parameters,
entry.func_name) entry.func_name))
print " if (!%s) return -1;" % ptr_name print(" if (!%s) return -1;" % ptr_name)
print " return 0;" print(" return 0;")
print "}" print("}")
def gen_windows_def_file(entries): def gen_windows_def_file(entries):
"""Generate a windows DLL .def file. |entries| is a list of Entry instances. """Generate a windows DLL .def file. |entries| is a list of Entry instances.
""" """
print "EXPORTS" print("EXPORTS")
for entry in entries: for entry in entries:
print " %s" % entry.func_name print(" %s" % entry.func_name)
def gen_unix_sym_file(entries): def gen_unix_sym_file(entries):
"""Generate an ELF linker version file. |entries| is a list of Entry """Generate an ELF linker version file. |entries| is a list of Entry
instances. instances.
""" """
print "VERSION {" print("VERSION {")
print "\tglobal:" print("\tglobal:")
for entry in entries: for entry in entries:
print "\t\t%s;" % entry.func_name print("\t\t%s;" % entry.func_name)
print "\tlocal:" print("\tlocal:")
print "\t\t*;" print("\t\t*;")
print "};" print("};")
def gen_symbols(entries, underscore): def gen_symbols(entries, underscore):
"""Generate a list of symbols from |entries|, a list of Entry instances. """Generate a list of symbols from |entries|, a list of Entry instances.
@ -403,7 +407,7 @@ def gen_symbols(entries, underscore):
if underscore: if underscore:
prefix = "_" prefix = "_"
for entry in entries: for entry in entries:
print "%s%s" % (prefix, entry.func_name) print("%s%s" % (prefix, entry.func_name))
def parse_file(filename, lines, mode): def parse_file(filename, lines, mode):
"""Generate one of possible outputs from |filename|. |lines| must be a list """Generate one of possible outputs from |filename|. |lines| must be a list
@ -413,7 +417,7 @@ def parse_file(filename, lines, mode):
entries, prefix_name, verbatim, errors = parse_entries_file(lines) entries, prefix_name, verbatim, errors = parse_entries_file(lines)
if errors: if errors:
for error in errors: for error in errors:
print >> sys.stderr, "ERROR: %s:%s" % (filename, error) eprint("ERROR: %s:%s" % (filename, error), file=sys.stderr)
sys.exit(1) sys.exit(1)
if not prefix_name: if not prefix_name:
@ -466,7 +470,7 @@ parser.add_argument("file", help=".entries file path")
args = parser.parse_args() args = parser.parse_args()
if not args.mode: if not args.mode:
print >> sys.stderr, "ERROR: Please use --mode=<name>, see --help." eprint("ERROR: Please use --mode=<name>, see --help.", file=sys.stderr)
sys.exit(1) sys.exit(1)
if args.output: if args.output:

View file

@ -35,6 +35,11 @@ export LD_LIBRARY_PATH="$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH"
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192 # Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl
# With recent builds on Ubuntu 16.04 the snap does not find the path to
# libpulsecommon-8.0.so anymore so we have to teach the linker manually
# where it can be found
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP/usr/lib/$ARCH/pulseaudio
# We set XDG_DATA_HOME to SNAP_USER_COMMON here as this will be the location we will # We set XDG_DATA_HOME to SNAP_USER_COMMON here as this will be the location we will
# create all our application launchers in. The system application launcher will # create all our application launchers in. The system application launcher will
# be configured by our installer to look into this directory for available # be configured by our installer to look into this directory for available

View file

@ -176,7 +176,7 @@ anbox::cmds::SessionManager::SessionManager()
input_manager, input_manager,
display_frame, display_frame,
single_window_); single_window_);
if (!platform) if (!platform)
return EXIT_FAILURE; return EXIT_FAILURE;
auto app_db = std::make_shared<application::Database>(); auto app_db = std::make_shared<application::Database>();

View file

@ -24,6 +24,9 @@
namespace anbox { namespace anbox {
namespace container { namespace container {
const std::chrono::milliseconds ManagementApiStub::stop_waiting_timeout{3000};
ManagementApiStub::ManagementApiStub( ManagementApiStub::ManagementApiStub(
const std::shared_ptr<rpc::Channel> &channel) const std::shared_ptr<rpc::Channel> &channel)
: channel_(channel) {} : channel_(channel) {}
@ -75,7 +78,9 @@ void ManagementApiStub::stop_container() {
channel_->call_method("stop_container", &message, c->response.get(), channel_->call_method("stop_container", &message, c->response.get(),
google::protobuf::NewCallback(this, &ManagementApiStub::container_stopped, c.get())); google::protobuf::NewCallback(this, &ManagementApiStub::container_stopped, c.get()));
c->wh.wait_for_all(); // If container manager dies before session manager, the session manager
// cannot exit if it waits for all, so just wait for 3 seconds.
c->wh.wait_for_pending(stop_waiting_timeout);
if (c->response->has_error()) throw std::runtime_error(c->response->error()); if (c->response->has_error()) throw std::runtime_error(c->response->error());
} }

View file

@ -56,6 +56,7 @@ class ManagementApiStub : public DoNotCopyOrMove {
mutable std::mutex mutex_; mutable std::mutex mutex_;
std::shared_ptr<rpc::Channel> channel_; std::shared_ptr<rpc::Channel> channel_;
static const std::chrono::milliseconds stop_waiting_timeout;
}; };
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

View file

@ -26,9 +26,9 @@
#include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h" #include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h" #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
#include <map> #include <map>
#include <string> #include <string>
#include <sstream>
static const GLint rendererVersion = 1; static const GLint rendererVersion = 1;
static std::shared_ptr<anbox::graphics::LayerComposer> composer; static std::shared_ptr<anbox::graphics::LayerComposer> composer;
@ -55,53 +55,61 @@ static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) {
return EGL_TRUE; return EGL_TRUE;
} }
static EGLint rcQueryEGLString(EGLenum name, void *buffer, EGLint bufferSize) { static std::string filter_extensions(const std::string& extensions, const std::vector<std::string>& whitelist) {
std::stringstream approved_extensions;
auto extension_list = anbox::utils::string_split(extensions, ' ');
for (const auto& ext : extension_list) {
if (std::find(whitelist.begin(), whitelist.end(), ext) == whitelist.end())
continue;
if (approved_extensions.tellp() > 0)
approved_extensions << " ";
approved_extensions << ext;
}
return approved_extensions.str();
}
static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) {
if (!renderer) if (!renderer)
return 0; return 0;
auto result = s_egl.eglQueryString(renderer->getDisplay(), name); std::string result = s_egl.eglQueryString(renderer->getDisplay(), name);
if (!result) if (result.empty())
return 0; return 0;
std::string approved_result = result;
// We need to drop a few extensions from the list reported by the driver
// as not all are well enough support by our EGL/GLES stack.
if (name == EGL_EXTENSIONS) { if (name == EGL_EXTENSIONS) {
std::vector<std::string> common_unsupported_extensions = { // We need to drop a few extensions from the list reported by the driver
// Leads to crashes on the Android side when SurfaceFlinger initializes // as not all are well enough support by our EGL implementation.
// EGL/GLES and it queries surfaces for available attributes. std::vector<std::string> whitelisted_extensions = {
"EGL_EXT_buffer_age" "EGL_KHR_image_base",
"EGL_KHR_gl_texture_2D_image",
}; };
result = filter_extensions(result, whitelisted_extensions);
for (const auto &extension : common_unsupported_extensions) {
size_t start_pos = approved_result.find(extension);
if (start_pos == std::string::npos) continue;
approved_result.replace(start_pos, extension.length(), "");
}
} }
int len = approved_result.length() + 1; int len = result.length() + 1;
if (!buffer || len > bufferSize) { if (!buffer || len > bufferSize) {
return -len; return -len;
} }
strcpy(static_cast<char *>(buffer), approved_result.c_str()); strcpy(static_cast<char*>(buffer), result.c_str());
return len; return len;
} }
static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) { static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
RenderThreadInfo *tInfo = RenderThreadInfo::get(); RenderThreadInfo* tInfo = RenderThreadInfo::get();
std::string result; std::string result;
if (tInfo && tInfo->currContext) { if (tInfo && tInfo->currContext) {
const char *str = nullptr; const char* str = nullptr;
if (tInfo->currContext->isGL2()) if (tInfo->currContext->isGL2())
str = reinterpret_cast<const char *>(s_gles2.glGetString(name)); str = reinterpret_cast<const char*>(s_gles2.glGetString(name));
else else
str = reinterpret_cast<const char *>(s_gles1.glGetString(name)); str = reinterpret_cast<const char*>(s_gles1.glGetString(name));
if (str) result += str; if (str)
result += str;
} }
// We're forcing version 2.0 no matter what the host provides as // We're forcing version 2.0 no matter what the host provides as
@ -113,27 +121,37 @@ static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) {
if (name == GL_VERSION) if (name == GL_VERSION)
result = "OpenGL ES 2.0"; result = "OpenGL ES 2.0";
else if (name == GL_EXTENSIONS) { else if (name == GL_EXTENSIONS) {
std::string approved_extensions = result; // We need to drop a few extensions from the list reported by the driver
std::vector<std::string> unsupported_extensions = { // as not all are well enough support by our GL implementation.
// Leaving this enabled gives crippeled text rendering when std::vector<std::string> whitelisted_extensions = {
// using the host mesa GLES drivers. "GL_OES_EGL_image",
"GL_EXT_unpack_subimage", "GL_OES_EGL_image_external",
"GL_OES_depth24",
"GL_OES_depth32",
"GL_OES_element_index_uint",
"GL_OES_texture_float",
"GL_OES_texture_float_linear",
"GL_OES_compressed_paletted_texture",
"GL_OES_compressed_ETC1_RGB8_texture",
"GL_OES_depth_texture",
"GL_OES_texture_half_float",
"GL_OES_texture_half_float_linear",
"GL_OES_packed_depth_stencil",
"GL_OES_vertex_half_float",
"GL_OES_standard_derivatives",
"GL_OES_texture_npot",
"GL_OES_rgb8_rgba8",
}; };
for (const auto &extension : unsupported_extensions) { result = filter_extensions(result, whitelisted_extensions);
size_t start_pos = approved_extensions.find(extension);
if (start_pos == std::string::npos) continue;
approved_extensions.replace(start_pos, extension.length(), "");
}
result = approved_extensions;
} }
int nextBufferSize = result.size() + 1; int nextBufferSize = result.size() + 1;
if (!buffer || nextBufferSize > bufferSize) return -nextBufferSize; if (!buffer || nextBufferSize > bufferSize)
return -nextBufferSize;
snprintf(static_cast<char *>(buffer), nextBufferSize, "%s", result.c_str()); snprintf(static_cast<char*>(buffer), nextBufferSize, "%s", result.c_str());
return nextBufferSize; return nextBufferSize;
} }

View file

@ -84,8 +84,12 @@ intptr_t RenderThread::main() {
} }
} while (progress); } while (progress);
} }
threadInfo.m_gl2Dec.freeShader();
threadInfo.m_gl2Dec.freeProgram();
// Release references to the current thread's context/surfaces if any // Release references to the current thread's context/surfaces if any
renderer_->bindContext(0, 0, 0); renderer_->bindContext(0, 0, 0);
if (threadInfo.currContext || threadInfo.currDrawSurf || threadInfo.currReadSurf) if (threadInfo.currContext || threadInfo.currDrawSurf || threadInfo.currReadSurf)

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define GLM_ENABLE_EXPERIMENTAL
#include "anbox/graphics/emugl/Renderer.h" #include "anbox/graphics/emugl/Renderer.h"
#include "anbox/graphics/emugl/DispatchTables.h" #include "anbox/graphics/emugl/DispatchTables.h"
#include "anbox/graphics/emugl/RenderThreadInfo.h" #include "anbox/graphics/emugl/RenderThreadInfo.h"

View file

@ -138,7 +138,7 @@ unsigned short BaseSocketMessenger<stream_protocol>::local_port() const {
template <typename stream_protocol> template <typename stream_protocol>
void BaseSocketMessenger<stream_protocol>::set_no_delay() { void BaseSocketMessenger<stream_protocol>::set_no_delay() {
const auto fd = socket->native(); const auto fd = socket->native_handle();
int flag = 1; int flag = 1;
const auto ret = const auto ret =
::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,

View file

@ -51,7 +51,6 @@ void QemudMessageProcessor::process_commands() {
unsigned int body_size = 0; unsigned int body_size = 0;
::sscanf(header, "%04x", &body_size); ::sscanf(header, "%04x", &body_size);
if (body_size != buffer_.size() - header_size) break;
std::string command; std::string command;
// Make sure we only copy as much bytes as we have to and not more // Make sure we only copy as much bytes as we have to and not more
@ -71,7 +70,7 @@ void QemudMessageProcessor::process_commands() {
void QemudMessageProcessor::send_header(const size_t &size) { void QemudMessageProcessor::send_header(const size_t &size) {
char header[header_size + 1]; char header[header_size + 1];
std::snprintf(header, header_size + 1, "%04lx", size); std::snprintf(header, header_size + 1, "%04zx", size);
messenger_->send(header, header_size); messenger_->send(header, header_size);
} }

View file

@ -53,7 +53,13 @@ std::shared_ptr<Runtime> Runtime::create(std::uint32_t pool_size) {
Runtime::Runtime(std::uint32_t pool_size) Runtime::Runtime(std::uint32_t pool_size)
: pool_size_{pool_size}, : pool_size_{pool_size},
#if BOOST_VERSION >= 106600
service_{static_cast<int>(pool_size_)},
#else
service_{pool_size_}, service_{pool_size_},
#endif
strand_{service_}, strand_{service_},
keep_alive_{service_} {} keep_alive_{service_} {}

View file

@ -19,6 +19,7 @@
#define ANBOX_RUNTIME_H_ #define ANBOX_RUNTIME_H_
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/version.hpp>
#include <memory.h> #include <memory.h>
#include <functional> #include <functional>