Merge pull request #8 from morphis/reformat

Reformat all code and use the Google cpp code style
This commit is contained in:
Simon Fels 2016-12-02 17:44:36 +01:00 • committed by GitHub
commit 7d9330f205
222 changed files with 8739 additions and 9281 deletions

8
.clang-format Normal file
View file

@ -0,0 +1,8 @@
# Defines the Chromium style for automatic reformatting.
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: Google
# This defaults to 'Auto'. Explicitly set it for a while, so that
# 'vector<vector<int> >' in existing files gets formatted to
# 'vector<vector<int>>'. ('Auto' means that clang-format will only use
# 'int>>' if the file already contains at least one such instance.)
Standard: Cpp11

3
scripts/clean-format.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
find src -name "*.h" | xargs clang-format -style=file -i
find src -name "*.cpp" | xargs clang-format -style=file -i

View file

@ -21,8 +21,7 @@
namespace anbox { namespace anbox {
namespace android { namespace android {
std::ostream& operator<<(std::ostream &out, const Intent &intent) std::ostream &operator<<(std::ostream &out, const Intent &intent) {
{
out << "[" out << "["
<< "action=" << intent.action << " " << "action=" << intent.action << " "
<< "uri=" << intent.uri << " " << "uri=" << intent.uri << " "
@ -31,11 +30,9 @@ std::ostream& operator<<(std::ostream &out, const Intent &intent)
<< "package=" << intent.package << " " << "package=" << intent.package << " "
<< "component=" << intent.component << " " << "component=" << intent.component << " "
<< "categories=[ "; << "categories=[ ";
for (const auto &category : intent.categories) for (const auto &category : intent.categories) out << category << " ";
out << category << " ";
out << "]]"; out << "]]";
return out; return out;
} }
} // namespace android } // namespace android
} // namespace anbox } // namespace anbox

View file

@ -37,5 +37,4 @@ std::ostream& operator<<(std::ostream &out, const Intent &intent);
} // namespace android } // namespace android
} // namespace anbox } // namespace anbox
#endif #endif

View file

@ -19,28 +19,25 @@
#include "anbox/utils.h" #include "anbox/utils.h"
#include <algorithm> #include <algorithm>
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace anbox { namespace anbox {
namespace application { namespace application {
LauncherStorage::LauncherStorage(const fs::path &path) : LauncherStorage::LauncherStorage(const fs::path &path) : path_(path) {}
path_(path) {
}
LauncherStorage::~LauncherStorage() { LauncherStorage::~LauncherStorage() {}
}
void LauncherStorage::add(const Item &item) { void LauncherStorage::add(const Item &item) {
if (!fs::exists(path_)) if (!fs::exists(path_)) fs::create_directories(path_);
fs::create_directories(path_);
auto package_name = item.package; auto package_name = item.package;
std::replace(package_name.begin(), package_name.end(), '.', '-'); std::replace(package_name.begin(), package_name.end(), '.', '-');
const auto item_path = path_ / utils::string_format("anbox-%s.desktop", package_name); const auto item_path =
path_ / utils::string_format("anbox-%s.desktop", package_name);
std::string exec = "anbox launch "; std::string exec = "anbox launch ";
if (!item.launch_intent.action.empty()) if (!item.launch_intent.action.empty())
@ -56,7 +53,8 @@ void LauncherStorage::add(const Item &item) {
exec += utils::string_format("--package=%s ", item.launch_intent.package); exec += utils::string_format("--package=%s ", item.launch_intent.package);
if (!item.launch_intent.component.empty()) if (!item.launch_intent.component.empty())
exec += utils::string_format("--component=%s ", item.launch_intent.component); exec +=
utils::string_format("--component=%s ", item.launch_intent.component);
std::ofstream f(item_path.string()); std::ofstream f(item_path.string());
f << "[Desktop Entry]" << std::endl f << "[Desktop Entry]" << std::endl

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_APPLICATION_MANAGER_H_ #ifndef ANBOX_APPLICATION_MANAGER_H_
#define ANBOX_APPLICATION_MANAGER_H_ #define ANBOX_APPLICATION_MANAGER_H_
#include "anbox/do_not_copy_or_move.h"
#include "anbox/android/intent.h" #include "anbox/android/intent.h"
#include "anbox/do_not_copy_or_move.h"
#include <string> #include <string>

View file

@ -16,13 +16,13 @@
*/ */
#include "anbox/bridge/android_api_stub.h" #include "anbox/bridge/android_api_stub.h"
#include "anbox/rpc/channel.h"
#include "anbox/utils.h"
#include "anbox/config.h" #include "anbox/config.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/rpc/channel.h"
#include "anbox/utils.h"
#include "anbox_rpc.pb.h"
#include "anbox_bridge.pb.h" #include "anbox_bridge.pb.h"
#include "anbox_rpc.pb.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -30,23 +30,19 @@ namespace fs = boost::filesystem;
namespace anbox { namespace anbox {
namespace bridge { namespace bridge {
AndroidApiStub::AndroidApiStub() { AndroidApiStub::AndroidApiStub() {}
}
AndroidApiStub::~AndroidApiStub() { AndroidApiStub::~AndroidApiStub() {}
}
void AndroidApiStub::set_rpc_channel(const std::shared_ptr<rpc::Channel> &channel) { void AndroidApiStub::set_rpc_channel(
const std::shared_ptr<rpc::Channel> &channel) {
channel_ = channel; channel_ = channel;
} }
void AndroidApiStub::reset_rpc_channel() { void AndroidApiStub::reset_rpc_channel() { channel_.reset(); }
channel_.reset();
}
void AndroidApiStub::ensure_rpc_channel() { void AndroidApiStub::ensure_rpc_channel() {
if (!channel_) if (!channel_) throw std::runtime_error("No remote client connected");
throw std::runtime_error("No remote client connected");
} }
void AndroidApiStub::launch(const android::Intent &intent) { void AndroidApiStub::launch(const android::Intent &intent) {
@ -62,38 +58,33 @@ void AndroidApiStub::launch(const android::Intent &intent) {
auto launch_intent = message.mutable_intent(); auto launch_intent = message.mutable_intent();
if (!intent.action.empty()) if (!intent.action.empty()) launch_intent->set_action(intent.action);
launch_intent->set_action(intent.action);
if (!intent.uri.empty()) if (!intent.uri.empty()) launch_intent->set_uri(intent.uri);
launch_intent->set_uri(intent.uri);
if (!intent.type.empty()) if (!intent.type.empty()) launch_intent->set_type(intent.type);
launch_intent->set_type(intent.type);
if (!intent.package.empty()) if (!intent.package.empty()) launch_intent->set_package(intent.package);
launch_intent->set_package(intent.package);
if (!intent.component.empty()) if (!intent.component.empty()) launch_intent->set_component(intent.component);
launch_intent->set_component(intent.component);
for (const auto &category : intent.categories) { for (const auto &category : intent.categories) {
auto c = launch_intent->add_categories(); auto c = launch_intent->add_categories();
*c = category; *c = category;
} }
channel_->call_method("launch_application", channel_->call_method(
&message, "launch_application", &message, c->response.get(),
c->response.get(), google::protobuf::NewCallback(this, &AndroidApiStub::application_launched,
google::protobuf::NewCallback(this, &AndroidApiStub::application_launched, c.get())); c.get()));
launch_wait_handle_.wait_for_all(); launch_wait_handle_.wait_for_all();
if (c->response->has_error()) if (c->response->has_error()) throw std::runtime_error(c->response->error());
throw std::runtime_error(c->response->error());
} }
void AndroidApiStub::application_launched(Request<protobuf::rpc::Void> *request) { void AndroidApiStub::application_launched(
Request<protobuf::rpc::Void> *request) {
(void)request; (void)request;
launch_wait_handle_.result_received(); launch_wait_handle_.result_received();
} }
@ -111,15 +102,13 @@ void AndroidApiStub::set_focused_task(const std::int32_t &id) {
set_focused_task_handle_.expect_result(); set_focused_task_handle_.expect_result();
} }
channel_->call_method("set_focused_task", channel_->call_method("set_focused_task", &message, c->response.get(),
&message, google::protobuf::NewCallback(
c->response.get(), this, &AndroidApiStub::focused_task_set, c.get()));
google::protobuf::NewCallback(this, &AndroidApiStub::focused_task_set, c.get()));
set_focused_task_handle_.wait_for_all(); set_focused_task_handle_.wait_for_all();
if (c->response->has_error()) if (c->response->has_error()) throw std::runtime_error(c->response->error());
throw std::runtime_error(c->response->error());
} }
void AndroidApiStub::focused_task_set(Request<protobuf::rpc::Void> *request) { void AndroidApiStub::focused_task_set(Request<protobuf::rpc::Void> *request) {

View file

@ -17,40 +17,41 @@
#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/bridge/platform_api_skeleton.h"
#include "anbox/application/launcher_storage.h" #include "anbox/application/launcher_storage.h"
#include "anbox/logger.h"
#include "anbox/wm/manager.h" #include "anbox/wm/manager.h"
#include "anbox/wm/window_state.h" #include "anbox/wm/window_state.h"
#include "anbox/logger.h"
#include "anbox_bridge.pb.h" #include "anbox_bridge.pb.h"
namespace anbox { namespace anbox {
namespace bridge { namespace bridge {
PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls, PlatformApiSkeleton::PlatformApiSkeleton(
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<wm::Manager> &window_manager, const std::shared_ptr<wm::Manager> &window_manager,
const std::shared_ptr<application::LauncherStorage> &launcher_storage) : const std::shared_ptr<application::LauncherStorage> &launcher_storage)
pending_calls_(pending_calls), : pending_calls_(pending_calls),
window_manager_(window_manager), window_manager_(window_manager),
launcher_storage_(launcher_storage) { launcher_storage_(launcher_storage) {}
}
PlatformApiSkeleton::~PlatformApiSkeleton() { PlatformApiSkeleton::~PlatformApiSkeleton() {}
}
void PlatformApiSkeleton::handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event) { void PlatformApiSkeleton::handle_boot_finished_event(
const anbox::protobuf::bridge::BootFinishedEvent &event) {
(void)event; (void)event;
if (boot_finished_handler_) if (boot_finished_handler_) boot_finished_handler_();
boot_finished_handler_();
} }
void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event) { void PlatformApiSkeleton::handle_window_state_update_event(
auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState &window) { const anbox::protobuf::bridge::WindowStateUpdateEvent &event) {
auto convert_window_state = [](
const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState
&window) {
return wm::WindowState( return wm::WindowState(
wm::Display::Id(window.display_id()), wm::Display::Id(window.display_id()), window.has_surface(),
window.has_surface(), graphics::Rect(window.frame_left(), window.frame_top(),
graphics::Rect(window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom()), window.frame_right(), window.frame_bottom()),
window.package_name(), window.package_name(), wm::Task::Id(window.task_id()),
wm::Task::Id(window.task_id()),
wm::Stack::Id(window.stack_id())); wm::Stack::Id(window.stack_id()));
}; };
@ -69,7 +70,8 @@ void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf
window_manager_->apply_window_state_update(updated, removed); window_manager_->apply_window_state_update(updated, removed);
} }
void PlatformApiSkeleton::handle_application_list_update_event(const anbox::protobuf::bridge::ApplicationListUpdateEvent &event) { void PlatformApiSkeleton::handle_application_list_update_event(
const anbox::protobuf::bridge::ApplicationListUpdateEvent &event) {
for (int n = 0; n < event.applications_size(); n++) { for (int n = 0; n < event.applications_size(); n++) {
application::LauncherStorage::Item item; application::LauncherStorage::Item item;
@ -92,7 +94,8 @@ void PlatformApiSkeleton::handle_application_list_update_event(const anbox::prot
} }
} }
void PlatformApiSkeleton::register_boot_finished_handler(const std::function<void()> &action) { void PlatformApiSkeleton::register_boot_finished_handler(
const std::function<void()> &action) {
boot_finished_handler_ = action; boot_finished_handler_ = action;
} }
} // namespace bridge } // namespace bridge

View file

@ -49,14 +49,18 @@ class LauncherStorage;
namespace bridge { namespace bridge {
class PlatformApiSkeleton { class PlatformApiSkeleton {
public: public:
PlatformApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls, PlatformApiSkeleton(
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<wm::Manager> &window_manager, const std::shared_ptr<wm::Manager> &window_manager,
const std::shared_ptr<application::LauncherStorage> &launcher_storage); const std::shared_ptr<application::LauncherStorage> &launcher_storage);
virtual ~PlatformApiSkeleton(); virtual ~PlatformApiSkeleton();
void handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event); void handle_boot_finished_event(
void handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event); const anbox::protobuf::bridge::BootFinishedEvent &event);
void handle_application_list_update_event(const anbox::protobuf::bridge::ApplicationListUpdateEvent &event); void handle_window_state_update_event(
const anbox::protobuf::bridge::WindowStateUpdateEvent &event);
void handle_application_list_update_event(
const anbox::protobuf::bridge::ApplicationListUpdateEvent &event);
void register_boot_finished_handler(const std::function<void()> &action); void register_boot_finished_handler(const std::function<void()> &action);

View file

@ -17,27 +17,25 @@
#include "anbox/bridge/platform_message_processor.h" #include "anbox/bridge/platform_message_processor.h"
#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/bridge/platform_api_skeleton.h"
#include "anbox/rpc/template_message_processor.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/rpc/template_message_processor.h"
#include "anbox_bridge.pb.h" #include "anbox_bridge.pb.h"
namespace anbox { namespace anbox {
namespace bridge { namespace bridge {
PlatformMessageProcessor::PlatformMessageProcessor(const std::shared_ptr<network::MessageSender> &sender, PlatformMessageProcessor::PlatformMessageProcessor(
const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PlatformApiSkeleton> &server, const std::shared_ptr<PlatformApiSkeleton> &server,
const std::shared_ptr<rpc::PendingCallCache> &pending_calls) : const std::shared_ptr<rpc::PendingCallCache> &pending_calls)
rpc::MessageProcessor(sender, pending_calls), : rpc::MessageProcessor(sender, pending_calls), server_(server) {}
server_(server) {
}
PlatformMessageProcessor::~PlatformMessageProcessor() { PlatformMessageProcessor::~PlatformMessageProcessor() {}
}
void PlatformMessageProcessor::dispatch(rpc::Invocation const& invocation) { void PlatformMessageProcessor::dispatch(rpc::Invocation const &invocation) {}
}
void PlatformMessageProcessor::process_event_sequence(const std::string &raw_events) { void PlatformMessageProcessor::process_event_sequence(
const std::string &raw_events) {
anbox::protobuf::bridge::EventSequence seq; anbox::protobuf::bridge::EventSequence seq;
if (!seq.ParseFromString(raw_events)) { if (!seq.ParseFromString(raw_events)) {
WARNING("Failed to parse events from raw string"); WARNING("Failed to parse events from raw string");
@ -51,7 +49,8 @@ void PlatformMessageProcessor::process_event_sequence(const std::string &raw_eve
server_->handle_window_state_update_event(seq.window_state_update()); server_->handle_window_state_update_event(seq.window_state_update());
if (seq.has_application_list_update()) if (seq.has_application_list_update())
server_->handle_application_list_update_event(seq.application_list_update()); server_->handle_application_list_update_event(
seq.application_list_update());
} }
} // namespace anbox } // namespace anbox
} // namespace network } // namespace network

View file

@ -25,7 +25,8 @@ namespace bridge {
class PlatformApiSkeleton; class PlatformApiSkeleton;
class PlatformMessageProcessor : public rpc::MessageProcessor { class PlatformMessageProcessor : public rpc::MessageProcessor {
public: public:
PlatformMessageProcessor(const std::shared_ptr<network::MessageSender> &sender, PlatformMessageProcessor(
const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<PlatformApiSkeleton> &server, const std::shared_ptr<PlatformApiSkeleton> &server,
const std::shared_ptr<rpc::PendingCallCache> &pending_calls); const std::shared_ptr<rpc::PendingCallCache> &pending_calls);
~PlatformMessageProcessor(); ~PlatformMessageProcessor();

View file

@ -41,125 +41,98 @@ static constexpr const char* options = "OPTIONS:";
static constexpr const char* option = " --%1% %2%"; static constexpr const char* option = " --%1% %2%";
} }
void add_to_desc_for_flags(po::options_description& desc, const std::set<cli::Flag::Ptr>& flags) void add_to_desc_for_flags(po::options_description& desc,
{ const std::set<cli::Flag::Ptr>& flags) {
for (auto flag : flags) for (auto flag : flags) {
{ auto v = po::value<std::string>()->notifier(
auto v = po::value<std::string>()->notifier([flag](const std::string& s) [flag](const std::string& s) { flag->notify(s); });
{ desc.add_options()(flag->name().as_string().c_str(), v,
flag->notify(s); flag->description().as_string().c_str());
});
desc.add_options()(flag->name().as_string().c_str(), v, flag->description().as_string().c_str());
} }
} }
} }
std::vector<std::string> cli::args(int argc, char **argv) std::vector<std::string> cli::args(int argc, char** argv) {
{
std::vector<std::string> result; std::vector<std::string> result;
for (int i = 1; i < argc; i++) result.push_back(argv[i]); for (int i = 1; i < argc; i++) result.push_back(argv[i]);
return result; return result;
} }
const cli::Name& cli::Flag::name() const const cli::Name& cli::Flag::name() const { return name_; }
{
return name_;
}
const cli::Description& cli::Flag::description() const const cli::Description& cli::Flag::description() const { return description_; }
{
return description_;
}
cli::Flag::Flag(const Name& name, const Description& description) cli::Flag::Flag(const Name& name, const Description& description)
: name_{name}, : name_{name}, description_{description} {}
description_{description}
{
}
cli::Command::FlagsWithInvalidValue::FlagsWithInvalidValue() : std::runtime_error{"Flags with invalid value"} cli::Command::FlagsWithInvalidValue::FlagsWithInvalidValue()
{ : std::runtime_error{"Flags with invalid value"} {}
}
cli::Command::FlagsMissing::FlagsMissing() : std::runtime_error{"Flags are missing in command invocation"} cli::Command::FlagsMissing::FlagsMissing()
{ : std::runtime_error{"Flags are missing in command invocation"} {}
}
cli::Name cli::Command::name() const cli::Name cli::Command::name() const { return name_; }
{
return name_;
}
cli::Usage cli::Command::usage() const cli::Usage cli::Command::usage() const { return usage_; }
{
return usage_;
}
cli::Description cli::Command::description() const cli::Description cli::Command::description() const { return description_; }
{
return description_;
}
cli::Command::Command(const cli::Name& name, const cli::Usage& usage, const cli::Description& description) cli::Command::Command(const cli::Name& name, const cli::Usage& usage,
: name_(name), const cli::Description& description)
usage_(usage), : name_(name), usage_(usage), description_(description) {}
description_(description)
{
}
cli::CommandWithSubcommands::CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description) cli::CommandWithSubcommands::CommandWithSubcommands(
: Command{name, usage, description} const Name& name, const Usage& usage, const Description& description)
{ : Command{name, usage, description} {
command(std::make_shared<cmd::Help>(*this)); command(std::make_shared<cmd::Help>(*this));
} }
cli::CommandWithSubcommands& cli::CommandWithSubcommands::command(const Command::Ptr& command) cli::CommandWithSubcommands& cli::CommandWithSubcommands::command(
{ const Command::Ptr& command) {
commands_[command->name().as_string()] = command; commands_[command->name().as_string()] = command;
return *this; return *this;
} }
cli::CommandWithSubcommands& cli::CommandWithSubcommands::flag(const Flag::Ptr& flag) cli::CommandWithSubcommands& cli::CommandWithSubcommands::flag(
{ const Flag::Ptr& flag) {
flags_.insert(flag); flags_.insert(flag);
return *this; return *this;
} }
void cli::CommandWithSubcommands::help(std::ostream& out) void cli::CommandWithSubcommands::help(std::ostream& out) {
{ out << boost::format(pattern::help_for_command_with_subcommands) %
out << boost::format(pattern::help_for_command_with_subcommands) name().as_string() % usage().as_string() % name().as_string()
% name().as_string() % usage().as_string() << std::endl;
% name().as_string() << std::endl;
if (flags_.size() > 0) if (flags_.size() > 0) {
{
out << std::endl << pattern::options << std::endl; out << std::endl << pattern::options << std::endl;
for (const auto& flag : flags_) for (const auto& flag : flags_)
out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl; out << boost::format(pattern::option) % flag->name() % flag->description()
<< std::endl;
} }
if (commands_.size() > 0) if (commands_.size() > 0) {
{
out << std::endl << pattern::commands << std::endl; out << std::endl << pattern::commands << std::endl;
for (const auto& cmd : commands_) { for (const auto& cmd : commands_) {
if (cmd.second) if (cmd.second)
out << boost::format(pattern::command) % cmd.second->name() % cmd.second->description() << std::endl; out << boost::format(pattern::command) % cmd.second->name() %
cmd.second->description()
<< std::endl;
} }
} }
} }
int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt) int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt) {
{
po::positional_options_description pdesc; po::positional_options_description pdesc;
pdesc.add("command", 1); pdesc.add("command", 1);
po::options_description desc("Options"); po::options_description desc("Options");
desc.add_options()("command", po::value<std::string>()->required(), "the command to be executed"); desc.add_options()("command", po::value<std::string>()->required(),
"the command to be executed");
add_to_desc_for_flags(desc, flags_); add_to_desc_for_flags(desc, flags_);
try try {
{
po::variables_map vm; po::variables_map vm;
auto parsed = po::command_line_parser(ctxt.args) auto parsed = po::command_line_parser(ctxt.args)
.options(desc) .options(desc)
@ -172,22 +145,17 @@ int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt)
po::notify(vm); po::notify(vm);
auto cmd = commands_[vm["command"].as<std::string>()]; auto cmd = commands_[vm["command"].as<std::string>()];
if (!cmd) if (!cmd) {
{ ctxt.cout << "Unknown command '" << vm["command"].as<std::string>() << "'"
ctxt.cout << "Unknown command '" << vm["command"].as<std::string>() << "'" << std::endl; << std::endl;
help(ctxt.cout); help(ctxt.cout);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
return cmd->run(cli::Command::Context return cmd->run(cli::Command::Context{
{ ctxt.cin, ctxt.cout,
ctxt.cin, po::collect_unrecognized(parsed.options, po::include_positional)});
ctxt.cout, } catch (const po::error& e) {
po::collect_unrecognized(parsed.options, po::include_positional)
});
}
catch (const po::error& e)
{
ctxt.cout << e.what() << std::endl; ctxt.cout << e.what() << std::endl;
help(ctxt.cout); help(ctxt.cout);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -196,54 +164,50 @@ int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
cli::CommandWithFlagsAndAction::CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description) cli::CommandWithFlagsAndAction::CommandWithFlagsAndAction(
: Command{name, usage, description} const Name& name, const Usage& usage, const Description& description)
{ : Command{name, usage, description} {}
}
cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::flag(const Flag::Ptr& flag) cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::flag(
{ const Flag::Ptr& flag) {
flags_.insert(flag); flags_.insert(flag);
return *this; return *this;
} }
cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::action(const Action& action) cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::action(
{ const Action& action) {
action_ = action; action_ = action;
return *this; return *this;
} }
int cli::CommandWithFlagsAndAction::run(const Context& ctxt) int cli::CommandWithFlagsAndAction::run(const Context& ctxt) {
{
po::options_description cd(name().as_string()); po::options_description cd(name().as_string());
bool help_requested{false}; bool help_requested{false};
cd.add_options()("help", po::bool_switch(&help_requested), "produces a help message"); cd.add_options()("help", po::bool_switch(&help_requested),
"produces a help message");
add_to_desc_for_flags(cd, flags_); add_to_desc_for_flags(cd, flags_);
try try {
{
po::variables_map vm; po::variables_map vm;
auto parsed = po::command_line_parser(ctxt.args).options(cd).style(po::command_line_style::unix_style).allow_unregistered().run(); auto parsed = po::command_line_parser(ctxt.args)
.options(cd)
.style(po::command_line_style::unix_style)
.allow_unregistered()
.run();
po::store(parsed, vm); po::store(parsed, vm);
po::notify(vm); po::notify(vm);
if (help_requested) if (help_requested) {
{
help(ctxt.cout); help(ctxt.cout);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
return action_(cli::Command::Context return action_(cli::Command::Context{
{ ctxt.cin, ctxt.cout,
ctxt.cin, po::collect_unrecognized(parsed.options, po::exclude_positional)});
ctxt.cout, } catch (const po::error& e) {
po::collect_unrecognized(parsed.options, po::exclude_positional)
});
}
catch (const po::error& e)
{
ctxt.cout << e.what() << std::endl; ctxt.cout << e.what() << std::endl;
help(ctxt.cout); help(ctxt.cout);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -252,34 +216,28 @@ int cli::CommandWithFlagsAndAction::run(const Context& ctxt)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
void cli::CommandWithFlagsAndAction::help(std::ostream& out) void cli::CommandWithFlagsAndAction::help(std::ostream& out) {
{ out << boost::format(pattern::help_for_command_with_subcommands) %
out << boost::format(pattern::help_for_command_with_subcommands) name().as_string() % description().as_string() % name().as_string()
% name().as_string() % description().as_string() << std::endl;
% name().as_string() << std::endl;
if (flags_.size() > 0) if (flags_.size() > 0) {
{
out << std::endl << boost::format(pattern::options) << std::endl; out << std::endl << boost::format(pattern::options) << std::endl;
for (const auto& flag : flags_) for (const auto& flag : flags_)
out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl; out << boost::format(pattern::option) % flag->name() % flag->description()
<< std::endl;
} }
} }
cli::cmd::Help::Help(Command& cmd) cli::cmd::Help::Help(Command& cmd)
: Command{cli::Name{"help"}, cli::Usage{"prints a short help message"}, cli::Description{"prints a short help message"}}, : Command{cli::Name{"help"}, cli::Usage{"prints a short help message"},
command{cmd} cli::Description{"prints a short help message"}},
{ command{cmd} {}
}
// From Command // From Command
int cli::cmd::Help::run(const Context &context) int cli::cmd::Help::run(const Context& context) {
{
command.help(context.cout); command.help(context.cout);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
void cli::cmd::Help::help(std::ostream &out) void cli::cmd::Help::help(std::ostream& out) { command.help(out); }
{
command.help(out);
}

View file

@ -35,44 +35,36 @@ namespace anbox {
namespace cli { namespace cli {
template <std::size_t max> template <std::size_t max>
class SizeConstrainedString class SizeConstrainedString {
{
public: public:
SizeConstrainedString(const std::string& s) : s{s} SizeConstrainedString(const std::string& s) : s{s} {
{
if (s.size() > max) if (s.size() > max)
throw std::logic_error{"Max size exceeded " + std::to_string(max)}; throw std::logic_error{"Max size exceeded " + std::to_string(max)};
} }
const std::string& as_string() const const std::string& as_string() const { return s; }
{
return s;
}
operator std::string() const operator std::string() const { return s; }
{
return s;
}
private: private:
std::string s; std::string s;
}; };
template <std::size_t max> template <std::size_t max>
bool operator<(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs) bool operator<(const SizeConstrainedString<max>& lhs,
{ const SizeConstrainedString<max>& rhs) {
return lhs.as_string() < rhs.as_string(); return lhs.as_string() < rhs.as_string();
} }
template <std::size_t max> template <std::size_t max>
bool operator==(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs) bool operator==(const SizeConstrainedString<max>& lhs,
{ const SizeConstrainedString<max>& rhs) {
return lhs.as_string() == rhs.as_string(); return lhs.as_string() == rhs.as_string();
} }
template <std::size_t max> template <std::size_t max>
std::ostream& operator<<(std::ostream& out, const SizeConstrainedString<max>& scs) std::ostream& operator<<(std::ostream& out,
{ const SizeConstrainedString<max>& scs) {
return out << std::setw(max) << std::left << scs.as_string(); return out << std::setw(max) << std::left << scs.as_string();
} }
@ -82,8 +74,7 @@ typedef SizeConstrainedString<60> Usage;
typedef SizeConstrainedString<60> Description; typedef SizeConstrainedString<60> 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 {
{
public: public:
// Safe us some typing. // Safe us some typing.
typedef std::shared_ptr<Flag> Ptr; typedef std::shared_ptr<Flag> Ptr;
@ -105,35 +96,30 @@ private:
Description description_; Description description_;
}; };
/// @brief TypedFlag implements Flag relying on operator<< and operator>> to read/write values to/from strings. /// @brief TypedFlag implements Flag relying on operator<< and operator>> to
/// read/write values to/from strings.
template <typename T> template <typename T>
class TypedFlag : public Flag class TypedFlag : public Flag {
{
public: public:
typedef std::shared_ptr<TypedFlag<T>> Ptr; typedef std::shared_ptr<TypedFlag<T>> Ptr;
TypedFlag(const Name& name, const Description& description) : Flag{name, description} TypedFlag(const Name& name, const Description& description)
{ : Flag{name, description} {}
}
/// @brief value installs the given value in the flag. /// @brief value installs the given value in the flag.
TypedFlag& value(const T& value) TypedFlag& value(const T& value) {
{
value_ = value; value_ = value;
return *this; return *this;
} }
/// @brief value returns the optional value associated with the flag. /// @brief value returns the optional value associated with the flag.
const Optional<T>& value() const const Optional<T>& value() const { return value_; }
{
return value_;
}
/// @brief notify tries to unwrap a value of type T from value. /// @brief notify tries to unwrap a value of type T from value.
void notify(const std::string& s) override void notify(const std::string& s) override {
{
std::stringstream ss{s}; std::stringstream ss{s};
T value; ss >> value; T value;
ss >> value;
value_ = value; value_ = value;
} }
@ -141,26 +127,23 @@ private:
Optional<T> value_; Optional<T> value_;
}; };
/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to convert to/from string representations, /// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to
/// convert to/from string representations,
/// updating the given mutable reference to a value of type T. /// updating the given mutable reference to a value of type T.
template <typename T> template <typename T>
class TypedReferenceFlag : public Flag class TypedReferenceFlag : public Flag {
{
public: public:
// Safe us some typing. // Safe us some typing.
typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr; typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
/// @brief TypedReferenceFlag initializes a new instance with name, description and value. /// @brief TypedReferenceFlag initializes a new instance with name,
/// description and value.
TypedReferenceFlag(const Name& name, const Description& description, T& value) TypedReferenceFlag(const Name& name, const Description& description, T& value)
: Flag{name, description}, : Flag{name, description}, value_{value} {}
value_{value}
{
}
/// @brief notify tries to unwrap a value of type T from value, /// @brief notify tries to unwrap a value of type T from value,
/// relying on operator>> to read from given string s. /// relying on operator>> to read from given string s.
void notify(const std::string& s) override void notify(const std::string& s) override {
{
std::stringstream ss{s}; std::stringstream ss{s};
ss >> value_.get(); ss >> value_.get();
} }
@ -169,24 +152,24 @@ private:
std::reference_wrapper<T> value_; std::reference_wrapper<T> value_;
}; };
/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making sure that /// @brief OptionalTypedReferenceFlag handles Optional<T> references, making
/// a value is always read on notify, even if the Optional<T> wasn't initialized previously. /// sure that
/// a value is always read on notify, even if the Optional<T> wasn't initialized
/// previously.
template <typename T> template <typename T>
class OptionalTypedReferenceFlag : public Flag class OptionalTypedReferenceFlag : public Flag {
{
public: public:
typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr; typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
OptionalTypedReferenceFlag(const Name& name, const Description& description, Optional<T>& value) OptionalTypedReferenceFlag(const Name& name, const Description& description,
: Flag{name, description}, Optional<T>& value)
value_{value} : Flag{name, description}, value_{value} {}
{
}
/// @brief notify tries to unwrap a value of type T from value. /// @brief notify tries to unwrap a value of type T from value.
void notify(const std::string& s) override void notify(const std::string& s) override {
{ std::stringstream ss{s};
std::stringstream ss{s}; T value; ss >> value; T value;
ss >> value;
value_.get() = value; value_.get() = value;
} }
@ -195,29 +178,26 @@ private:
}; };
/// @brief Command abstracts an individual command available from the daemon. /// @brief Command abstracts an individual command available from the daemon.
class Command : public DoNotCopyOrMove class Command : public DoNotCopyOrMove {
{
public: public:
// Safe us some typing // Safe us some typing
typedef std::shared_ptr<Command> Ptr; typedef std::shared_ptr<Command> Ptr;
/// @brief FlagsMissing is thrown if at least one required flag is missing. /// @brief FlagsMissing is thrown if at least one required flag is missing.
struct FlagsMissing : public std::runtime_error struct FlagsMissing : public std::runtime_error {
{
/// @brief FlagsMissing initializes a new instance. /// @brief FlagsMissing initializes a new instance.
FlagsMissing(); FlagsMissing();
}; };
/// @brief FlagsWithWrongValue is thrown if a value passed on the command line is invalid. /// @brief FlagsWithWrongValue is thrown if a value passed on the command line
struct FlagsWithInvalidValue : public std::runtime_error /// is invalid.
{ struct FlagsWithInvalidValue : public std::runtime_error {
/// @brief FlagsWithInvalidValue initializes a new instance. /// @brief FlagsWithInvalidValue initializes a new instance.
FlagsWithInvalidValue(); FlagsWithInvalidValue();
}; };
/// @brief Context bundles information passed to Command::run invocations. /// @brief Context bundles information passed to Command::run invocations.
struct Context struct Context {
{
std::istream& cin; ///< The std::istream that should be used for reading. std::istream& cin; ///< The std::istream that should be used for reading.
std::ostream& cout; ///< The std::ostream that should be used for writing. std::ostream& cout; ///< The std::ostream that should be used for writing.
std::vector<std::string> args; ///< The command line args. std::vector<std::string> args; ///< The command line args.
@ -239,7 +219,8 @@ public:
virtual void help(std::ostream& out) = 0; virtual void help(std::ostream& out) = 0;
protected: protected:
/// @brief Command initializes a new instance with the given name, usage and description. /// @brief Command initializes a new instance with the given name, usage and
/// description.
Command(const Name& name, const Usage& usage, const Description& description); Command(const Name& name, const Usage& usage, const Description& description);
/// @brief name adjusts the name of the command to n. /// @brief name adjusts the name of the command to n.
@ -255,15 +236,17 @@ private:
Description description_; Description description_;
}; };
/// @brief CommandWithSubcommands implements Command, selecting one of a set of actions. /// @brief CommandWithSubcommands implements Command, selecting one of a set of
class CommandWithSubcommands : public Command /// actions.
{ class CommandWithSubcommands : public Command {
public: public:
typedef std::shared_ptr<CommandWithSubcommands> Ptr; typedef std::shared_ptr<CommandWithSubcommands> Ptr;
typedef std::function<int(const Context&)> Action; typedef std::function<int(const Context&)> Action;
/// @brief CommandWithSubcommands initializes a new instance with the given name, usage and description /// @brief CommandWithSubcommands initializes a new instance with the given
CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description); /// name, usage and description
CommandWithSubcommands(const Name& name, const Usage& usage,
const Description& description);
/// @brief command adds the given command to the set of known commands. /// @brief command adds the given command to the set of known commands.
CommandWithSubcommands& command(const Command::Ptr& command); CommandWithSubcommands& command(const Command::Ptr& command);
@ -280,15 +263,17 @@ private:
std::set<Flag::Ptr> flags_; std::set<Flag::Ptr> flags_;
}; };
/// @brief CommandWithFlagsAction implements Command, executing an Action after handling /// @brief CommandWithFlagsAction implements Command, executing an Action after
class CommandWithFlagsAndAction : public Command /// handling
{ class CommandWithFlagsAndAction : public Command {
public: public:
typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr; typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
typedef std::function<int(const Context&)> Action; typedef std::function<int(const Context&)> Action;
/// @brief CommandWithFlagsAndAction initializes a new instance with the given name, usage and description /// @brief CommandWithFlagsAndAction initializes a new instance with the given
CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description); /// name, usage and description
CommandWithFlagsAndAction(const Name& name, const Usage& usage,
const Description& description);
/// @brief flag adds the given flag to the set of known flags. /// @brief flag adds the given flag to the set of known flags.
CommandWithFlagsAndAction& flag(const Flag::Ptr& flag); CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
@ -305,13 +290,12 @@ private:
Action action_; Action action_;
}; };
namespace cmd namespace cmd {
{
/// @brief HelpFor prints a help message for the given command on execution. /// @brief HelpFor prints a help message for the given command on execution.
class Help : public Command class Help : public Command {
{
public: public:
/// @brief HelpFor initializes a new instance with the given reference to a cmd. /// @brief HelpFor initializes a new instance with the given reference to a
/// cmd.
explicit Help(Command& cmd); explicit Help(Command& cmd);
// From Command // From Command
@ -330,27 +314,30 @@ std::vector<std::string> args(int argc, char** argv);
/// @brief make_flag returns a flag with the given name and description. /// @brief make_flag returns a flag with the given name and description.
template <typename T> template <typename T>
typename TypedFlag<T>::Ptr make_flag(const Name& name, const Description& description) typename TypedFlag<T>::Ptr make_flag(const Name& name,
{ const Description& description) {
return std::make_shared<TypedFlag<T>>(name, description); return std::make_shared<TypedFlag<T>>(name, description);
} }
/// @brief make_flag returns a flag with the given name and description, notifying updates to value. /// @brief make_flag returns a flag with the given name and description,
/// notifying updates to value.
template <typename T> template <typename T>
typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, T& value) typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name,
{ const Description& desc,
T& value) {
return std::make_shared<TypedReferenceFlag<T>>(name, desc, value); return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
} }
/// @brief make_flag returns a flag with the given name and description, updating the given optional value. /// @brief make_flag returns a flag with the given name and description,
/// updating the given optional value.
template <typename T> template <typename T>
typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, Optional<T>& value) typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name,
{ const Description& desc,
Optional<T>& value) {
return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value); return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
} }
} // namespace cli } // namespace cli
} // namespace anbox } // namespace anbox
#endif #endif

View file

@ -17,17 +17,18 @@
#include "anbox/cmds/container_manager.h" #include "anbox/cmds/container_manager.h"
#include "anbox/container/service.h" #include "anbox/container/service.h"
#include "anbox/runtime.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/runtime.h"
#include "core/posix/signal.h" #include "core/posix/signal.h"
anbox::cmds::ContainerManager::ContainerManager() anbox::cmds::ContainerManager::ContainerManager()
: CommandWithFlagsAndAction{cli::Name{"container-manager"}, cli::Usage{"container-manager"}, cli::Description{"Start the container manager service"}} : CommandWithFlagsAndAction{
{ cli::Name{"container-manager"}, cli::Usage{"container-manager"},
cli::Description{"Start the container manager service"}} {
action([](const cli::Command::Context& ctxt) { action([](const cli::Command::Context& ctxt) {
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term, auto trap = core::posix::trap_signals_for_process(
core::posix::Signal::sig_int}); {core::posix::Signal::sig_term, core::posix::Signal::sig_int});
trap->signal_raised().connect([trap](const core::posix::Signal& signal) { trap->signal_raised().connect([trap](const core::posix::Signal& signal) {
INFO("Signal %i received. Good night.", static_cast<int>(signal)); INFO("Signal %i received. Good night.", static_cast<int>(signal));
trap->stop(); trap->stop();

View file

@ -25,17 +25,22 @@
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
anbox::cmds::Install::Install() anbox::cmds::Install::Install()
: CommandWithFlagsAndAction{cli::Name{"install"}, cli::Usage{"install"}, cli::Description{"Install specified application in the Android container"}} : CommandWithFlagsAndAction{
{ cli::Name{"install"}, cli::Usage{"install"},
flag(cli::make_flag(cli::Name{"apk"}, cli::Description{"Path to APK to install"}, apk_)); cli::Description{
"Install specified application in the Android container"}} {
flag(cli::make_flag(cli::Name{"apk"},
cli::Description{"Path to APK to install"}, apk_));
action([this](const cli::Command::Context&) { action([this](const cli::Command::Context&) {
if (apk_.length() == 0) if (apk_.length() == 0)
BOOST_THROW_EXCEPTION(std::runtime_error("No APK to install specified")); BOOST_THROW_EXCEPTION(std::runtime_error("No APK to install specified"));
if (!fs::is_regular_file(apk_)) if (!fs::is_regular_file(apk_))
BOOST_THROW_EXCEPTION(std::runtime_error("Specified APK file does not exist")); BOOST_THROW_EXCEPTION(
std::runtime_error("Specified APK file does not exist"));
auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); auto bus =
std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
bus->install_executor(core::dbus::asio::make_executor(bus)); bus->install_executor(core::dbus::asio::make_executor(bus));
auto stub = dbus::stub::ApplicationManager::create_for_bus(bus); auto stub = dbus::stub::ApplicationManager::create_for_bus(bus);

View file

@ -25,16 +25,29 @@
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
anbox::cmds::Launch::Launch() anbox::cmds::Launch::Launch()
: CommandWithFlagsAndAction{cli::Name{"launch"}, cli::Usage{"launch"}, cli::Description{"Launch an Activity by sending an intent"}} : CommandWithFlagsAndAction{
{ cli::Name{"launch"}, cli::Usage{"launch"},
flag(cli::make_flag(cli::Name{"action"}, cli::Description{"Action of the intent"}, intent_.action)); cli::Description{"Launch an Activity by sending an intent"}} {
flag(cli::make_flag(cli::Name{"type"}, cli::Description{"MIME type for the intent"}, intent_.type)); flag(cli::make_flag(cli::Name{"action"},
flag(cli::make_flag(cli::Name{"uri"}, cli::Description{"URI used as data within the intent"}, intent_.uri)); cli::Description{"Action of the intent"},
flag(cli::make_flag(cli::Name{"package"}, cli::Description{"Package the intent should go to"}, intent_.package)); intent_.action));
flag(cli::make_flag(cli::Name{"component"}, cli::Description{"Component of a package the intent should go"}, intent_.component)); flag(cli::make_flag(cli::Name{"type"},
cli::Description{"MIME type for the intent"},
intent_.type));
flag(cli::make_flag(cli::Name{"uri"},
cli::Description{"URI used as data within the intent"},
intent_.uri));
flag(cli::make_flag(cli::Name{"package"},
cli::Description{"Package the intent should go to"},
intent_.package));
flag(cli::make_flag(
cli::Name{"component"},
cli::Description{"Component of a package the intent should go"},
intent_.component));
action([this](const cli::Command::Context&) { action([this](const cli::Command::Context&) {
auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); auto bus =
std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
bus->install_executor(core::dbus::asio::make_executor(bus)); bus->install_executor(core::dbus::asio::make_executor(bus));
auto stub = dbus::stub::ApplicationManager::create_for_bus(bus); auto stub = dbus::stub::ApplicationManager::create_for_bus(bus);

View file

@ -22,8 +22,8 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include "anbox/cli.h"
#include "anbox/android/intent.h" #include "anbox/android/intent.h"
#include "anbox/cli.h"
namespace anbox { namespace anbox {
namespace cmds { namespace cmds {

View file

@ -19,40 +19,42 @@
#include "core/posix/signal.h" #include "core/posix/signal.h"
#include "anbox/logger.h" #include "anbox/application/launcher_storage.h"
#include "anbox/runtime.h"
#include "anbox/config.h"
#include "anbox/common/dispatcher.h"
#include "anbox/cmds/run.h"
#include "anbox/network/published_socket_connector.h"
#include "anbox/qemu/pipe_connection_creator.h"
#include "anbox/graphics/gl_renderer_server.h"
#include "anbox/input/manager.h"
#include "anbox/rpc/connection_creator.h"
#include "anbox/rpc/channel.h"
#include "anbox/bridge/platform_message_processor.h"
#include "anbox/bridge/android_api_stub.h" #include "anbox/bridge/android_api_stub.h"
#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/bridge/platform_api_skeleton.h"
#include "anbox/dbus/skeleton/service.h" #include "anbox/bridge/platform_message_processor.h"
#include "anbox/cmds/run.h"
#include "anbox/common/dispatcher.h"
#include "anbox/config.h"
#include "anbox/container/client.h" #include "anbox/container/client.h"
#include "anbox/wm/manager.h" #include "anbox/dbus/skeleton/service.h"
#include "anbox/graphics/gl_renderer_server.h"
#include "anbox/input/manager.h"
#include "anbox/logger.h"
#include "anbox/network/published_socket_connector.h"
#include "anbox/qemu/pipe_connection_creator.h"
#include "anbox/rpc/channel.h"
#include "anbox/rpc/connection_creator.h"
#include "anbox/runtime.h"
#include "anbox/ubuntu/platform_policy.h" #include "anbox/ubuntu/platform_policy.h"
#include "anbox/application/launcher_storage.h" #include "anbox/wm/manager.h"
#include "external/xdg/xdg.h" #include "external/xdg/xdg.h"
#include <sys/prctl.h> #include <sys/prctl.h>
#include <core/dbus/bus.h>
#include <core/dbus/asio/executor.h> #include <core/dbus/asio/executor.h>
#include <core/dbus/bus.h>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace { namespace {
class NullConnectionCreator : public anbox::network::ConnectionCreator<boost::asio::local::stream_protocol> { class NullConnectionCreator : public anbox::network::ConnectionCreator<
boost::asio::local::stream_protocol> {
public: public:
void create_connection_for( void create_connection_for(
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override { std::shared_ptr<boost::asio::local::stream_protocol::socket> const
&socket) override {
WARNING("Not implemented"); WARNING("Not implemented");
socket->close(); socket->close();
} }
@ -66,25 +68,29 @@ anbox::cmds::Run::BusFactory anbox::cmds::Run::session_bus_factory() {
} }
anbox::cmds::Run::Run(const BusFactory &bus_factory) anbox::cmds::Run::Run(const BusFactory &bus_factory)
: CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"Run the the anbox system"}}, : CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"},
bus_factory_(bus_factory) cli::Description{"Run the the anbox system"}},
{ bus_factory_(bus_factory) {
// Just for the purpose to allow QtMir (or unity8) to find this on our /proc/*/cmdline // Just for the purpose to allow QtMir (or unity8) to find this on our
// /proc/*/cmdline
// for proper confinement etc. // for proper confinement etc.
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{"desktop_file_hint"},
flag(cli::make_flag(cli::Name{"icon"}, cli::Description{"Icon of the application to run"}, icon_)); cli::Description{"Desktop file hint for QtMir/Unity8"},
desktop_file_hint_));
flag(cli::make_flag(cli::Name{"icon"},
cli::Description{"Icon of the application to run"},
icon_));
action([this](const cli::Command::Context &ctx) { action([this](const cli::Command::Context &ctx) {
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term, auto trap = core::posix::trap_signals_for_process(
core::posix::Signal::sig_int}); {core::posix::Signal::sig_term, core::posix::Signal::sig_int});
trap->signal_raised().connect([trap](const core::posix::Signal &signal) { trap->signal_raised().connect([trap](const core::posix::Signal &signal) {
INFO("Signal %i received. Good night.", static_cast<int>(signal)); INFO("Signal %i received. Good night.", static_cast<int>(signal));
trap->stop(); trap->stop();
}); });
utils::ensure_paths({ utils::ensure_paths({
config::socket_path(), config::socket_path(), config::host_input_device_path(),
config::host_input_device_path(),
}); });
auto rt = Runtime::create(); auto rt = Runtime::create();
@ -94,7 +100,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
auto android_api_stub = std::make_shared<bridge::AndroidApiStub>(); auto android_api_stub = std::make_shared<bridge::AndroidApiStub>();
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager, android_api_stub); auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager,
android_api_stub);
// FIXME this needs to be removed and solved differently behind the scenes // FIXME this needs to be removed and solved differently behind the scenes
registerDisplayManager(policy); registerDisplayManager(policy);
@ -103,7 +110,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
auto launcher_storage = std::make_shared<application::LauncherStorage>( auto launcher_storage = std::make_shared<application::LauncherStorage>(
xdg::data().home() / "applications"); xdg::data().home() / "applications");
auto renderer = std::make_shared<graphics::GLRendererServer>(window_manager); auto renderer =
std::make_shared<graphics::GLRendererServer>(window_manager);
renderer->start(); renderer->start();
// Socket which will be used by the qemud service inside the Android // Socket which will be used by the qemud service inside the Android
@ -117,32 +125,31 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
// The qemu pipe is used as a very fast communication channel between guest // 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. // and host for things like the GLES emulation/translation, the RIL or ADB.
auto qemu_pipe_connector = std::make_shared<network::PublishedSocketConnector>( auto qemu_pipe_connector =
utils::string_format("%s/qemu_pipe", config::socket_path()), std::make_shared<network::PublishedSocketConnector>(
rt, utils::string_format("%s/qemu_pipe", config::socket_path()), rt,
std::make_shared<qemu::PipeConnectionCreator>(rt, std::make_shared<qemu::PipeConnectionCreator>(
renderer->socket_path(), rt, renderer->socket_path(), icon_));
icon_));
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>( auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
utils::string_format("%s/anbox_bridge", config::socket_path()), utils::string_format("%s/anbox_bridge", config::socket_path()), rt,
rt, std::make_shared<rpc::ConnectionCreator>(
std::make_shared<rpc::ConnectionCreator>(rt, rt, [&](const std::shared_ptr<network::MessageSender> &sender) {
[&](const std::shared_ptr<network::MessageSender> &sender) {
auto pending_calls = std::make_shared<rpc::PendingCallCache>(); auto pending_calls = std::make_shared<rpc::PendingCallCache>();
auto rpc_channel = std::make_shared<rpc::Channel>(pending_calls, sender); auto rpc_channel =
// This is safe as long as we only support a single client. If we support std::make_shared<rpc::Channel>(pending_calls, sender);
// more than one one day we need proper dispatching to the right one. // This is safe as long as we only support a single client. If we
// support
// more than one one day we need proper dispatching to the right
// one.
android_api_stub->set_rpc_channel(rpc_channel); android_api_stub->set_rpc_channel(rpc_channel);
auto server = std::make_shared<bridge::PlatformApiSkeleton>(pending_calls, auto server = std::make_shared<bridge::PlatformApiSkeleton>(
window_manager, pending_calls, window_manager, launcher_storage);
launcher_storage); server->register_boot_finished_handler(
server->register_boot_finished_handler([&]() { [&]() { DEBUG("Android successfully booted"); });
DEBUG("Android successfully booted"); return std::make_shared<bridge::PlatformMessageProcessor>(
}); sender, server, pending_calls);
return std::make_shared<bridge::PlatformMessageProcessor>(sender, server, pending_calls);
})); }));
container::Client container(rt); container::Client container(rt);
@ -156,14 +163,14 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
{"/dev/ashmem", "/dev/ashmem"}, {"/dev/ashmem", "/dev/ashmem"},
}; };
dispatcher->dispatch([&]() { dispatcher->dispatch(
container.start_container(container_configuration); [&]() { container.start_container(container_configuration); });
});
auto bus = bus_factory_(); auto bus = bus_factory_();
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service())); bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
auto skeleton = anbox::dbus::skeleton::Service::create_for_bus(bus, android_api_stub); auto skeleton =
anbox::dbus::skeleton::Service::create_for_bus(bus, android_api_stub);
rt->start(); rt->start();
trap->run(); trap->run();

View file

@ -21,10 +21,10 @@
#include "anbox/version.h" #include "anbox/version.h"
anbox::cmds::Version::Version() anbox::cmds::Version::Version()
: CommandWithFlagsAndAction{cli::Name{"version"}, cli::Usage{"version"}, cli::Description{"print the version of the daemon"}} : CommandWithFlagsAndAction{
{ cli::Name{"version"}, cli::Usage{"version"},
action([](const cli::Command::Context& ctxt) cli::Description{"print the version of the daemon"}} {
{ action([](const cli::Command::Context& ctxt) {
std::uint32_t major, minor, patch; std::uint32_t major, minor, patch;
anbox::version(major, minor, patch); anbox::version(major, minor, patch);
ctxt.cout << "anbox " << major << "." << minor << "." << patch << std::endl; ctxt.cout << "anbox " << major << "." << minor << "." << patch << std::endl;

View file

@ -23,13 +23,9 @@ namespace {
struct AsioStrandDispatcher : public anbox::common::Dispatcher { struct AsioStrandDispatcher : public anbox::common::Dispatcher {
public: public:
AsioStrandDispatcher(const std::shared_ptr<anbox::Runtime>& rt) AsioStrandDispatcher(const std::shared_ptr<anbox::Runtime>& rt)
: rt{rt}, : rt{rt}, strand{rt->service()} {}
strand{rt->service()} {
}
void dispatch(const Task &task) override { void dispatch(const Task& task) override { strand.post(task); }
strand.post(task);
}
private: private:
std::shared_ptr<anbox::Runtime> rt; std::shared_ptr<anbox::Runtime> rt;
@ -37,7 +33,8 @@ private:
}; };
} }
std::shared_ptr<anbox::common::Dispatcher> anbox::common::create_dispatcher_for_runtime( std::shared_ptr<anbox::common::Dispatcher>
anbox::common::create_dispatcher_for_runtime(
const std::shared_ptr<anbox::Runtime>& rt) { const std::shared_ptr<anbox::Runtime>& rt) {
return std::make_shared<AsioStrandDispatcher>(rt); return std::make_shared<AsioStrandDispatcher>(rt);
} }

View file

@ -36,7 +36,8 @@ protected:
Dispatcher() = default; Dispatcher() = default;
}; };
std::shared_ptr<Dispatcher> create_dispatcher_for_runtime(const std::shared_ptr<Runtime>&); std::shared_ptr<Dispatcher> create_dispatcher_for_runtime(
const std::shared_ptr<Runtime>&);
} // namespace common } // namespace common
} // namespace anbox } // namespace anbox

View file

@ -21,40 +21,26 @@
#include <algorithm> #include <algorithm>
namespace anbox { namespace anbox {
Fd::Fd() : Fd::Fd() : Fd{invalid} {}
Fd{invalid}
{
}
Fd::Fd(IntOwnedFd fd) : Fd::Fd(IntOwnedFd fd) : fd{std::make_shared<int>(fd.int_owned_fd)} {}
fd{std::make_shared<int>(fd.int_owned_fd)}
{
}
Fd::Fd(int raw_fd) : Fd::Fd(int raw_fd)
fd{new int{raw_fd}, : fd{new int{raw_fd},
[](int* fd) [](int* fd) {
{
if (!fd) return; if (!fd) return;
if (*fd > Fd::invalid) ::close(*fd); if (*fd > Fd::invalid) ::close(*fd);
delete fd; delete fd;
}} }} {}
{
}
Fd::Fd(Fd&& other) : Fd::Fd(Fd&& other) : fd{std::move(other.fd)} {}
fd{std::move(other.fd)}
{
}
Fd& Fd::operator=(Fd other) Fd& Fd::operator=(Fd other) {
{
std::swap(fd, other.fd); std::swap(fd, other.fd);
return *this; return *this;
} }
Fd::operator int() const Fd::operator int() const {
{
if (fd) return *fd; if (fd) return *fd;
return invalid; return invalid;
} }

View file

@ -22,14 +22,13 @@
#include <memory> #include <memory>
namespace anbox { namespace anbox {
struct IntOwnedFd struct IntOwnedFd {
{
int int_owned_fd; int int_owned_fd;
}; };
class Fd class Fd {
{
public: public:
//transfer ownership of the POD-int to the object. The int no longer needs close()ing, // transfer ownership of the POD-int to the object. The int no longer needs
// close()ing,
// and has the lifetime of the Fd object. // and has the lifetime of the Fd object.
explicit Fd(int fd); explicit Fd(int fd);
explicit Fd(IntOwnedFd); explicit Fd(IntOwnedFd);
@ -39,7 +38,8 @@ public:
Fd(Fd const&) = default; Fd(Fd const&) = default;
Fd& operator=(Fd); Fd& operator=(Fd);
//bit of a convenient kludge. take care not to close or otherwise destroy the FD. // bit of a convenient kludge. take care not to close or otherwise destroy the
// FD.
operator int() const; operator int() const;
private: private:

View file

@ -19,8 +19,8 @@
#ifndef ANBOX_COMMON_FD_SETS_H_ #ifndef ANBOX_COMMON_FD_SETS_H_
#define ANBOX_COMMON_FD_SETS_H_ #define ANBOX_COMMON_FD_SETS_H_
#include <vector>
#include <initializer_list> #include <initializer_list>
#include <vector>
#include "anbox/common/fd.h" #include "anbox/common/fd.h"

View file

@ -24,17 +24,14 @@
namespace anbox { namespace anbox {
template <size_t BuiltInBufferSize> template <size_t BuiltInBufferSize>
class VariableLengthArray class VariableLengthArray {
{
public: public:
explicit VariableLengthArray(size_t size) : size_{size} explicit VariableLengthArray(size_t size) : size_{size} {
{
/* Don't call resize if the initial values of member variables are valid */ /* Don't call resize if the initial values of member variables are valid */
if (size > BuiltInBufferSize) resize(size); if (size > BuiltInBufferSize) resize(size);
} }
void resize(size_t size) void resize(size_t size) {
{
if (size > BuiltInBufferSize) if (size > BuiltInBufferSize)
effective_buffer = BufferUPtr{new unsigned char[size], heap_deleter}; effective_buffer = BufferUPtr{new unsigned char[size], heap_deleter};
else else

View file

@ -21,27 +21,18 @@
namespace anbox { namespace anbox {
namespace common { namespace common {
WaitHandle::WaitHandle() : WaitHandle::WaitHandle()
guard(), : guard(), wait_condition(), expecting(0), received(0) {}
wait_condition(),
expecting(0),
received(0)
{
}
WaitHandle::~WaitHandle() WaitHandle::~WaitHandle() {}
{
}
void WaitHandle::expect_result() void WaitHandle::expect_result() {
{
std::lock_guard<std::mutex> lock(guard); std::lock_guard<std::mutex> lock(guard);
expecting++; expecting++;
} }
void WaitHandle::result_received() void WaitHandle::result_received() {
{
std::lock_guard<std::mutex> lock(guard); std::lock_guard<std::mutex> lock(guard);
received++; received++;
@ -58,14 +49,12 @@ void WaitHandle::wait_for_all() // wait for all results you expect
expecting = 0; expecting = 0;
} }
void WaitHandle::wait_for_pending(std::chrono::milliseconds limit) void WaitHandle::wait_for_pending(std::chrono::milliseconds limit) {
{
std::unique_lock<std::mutex> lock(guard); std::unique_lock<std::mutex> lock(guard);
wait_condition.wait_for(lock, limit, [&] { return received == expecting; }); wait_condition.wait_for(lock, limit, [&] { return received == expecting; });
} }
void WaitHandle::wait_for_one() // wait for any single result void WaitHandle::wait_for_one() // wait for any single result
{ {
std::unique_lock<std::mutex> lock(guard); std::unique_lock<std::mutex> lock(guard);
@ -76,15 +65,13 @@ void WaitHandle::wait_for_one() // wait for any single result
--expecting; --expecting;
} }
bool WaitHandle::has_result() bool WaitHandle::has_result() {
{
std::lock_guard<std::mutex> lock(guard); std::lock_guard<std::mutex> lock(guard);
return received > 0; return received > 0;
} }
bool WaitHandle::is_pending() bool WaitHandle::is_pending() {
{
std::unique_lock<std::mutex> lock(guard); std::unique_lock<std::mutex> lock(guard);
return expecting > 0 && received != expecting; return expecting > 0 && received != expecting;
} }

View file

@ -26,8 +26,7 @@
namespace anbox { namespace anbox {
namespace common { namespace common {
struct WaitHandle struct WaitHandle {
{
public: public:
WaitHandle(); WaitHandle();
~WaitHandle(); ~WaitHandle();

View file

@ -53,7 +53,8 @@ std::string runtime_dir() {
if (path.empty()) { if (path.empty()) {
path = utils::get_env_value("XDG_RUNTIME_DIR", ""); path = utils::get_env_value("XDG_RUNTIME_DIR", "");
if (path.empty()) if (path.empty())
BOOST_THROW_EXCEPTION(std::runtime_error("No runtime directory specified")); BOOST_THROW_EXCEPTION(
std::runtime_error("No runtime directory specified"));
} }
return path; return path;
} }
@ -64,13 +65,14 @@ std::string state_dir() {
} }
std::string log_path() { std::string log_path() {
static std::string path = in_snap_data_dir(utils::string_format("%s/anbox/", state_dir())); static std::string path =
in_snap_data_dir(utils::string_format("%s/anbox/", state_dir()));
return path; return path;
} }
std::string socket_path() { std::string socket_path() {
static std::string path =
static std::string path = utils::string_format("%s/anbox/sockets", runtime_dir()); utils::string_format("%s/anbox/sockets", runtime_dir());
return path; return path;
} }
@ -80,12 +82,14 @@ std::string data_path() {
} }
std::string rootfs_path() { std::string rootfs_path() {
static std::string path = in_snap_data_dir(utils::string_format("%s/anbox/rootfs", state_dir())); static std::string path =
in_snap_data_dir(utils::string_format("%s/anbox/rootfs", state_dir()));
return path; return path;
} }
std::string container_config_path() { std::string container_config_path() {
static std::string path = in_snap_data_dir(utils::string_format("%s/anbox/containers", state_dir())); static std::string path = in_snap_data_dir(
utils::string_format("%s/anbox/containers", state_dir()));
return path; return path;
} }
@ -95,7 +99,8 @@ std::string container_socket_path() {
} }
std::string host_input_device_path() { std::string host_input_device_path() {
static std::string path = utils::string_format("%s/anbox/input-devices", runtime_dir()); static std::string path =
utils::string_format("%s/anbox/input-devices", runtime_dir());
return path; return path;
} }
} // namespace config } // namespace config

View file

@ -16,53 +16,50 @@
*/ */
#include "anbox/container/client.h" #include "anbox/container/client.h"
#include "anbox/config.h"
#include "anbox/container/management_api_stub.h" #include "anbox/container/management_api_stub.h"
#include "anbox/logger.h"
#include "anbox/network/local_socket_messenger.h" #include "anbox/network/local_socket_messenger.h"
#include "anbox/rpc/pending_call_cache.h"
#include "anbox/rpc/channel.h" #include "anbox/rpc/channel.h"
#include "anbox/rpc/message_processor.h" #include "anbox/rpc/message_processor.h"
#include "anbox/config.h" #include "anbox/rpc/pending_call_cache.h"
#include "anbox/logger.h"
namespace ba = boost::asio; namespace ba = boost::asio;
namespace bs = boost::system; namespace bs = boost::system;
namespace anbox { namespace anbox {
namespace container { namespace container {
Client::Client(const std::shared_ptr<Runtime> &rt) : Client::Client(const std::shared_ptr<Runtime> &rt)
messenger_(std::make_shared<network::LocalSocketMessenger>(config::container_socket_path(), rt)), : messenger_(std::make_shared<network::LocalSocketMessenger>(
config::container_socket_path(), rt)),
pending_calls_(std::make_shared<rpc::PendingCallCache>()), pending_calls_(std::make_shared<rpc::PendingCallCache>()),
rpc_channel_(std::make_shared<rpc::Channel>(pending_calls_, messenger_)), rpc_channel_(std::make_shared<rpc::Channel>(pending_calls_, messenger_)),
management_api_(std::make_shared<ManagementApiStub>(rpc_channel_)), management_api_(std::make_shared<ManagementApiStub>(rpc_channel_)),
processor_(std::make_shared<rpc::MessageProcessor>(messenger_, pending_calls_)) { processor_(
std::make_shared<rpc::MessageProcessor>(messenger_, pending_calls_)) {
read_next_message(); read_next_message();
} }
Client::~Client() { Client::~Client() {}
}
void Client::start_container(const Configuration &configuration) { void Client::start_container(const Configuration &configuration) {
management_api_->start_container(configuration); management_api_->start_container(configuration);
} }
void Client::read_next_message() void Client::read_next_message() {
{ auto callback = std::bind(&Client::on_read_size, this, std::placeholders::_1,
auto callback = std::bind(&Client::on_read_size, std::placeholders::_2);
this, std::placeholders::_1, std::placeholders::_2);
messenger_->async_receive_msg(callback, ba::buffer(buffer_)); messenger_->async_receive_msg(callback, ba::buffer(buffer_));
} }
void Client::on_read_size(const boost::system::error_code& error, std::size_t bytes_read) void Client::on_read_size(const boost::system::error_code &error,
{ std::size_t bytes_read) {
if (error) if (error) BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
std::vector<std::uint8_t> data(bytes_read); std::vector<std::uint8_t> data(bytes_read);
std::copy(buffer_.data(), buffer_.data() + bytes_read, data.data()); std::copy(buffer_.data(), buffer_.data() + bytes_read, data.data());
if (processor_->process_data(data)) if (processor_->process_data(data)) read_next_message();
read_next_message();
} }
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_CONTAINER_CLIENT_H_ #ifndef ANBOX_CONTAINER_CLIENT_H_
#define ANBOX_CONTAINER_CLIENT_H_ #define ANBOX_CONTAINER_CLIENT_H_
#include "anbox/runtime.h"
#include "anbox/container/configuration.h" #include "anbox/container/configuration.h"
#include "anbox/runtime.h"
namespace anbox { namespace anbox {
namespace rpc { namespace rpc {
@ -41,7 +41,8 @@ public:
private: private:
void read_next_message(); void read_next_message();
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read); void on_read_size(const boost::system::error_code &ec,
std::size_t bytes_read);
std::shared_ptr<network::LocalSocketMessenger> messenger_; std::shared_ptr<network::LocalSocketMessenger> messenger_;
std::shared_ptr<rpc::PendingCallCache> pending_calls_; std::shared_ptr<rpc::PendingCallCache> pending_calls_;

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_CONTAINER_CONFIGURATION_H_ #ifndef ANBOX_CONTAINER_CONFIGURATION_H_
#define ANBOX_CONTAINER_CONFIGURATION_H_ #define ANBOX_CONTAINER_CONFIGURATION_H_
#include <string>
#include <map> #include <map>
#include <string>
namespace anbox { namespace anbox {
namespace container { namespace container {

View file

@ -19,7 +19,6 @@
namespace anbox { namespace anbox {
namespace container { namespace container {
Container::~Container() { Container::~Container() {}
}
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

View file

@ -20,8 +20,8 @@
#include "anbox/container/configuration.h" #include "anbox/container/configuration.h"
#include <string>
#include <map> #include <map>
#include <string>
namespace anbox { namespace anbox {
namespace container { namespace container {

View file

@ -16,31 +16,28 @@
*/ */
#include "anbox/container/lxc_container.h" #include "anbox/container/lxc_container.h"
#include "anbox/utils.h"
#include "anbox/config.h" #include "anbox/config.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/utils.h"
#include <stdexcept>
#include <map> #include <map>
#include <stdexcept>
#include <boost/throw_exception.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/throw_exception.hpp>
#include <sys/wait.h>
#include <sys/capability.h> #include <sys/capability.h>
#include <sys/types.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace anbox { namespace anbox {
namespace container { namespace container {
LxcContainer::LxcContainer() : LxcContainer::LxcContainer() : state_(State::inactive), container_(nullptr) {
state_(State::inactive),
container_(nullptr) {
utils::ensure_paths({ utils::ensure_paths({
config::container_config_path(), config::container_config_path(), config::log_path(),
config::log_path(),
}); });
} }
@ -49,16 +46,17 @@ LxcContainer::~LxcContainer() {
stop(); stop();
if (container_) if (container_) lxc_container_put(container_);
lxc_container_put(container_);
} }
void LxcContainer::start(const Configuration &configuration) { void LxcContainer::start(const Configuration &configuration) {
if (getuid() != 0) if (getuid() != 0)
BOOST_THROW_EXCEPTION(std::runtime_error("You have to start the container as root")); BOOST_THROW_EXCEPTION(
std::runtime_error("You have to start the container as root"));
if (container_ && container_->is_running(container_)) { if (container_ && container_->is_running(container_)) {
BOOST_THROW_EXCEPTION(std::runtime_error("Container already started, stopping it now")); BOOST_THROW_EXCEPTION(
std::runtime_error("Container already started, stopping it now"));
container_->stop(container_); container_->stop(container_);
} }
@ -66,22 +64,28 @@ void LxcContainer::start(const Configuration &configuration) {
DEBUG("Containers are stored in %s", config::container_config_path()); DEBUG("Containers are stored in %s", config::container_config_path());
// Remove container config to be be able to rewrite it // Remove container config to be be able to rewrite it
::unlink(utils::string_format("%s/default/config", config::container_config_path()).c_str()); ::unlink(utils::string_format("%s/default/config",
config::container_config_path())
.c_str());
container_ = lxc_container_new("default", config::container_config_path().c_str()); container_ =
lxc_container_new("default", config::container_config_path().c_str());
if (!container_) if (!container_)
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create LXC container instance")); BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to create LXC container instance"));
// If container is still running (for example after a crash) we stop it here to ensure // If container is still running (for example after a crash) we stop it here
// to ensure
// its configuration is synchronized. // its configuration is synchronized.
if (container_->is_running(container_)) if (container_->is_running(container_)) container_->stop(container_);
container_->stop(container_);
} }
// We drop all not needed capabilities // We drop all not needed capabilities
set_config_item("lxc.cap.drop", "mac_admin mac_override sys_time sys_module sys_rawio"); set_config_item("lxc.cap.drop",
"mac_admin mac_override sys_time sys_module sys_rawio");
// We can mount proc/sys as rw here as we will run the container unprivileged in the end // We can mount proc/sys as rw here as we will run the container unprivileged
// in the end
set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed"); set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed");
set_config_item("lxc.autodev", "1"); set_config_item("lxc.autodev", "1");
@ -95,7 +99,8 @@ void LxcContainer::start(const Configuration &configuration) {
// We can't move bind-mounts, so don't use /dev/lxc/ // We can't move bind-mounts, so don't use /dev/lxc/
set_config_item("lxc.devttydir", ""); set_config_item("lxc.devttydir", "");
set_config_item("lxc.environment", "PATH=/system/bin:/system/sbin:/system/xbin"); set_config_item("lxc.environment",
"PATH=/system/bin:/system/sbin:/system/xbin");
set_config_item("lxc.init_cmd", "/anbox-init.sh"); set_config_item("lxc.init_cmd", "/anbox-init.sh");
set_config_item("lxc.rootfs.backend", "dir"); set_config_item("lxc.rootfs.backend", "dir");
@ -104,7 +109,9 @@ void LxcContainer::start(const Configuration &configuration) {
set_config_item("lxc.rootfs", config::rootfs_path()); set_config_item("lxc.rootfs", config::rootfs_path());
set_config_item("lxc.loglevel", "0"); set_config_item("lxc.loglevel", "0");
set_config_item("lxc.logfile", utils::string_format("%s/container.log", config::log_path()).c_str()); set_config_item(
"lxc.logfile",
utils::string_format("%s/container.log", config::log_path()).c_str());
set_config_item("lxc.network.type", "veth"); set_config_item("lxc.network.type", "veth");
set_config_item("lxc.network.flags", "up"); set_config_item("lxc.network.flags", "up");
@ -115,8 +122,10 @@ void LxcContainer::start(const Configuration &configuration) {
// which are otherwise forbidden by AppArmor. // which are otherwise forbidden by AppArmor.
set_config_item("lxc.aa_profile", "lxc-container-default-with-nesting"); set_config_item("lxc.aa_profile", "lxc-container-default-with-nesting");
#else #else
// FIXME: when using the nested profile we still get various denials from things // FIXME: when using the nested profile we still get various denials from
// Android tries to do but isn't allowed to. We need to look into those and see // things
// Android tries to do but isn't allowed to. We need to look into those and
// see
// how we can switch back to a confined way of running the container. // how we can switch back to a confined way of running the container.
set_config_item("lxc.aa_profile", "unconfined"); set_config_item("lxc.aa_profile", "unconfined");
#endif #endif
@ -124,22 +133,22 @@ void LxcContainer::start(const Configuration &configuration) {
for (const auto &bind_mount : configuration.bind_mounts) { for (const auto &bind_mount : configuration.bind_mounts) {
std::string create_type = "file"; std::string create_type = "file";
if (fs::is_directory(bind_mount.first)) if (fs::is_directory(bind_mount.first)) create_type = "dir";
create_type = "dir";
auto target_path = bind_mount.second; auto target_path = bind_mount.second;
// LXC wants target paths relative to the container rootfs so // LXC wants target paths relative to the container rootfs so
// prividing an absolute path doesn't work. // prividing an absolute path doesn't work.
if (utils::string_starts_with(target_path, "/")) if (utils::string_starts_with(target_path, "/")) target_path.erase(0, 1);
target_path.erase(0, 1);
set_config_item("lxc.mount.entry", set_config_item(
"lxc.mount.entry",
utils::string_format("%s %s none bind,create=%s,optional 0 0", utils::string_format("%s %s none bind,create=%s,optional 0 0",
bind_mount.first, target_path, create_type)); bind_mount.first, target_path, create_type));
} }
if (!container_->save_config(container_, nullptr)) if (!container_->save_config(container_, nullptr))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to save container configuration")); BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to save container configuration"));
if (not container_->start(container_, 0, nullptr)) if (not container_->start(container_, 0, nullptr))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start container")); BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start container"));
@ -151,7 +160,8 @@ void LxcContainer::start(const Configuration &configuration) {
void LxcContainer::stop() { void LxcContainer::stop() {
if (not container_ || not container_->is_running(container_)) if (not container_ || not container_->is_running(container_))
BOOST_THROW_EXCEPTION(std::runtime_error("Cannot stop container as it is not running")); BOOST_THROW_EXCEPTION(
std::runtime_error("Cannot stop container as it is not running"));
if (not container_->stop(container_)) if (not container_->stop(container_))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container")); BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container"));
@ -161,13 +171,13 @@ void LxcContainer::stop() {
DEBUG("Container successfully stopped"); DEBUG("Container successfully stopped");
} }
void LxcContainer::set_config_item(const std::string &key, const std::string &value) { void LxcContainer::set_config_item(const std::string &key,
const std::string &value) {
if (!container_->set_config_item(container_, key.c_str(), value.c_str())) if (!container_->set_config_item(container_, key.c_str(), value.c_str()))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to configure LXC container")); BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to configure LXC container"));
} }
Container::State LxcContainer::state() { Container::State LxcContainer::state() { return state_; }
return state_;
}
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

View file

@ -24,22 +24,22 @@
namespace anbox { namespace anbox {
namespace container { namespace container {
ManagementApiMessageProcessor::ManagementApiMessageProcessor(const std::shared_ptr<network::MessageSender> &sender, ManagementApiMessageProcessor::ManagementApiMessageProcessor(
const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<rpc::PendingCallCache> &pending_calls, const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<ManagementApiSkeleton> &server) : const std::shared_ptr<ManagementApiSkeleton> &server)
rpc::MessageProcessor(sender, pending_calls), : rpc::MessageProcessor(sender, pending_calls), server_(server) {}
server_(server) {
}
ManagementApiMessageProcessor::~ManagementApiMessageProcessor() { ManagementApiMessageProcessor::~ManagementApiMessageProcessor() {}
}
void ManagementApiMessageProcessor::dispatch(rpc::Invocation const& invocation) { void ManagementApiMessageProcessor::dispatch(
rpc::Invocation const &invocation) {
if (invocation.method_name() == "start_container") if (invocation.method_name() == "start_container")
invoke(this, server_.get(), &ManagementApiSkeleton::start_container, invocation); invoke(this, server_.get(), &ManagementApiSkeleton::start_container,
invocation);
} }
void ManagementApiMessageProcessor::process_event_sequence(const std::string&) { void ManagementApiMessageProcessor::process_event_sequence(
} const std::string &) {}
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

View file

@ -25,7 +25,8 @@ namespace container {
class ManagementApiSkeleton; class ManagementApiSkeleton;
class ManagementApiMessageProcessor : public rpc::MessageProcessor { class ManagementApiMessageProcessor : public rpc::MessageProcessor {
public: public:
ManagementApiMessageProcessor(const std::shared_ptr<network::MessageSender> &sender, ManagementApiMessageProcessor(
const std::shared_ptr<network::MessageSender> &sender,
const std::shared_ptr<rpc::PendingCallCache> &pending_calls, const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<ManagementApiSkeleton> &server); const std::shared_ptr<ManagementApiSkeleton> &server);
~ManagementApiMessageProcessor(); ~ManagementApiMessageProcessor();

View file

@ -16,30 +16,27 @@
*/ */
#include "anbox/container/management_api_skeleton.h" #include "anbox/container/management_api_skeleton.h"
#include "anbox/container/container.h"
#include "anbox/container/configuration.h" #include "anbox/container/configuration.h"
#include "anbox/container/container.h"
#include "anbox/defer_action.h" #include "anbox/defer_action.h"
#include "anbox/utils.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/utils.h"
#include "anbox_rpc.pb.h"
#include "anbox_container.pb.h" #include "anbox_container.pb.h"
#include "anbox_rpc.pb.h"
namespace anbox { namespace anbox {
namespace container { namespace container {
ManagementApiSkeleton::ManagementApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls, ManagementApiSkeleton::ManagementApiSkeleton(
const std::shared_ptr<Container> &container) : const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
pending_calls_(pending_calls), const std::shared_ptr<Container> &container)
container_(container) { : pending_calls_(pending_calls), container_(container) {}
}
ManagementApiSkeleton::~ManagementApiSkeleton() { ManagementApiSkeleton::~ManagementApiSkeleton() {}
}
void ManagementApiSkeleton::start_container(anbox::protobuf::container::StartContainer const *request,
anbox::protobuf::rpc::Void *response,
google::protobuf::Closure *done) {
void ManagementApiSkeleton::start_container(
anbox::protobuf::container::StartContainer const *request,
anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done) {
if (container_->state() == Container::State::running) { if (container_->state() == Container::State::running) {
response->set_error("Container is already running"); response->set_error("Container is already running");
done->Run(); done->Run();
@ -51,14 +48,15 @@ void ManagementApiSkeleton::start_container(anbox::protobuf::container::StartCon
const auto configuration = request->configuration(); const auto configuration = request->configuration();
for (int n = 0; n < configuration.bind_mounts_size(); n++) { for (int n = 0; n < configuration.bind_mounts_size(); n++) {
const auto bind_mount = configuration.bind_mounts(n); const auto bind_mount = configuration.bind_mounts(n);
container_configuration.bind_mounts.insert({ bind_mount.source(), bind_mount.target() }); container_configuration.bind_mounts.insert(
{bind_mount.source(), bind_mount.target()});
} }
try { try {
container_->start(container_configuration); container_->start(container_configuration);
} } catch (std::exception &err) {
catch (std::exception &err) { response->set_error(
response->set_error(utils::string_format("Failed to start container: %s", err.what())); utils::string_format("Failed to start container: %s", err.what()));
} }
DEBUG(""); DEBUG("");

View file

@ -42,13 +42,14 @@ namespace container {
class Container; class Container;
class ManagementApiSkeleton { class ManagementApiSkeleton {
public: public:
ManagementApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls, ManagementApiSkeleton(
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
const std::shared_ptr<Container> &container); const std::shared_ptr<Container> &container);
~ManagementApiSkeleton(); ~ManagementApiSkeleton();
void start_container(anbox::protobuf::container::StartContainer const *request, void start_container(
anbox::protobuf::rpc::Void *response, anbox::protobuf::container::StartContainer const *request,
google::protobuf::Closure *done); anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done);
private: private:
std::shared_ptr<rpc::PendingCallCache> pending_calls_; std::shared_ptr<rpc::PendingCallCache> pending_calls_;

View file

@ -16,20 +16,19 @@
*/ */
#include "anbox/container/management_api_stub.h" #include "anbox/container/management_api_stub.h"
#include "anbox/rpc/channel.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/rpc/channel.h"
#include "anbox_rpc.pb.h"
#include "anbox_container.pb.h" #include "anbox_container.pb.h"
#include "anbox_rpc.pb.h"
namespace anbox { namespace anbox {
namespace container { namespace container {
ManagementApiStub::ManagementApiStub(const std::shared_ptr<rpc::Channel> &channel) : ManagementApiStub::ManagementApiStub(
channel_(channel) { const std::shared_ptr<rpc::Channel> &channel)
} : channel_(channel) {}
ManagementApiStub::~ManagementApiStub() { ManagementApiStub::~ManagementApiStub() {}
}
void ManagementApiStub::start_container(const Configuration &configuration) { void ManagementApiStub::start_container(const Configuration &configuration) {
auto c = std::make_shared<Request<protobuf::rpc::Void>>(); auto c = std::make_shared<Request<protobuf::rpc::Void>>();
@ -50,18 +49,18 @@ void ManagementApiStub::start_container(const Configuration &configuration) {
start_wait_handle_.expect_result(); start_wait_handle_.expect_result();
} }
channel_->call_method("start_container", channel_->call_method(
&message, "start_container", &message, c->response.get(),
c->response.get(), google::protobuf::NewCallback(this, &ManagementApiStub::container_started,
google::protobuf::NewCallback(this, &ManagementApiStub::container_started, c.get())); c.get()));
start_wait_handle_.wait_for_all(); start_wait_handle_.wait_for_all();
if (c->response->has_error()) if (c->response->has_error()) throw std::runtime_error(c->response->error());
throw std::runtime_error(c->response->error());
} }
void ManagementApiStub::container_started(Request<protobuf::rpc::Void> *request) { void ManagementApiStub::container_started(
Request<protobuf::rpc::Void> *request) {
(void)request; (void)request;
DEBUG(""); DEBUG("");
start_wait_handle_.result_received(); start_wait_handle_.result_received();

View file

@ -18,9 +18,9 @@
#ifndef ANBOX_CONTAINER_MANAGEMENT_API_STUB_H_ #ifndef ANBOX_CONTAINER_MANAGEMENT_API_STUB_H_
#define ANBOX_CONTAINER_MANAGEMENT_API_STUB_H_ #define ANBOX_CONTAINER_MANAGEMENT_API_STUB_H_
#include "anbox/do_not_copy_or_move.h"
#include "anbox/container/configuration.h"
#include "anbox/common/wait_handle.h" #include "anbox/common/wait_handle.h"
#include "anbox/container/configuration.h"
#include "anbox/do_not_copy_or_move.h"
#include <memory> #include <memory>

View file

@ -16,60 +16,61 @@
*/ */
#include "anbox/container/service.h" #include "anbox/container/service.h"
#include "anbox/config.h"
#include "anbox/container/lxc_container.h"
#include "anbox/container/management_api_message_processor.h"
#include "anbox/container/management_api_skeleton.h"
#include "anbox/logger.h"
#include "anbox/network/delegate_connection_creator.h" #include "anbox/network/delegate_connection_creator.h"
#include "anbox/network/delegate_message_processor.h" #include "anbox/network/delegate_message_processor.h"
#include "anbox/network/local_socket_messenger.h" #include "anbox/network/local_socket_messenger.h"
#include "anbox/qemu/null_message_processor.h" #include "anbox/qemu/null_message_processor.h"
#include "anbox/rpc/pending_call_cache.h"
#include "anbox/rpc/channel.h" #include "anbox/rpc/channel.h"
#include "anbox/container/lxc_container.h" #include "anbox/rpc/pending_call_cache.h"
#include "anbox/container/management_api_message_processor.h"
#include "anbox/container/management_api_skeleton.h"
#include "anbox/config.h"
#include "anbox/logger.h"
namespace anbox { namespace anbox {
namespace container { namespace container {
std::shared_ptr<Service> Service::create(const std::shared_ptr<Runtime> &rt) { std::shared_ptr<Service> Service::create(const std::shared_ptr<Runtime> &rt) {
auto sp = std::make_shared<Service>(rt); auto sp = std::make_shared<Service>(rt);
auto delegate_connector = std::make_shared<network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>( auto delegate_connector = std::make_shared<
[sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) { network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>(
sp->new_client(socket); [sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const
}); &socket) { sp->new_client(socket); });
sp->connector_ = std::make_shared<network::PublishedSocketConnector>( sp->connector_ = std::make_shared<network::PublishedSocketConnector>(
config::container_socket_path(), rt, delegate_connector); config::container_socket_path(), rt, delegate_connector);
// Make sure others can connect to our socket // Make sure others can connect to our socket
::chmod(config::container_socket_path().c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); ::chmod(config::container_socket_path().c_str(),
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
DEBUG("Everything setup. Waiting for incoming connections."); DEBUG("Everything setup. Waiting for incoming connections.");
return sp; return sp;
} }
Service::Service(const std::shared_ptr<Runtime> &rt) : Service::Service(const std::shared_ptr<Runtime> &rt)
dispatcher_(anbox::common::create_dispatcher_for_runtime(rt)), : dispatcher_(anbox::common::create_dispatcher_for_runtime(rt)),
next_connection_id_(0), next_connection_id_(0),
connections_(std::make_shared<network::Connections<network::SocketConnection>>()) { connections_(
std::make_shared<network::Connections<network::SocketConnection>>()) {
} }
Service::~Service() { Service::~Service() { DEBUG(""); }
DEBUG("");
}
int Service::next_id() { int Service::next_id() { return next_connection_id_++; }
return next_connection_id_++;
}
void Service::new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) { void Service::new_client(
std::shared_ptr<boost::asio::local::stream_protocol::socket> const
&socket) {
if (connections_->size() >= 1) { if (connections_->size() >= 1) {
socket->close(); socket->close();
return; return;
} }
auto const messenger = std::make_shared<network::LocalSocketMessenger>(socket); auto const messenger =
std::make_shared<network::LocalSocketMessenger>(socket);
DEBUG("Got connection from pid %d", messenger->creds().pid()); DEBUG("Got connection from pid %d", messenger->creds().pid());

View file

@ -18,12 +18,12 @@
#ifndef ANBOX_CONTAINER_SERVICE_H_ #ifndef ANBOX_CONTAINER_SERVICE_H_
#define ANBOX_CONTAINER_SERVICE_H_ #define ANBOX_CONTAINER_SERVICE_H_
#include "anbox/network/published_socket_connector.h"
#include "anbox/network/connections.h"
#include "anbox/network/socket_connection.h"
#include "anbox/network/credentials.h"
#include "anbox/container/container.h"
#include "anbox/common/dispatcher.h" #include "anbox/common/dispatcher.h"
#include "anbox/container/container.h"
#include "anbox/network/connections.h"
#include "anbox/network/credentials.h"
#include "anbox/network/published_socket_connector.h"
#include "anbox/network/socket_connection.h"
#include "anbox/runtime.h" #include "anbox/runtime.h"
namespace anbox { namespace anbox {
@ -37,7 +37,8 @@ public:
private: private:
int next_id(); int next_id();
void new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket); void new_client(std::shared_ptr<
boost::asio::local::stream_protocol::socket> const &socket);
std::shared_ptr<common::Dispatcher> dispatcher_; std::shared_ptr<common::Dispatcher> dispatcher_;
std::shared_ptr<network::PublishedSocketConnector> connector_; std::shared_ptr<network::PublishedSocketConnector> connector_;

View file

@ -15,37 +15,35 @@
* *
*/ */
#include <sys/prctl.h>
#include <signal.h> #include <signal.h>
#include <sys/prctl.h>
#include "anbox/logger.h"
#include "anbox/daemon.h"
#include "anbox/config.h" #include "anbox/config.h"
#include "anbox/daemon.h"
#include "anbox/logger.h"
#include "anbox/cmds/version.h"
#include "anbox/cmds/run.h"
#include "anbox/cmds/launch.h"
#include "anbox/cmds/container_manager.h" #include "anbox/cmds/container_manager.h"
#include "anbox/cmds/launch.h"
#include "anbox/cmds/run.h"
#include "anbox/cmds/version.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace anbox { namespace anbox {
Daemon::Daemon() : Daemon::Daemon()
cmd{cli::Name{"anbox"}, cli::Usage{"anbox"}, cli::Description{"The Android in a Box runtime"}} { : cmd{cli::Name{"anbox"}, cli::Usage{"anbox"},
cli::Description{"The Android in a Box runtime"}} {
cmd.command(std::make_shared<cmds::Version>()) cmd.command(std::make_shared<cmds::Version>())
.command(std::make_shared<cmds::Run>()) .command(std::make_shared<cmds::Run>())
.command(std::make_shared<cmds::Launch>()) .command(std::make_shared<cmds::Launch>())
.command(std::make_shared<cmds::ContainerManager>()); .command(std::make_shared<cmds::ContainerManager>());
} }
int Daemon::Run(const std::vector<std::string> &arguments) int Daemon::Run(const std::vector<std::string> &arguments) try {
try {
return cmd.run({std::cin, std::cout, arguments}); return cmd.run({std::cin, std::cout, arguments});
} } catch (std::exception &err) {
catch(std::exception &err) {
ERROR("%s", err.what()); ERROR("%s", err.what());
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View file

@ -18,11 +18,11 @@
#ifndef ANBOX_DAEMON_H_ #ifndef ANBOX_DAEMON_H_
#define ANBOX_DAEMON_H_ #define ANBOX_DAEMON_H_
#include <vector>
#include <string> #include <string>
#include <vector>
#include "anbox/do_not_copy_or_move.h"
#include "anbox/cli.h" #include "anbox/cli.h"
#include "anbox/do_not_copy_or_move.h"
namespace anbox { namespace anbox {
class Daemon : public DoNotCopyOrMove { class Daemon : public DoNotCopyOrMove {

View file

@ -20,8 +20,8 @@
#include <core/dbus/macros.h> #include <core/dbus/macros.h>
#include <string>
#include <chrono> #include <chrono>
#include <string>
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
@ -37,7 +37,9 @@ struct ApplicationManager {
static inline std::string name() { return "Launch"; } static inline std::string name() { return "Launch"; }
typedef anbox::dbus::interface::ApplicationManager Interface; typedef anbox::dbus::interface::ApplicationManager Interface;
typedef void ResultType; typedef void ResultType;
static inline std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } static inline std::chrono::milliseconds default_timeout() {
return std::chrono::seconds{1};
}
}; };
}; };
}; };
@ -48,7 +50,8 @@ struct ApplicationManager {
namespace core { namespace core {
namespace dbus { namespace dbus {
namespace traits { namespace traits {
template<> struct Service<anbox::dbus::interface::ApplicationManager> { template <>
struct Service<anbox::dbus::interface::ApplicationManager> {
static inline const std::string& interface_name() { static inline const std::string& interface_name() {
static const std::string s{"org.anbox.ApplicationManager"}; static const std::string s{"org.anbox.ApplicationManager"};
return s; return s;

View file

@ -16,21 +16,19 @@
*/ */
#include "anbox/dbus/skeleton/application_manager.h" #include "anbox/dbus/skeleton/application_manager.h"
#include "anbox/dbus/interface.h"
#include "anbox/android/intent.h" #include "anbox/android/intent.h"
#include "anbox/dbus/interface.h"
#include "anbox/logger.h" #include "anbox/logger.h"
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace skeleton { namespace skeleton {
ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus, ApplicationManager::ApplicationManager(
const core::dbus::Object::Ptr& object, const core::dbus::Bus::Ptr &bus, const core::dbus::Object::Ptr &object,
const std::shared_ptr<anbox::ApplicationManager> &impl) : const std::shared_ptr<anbox::ApplicationManager> &impl)
bus_(bus), : bus_(bus), object_(object), impl_(impl) {
object_(object), object_->install_method_handler<
impl_(impl) { anbox::dbus::interface::ApplicationManager::Methods::Launch>(
object_->install_method_handler<anbox::dbus::interface::ApplicationManager::Methods::Launch>(
[this](const core::dbus::Message::Ptr &msg) { [this](const core::dbus::Message::Ptr &msg) {
auto reader = msg->reader(); auto reader = msg->reader();
@ -47,10 +45,8 @@ ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus,
try { try {
launch(intent); launch(intent);
reply = core::dbus::Message::make_method_return(msg); reply = core::dbus::Message::make_method_return(msg);
} } catch (std::exception const &err) {
catch (std::exception const &err) { reply = core::dbus::Message::make_error(msg, "org.anbox.Error.Failed",
reply = core::dbus::Message::make_error(msg,
"org.anbox.Error.Failed",
err.what()); err.what());
} }
@ -58,8 +54,7 @@ ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus,
}); });
} }
ApplicationManager::~ApplicationManager() { ApplicationManager::~ApplicationManager() {}
}
void ApplicationManager::launch(const android::Intent &intent) { void ApplicationManager::launch(const android::Intent &intent) {
impl_->launch(intent); impl_->launch(intent);

View file

@ -16,31 +16,33 @@
*/ */
#include "anbox/dbus/skeleton/service.h" #include "anbox/dbus/skeleton/service.h"
#include "anbox/dbus/skeleton/application_manager.h"
#include "anbox/dbus/interface.h" #include "anbox/dbus/interface.h"
#include "anbox/dbus/skeleton/application_manager.h"
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace skeleton { namespace skeleton {
std::shared_ptr<Service> Service::create_for_bus(const core::dbus::Bus::Ptr &bus, std::shared_ptr<Service> Service::create_for_bus(
const core::dbus::Bus::Ptr &bus,
const std::shared_ptr<anbox::ApplicationManager> &application_manager) { const std::shared_ptr<anbox::ApplicationManager> &application_manager) {
auto service = core::dbus::Service::add_service(bus, anbox::dbus::interface::Service::name()); auto service = core::dbus::Service::add_service(
auto object = service->add_object_for_path(anbox::dbus::interface::Service::path()); bus, anbox::dbus::interface::Service::name());
auto object =
service->add_object_for_path(anbox::dbus::interface::Service::path());
return std::make_shared<Service>(bus, service, object, application_manager); return std::make_shared<Service>(bus, service, object, application_manager);
} }
Service::Service(const core::dbus::Bus::Ptr &bus, Service::Service(
const core::dbus::Service::Ptr& service, const core::dbus::Bus::Ptr &bus, const core::dbus::Service::Ptr &service,
const core::dbus::Object::Ptr &object, const core::dbus::Object::Ptr &object,
const std::shared_ptr<anbox::ApplicationManager> &application_manager) : const std::shared_ptr<anbox::ApplicationManager> &application_manager)
bus_(bus), : bus_(bus),
service_(service), service_(service),
object_(object), object_(object),
application_manager_(std::make_shared<ApplicationManager>(bus_, object_, application_manager)) { application_manager_(std::make_shared<ApplicationManager>(
} bus_, object_, application_manager)) {}
Service::~Service() { Service::~Service() {}
}
} // namespace skeleton } // namespace skeleton
} // namespace dbus } // namespace dbus
} // namespace anbox } // namespace anbox

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_DBUS_SKELETON_SERVICE_H_ #ifndef ANBOX_DBUS_SKELETON_SERVICE_H_
#define ANBOX_DBUS_SKELETON_SERVICE_H_ #define ANBOX_DBUS_SKELETON_SERVICE_H_
#include "anbox/do_not_copy_or_move.h"
#include "anbox/application_manager.h" #include "anbox/application_manager.h"
#include "anbox/do_not_copy_or_move.h"
#include <core/dbus/bus.h> #include <core/dbus/bus.h>
#include <core/dbus/object.h> #include <core/dbus/object.h>
@ -31,11 +31,12 @@ namespace skeleton {
class ApplicationManager; class ApplicationManager;
class Service : public DoNotCopyOrMove { class Service : public DoNotCopyOrMove {
public: public:
static std::shared_ptr<Service> create_for_bus(const core::dbus::Bus::Ptr &bus, static std::shared_ptr<Service> create_for_bus(
const core::dbus::Bus::Ptr &bus,
const std::shared_ptr<anbox::ApplicationManager> &application_manager); const std::shared_ptr<anbox::ApplicationManager> &application_manager);
Service(const core::dbus::Bus::Ptr &bus, Service(
const core::dbus::Service::Ptr& service, const core::dbus::Bus::Ptr &bus, const core::dbus::Service::Ptr &service,
const core::dbus::Object::Ptr &object, const core::dbus::Object::Ptr &object,
const std::shared_ptr<anbox::ApplicationManager> &application_manager); const std::shared_ptr<anbox::ApplicationManager> &application_manager);
~Service(); ~Service();

View file

@ -22,36 +22,30 @@
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace stub { namespace stub {
std::shared_ptr<ApplicationManager> ApplicationManager::create_for_bus(const core::dbus::Bus::Ptr &bus) { std::shared_ptr<ApplicationManager> ApplicationManager::create_for_bus(
auto service = core::dbus::Service::use_service(bus, anbox::dbus::interface::Service::name()); const core::dbus::Bus::Ptr &bus) {
auto object = service->add_object_for_path(anbox::dbus::interface::Service::path()); auto service = core::dbus::Service::use_service(
bus, anbox::dbus::interface::Service::name());
auto object =
service->add_object_for_path(anbox::dbus::interface::Service::path());
return std::make_shared<ApplicationManager>(bus, service, object); return std::make_shared<ApplicationManager>(bus, service, object);
} }
ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus, ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus,
const core::dbus::Service::Ptr &service, const core::dbus::Service::Ptr &service,
const core::dbus::Object::Ptr& object) : const core::dbus::Object::Ptr &object)
bus_(bus), : bus_(bus), service_(service), object_(object) {}
service_(service),
object_(object) {
}
ApplicationManager::~ApplicationManager() { ApplicationManager::~ApplicationManager() {}
}
void ApplicationManager::launch(const android::Intent &intent) { void ApplicationManager::launch(const android::Intent &intent) {
auto result = object_->invoke_method_synchronously< auto result = object_->invoke_method_synchronously<
anbox::dbus::interface::ApplicationManager::Methods::Launch, anbox::dbus::interface::ApplicationManager::Methods::Launch,
anbox::dbus::interface::ApplicationManager::Methods::Launch::ResultType>( anbox::dbus::interface::ApplicationManager::Methods::Launch::ResultType>(
intent.action, intent.action, intent.uri, intent.type, intent.flags, intent.package,
intent.uri,
intent.type,
intent.flags,
intent.package,
intent.component); intent.component);
if (result.is_error()) if (result.is_error()) throw std::runtime_error(result.error().print());
throw std::runtime_error(result.error().print());
} }
} // namespace skeleton } // namespace skeleton
} // namespace dbus } // namespace dbus

View file

@ -29,7 +29,8 @@ namespace dbus {
namespace stub { namespace stub {
class ApplicationManager : public anbox::ApplicationManager { class ApplicationManager : public anbox::ApplicationManager {
public: public:
static std::shared_ptr<ApplicationManager> create_for_bus(const core::dbus::Bus::Ptr &bus); static std::shared_ptr<ApplicationManager> create_for_bus(
const core::dbus::Bus::Ptr &bus);
ApplicationManager(const core::dbus::Bus::Ptr &bus, ApplicationManager(const core::dbus::Bus::Ptr &bus,
const core::dbus::Service::Ptr &service, const core::dbus::Service::Ptr &service,

View file

@ -26,13 +26,10 @@ namespace anbox {
class DeferAction : public DoNotCopyOrMove { class DeferAction : public DoNotCopyOrMove {
public: public:
DeferAction(const std::function<void()> action) : DeferAction(const std::function<void()> action) : action_(action) {}
action_(action) {
}
~DeferAction() { ~DeferAction() {
if (action_) if (action_) action_();
action_();
} }
private: private:

View file

@ -20,8 +20,7 @@
namespace anbox { namespace anbox {
class DoNotCopyOrMove class DoNotCopyOrMove {
{
public: public:
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete; DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete; DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
@ -32,7 +31,6 @@ public:
protected: protected:
DoNotCopyOrMove() = default; DoNotCopyOrMove() = default;
}; };
} }
#endif #endif

View file

@ -21,8 +21,10 @@
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
/** /**
* @brief Defines different types of density being used in an Android system. See the * @brief Defines different types of density being used in an Android system.
* documentation in frameworks/base/core/java/android/util/DisplayMetrics.java * See the
* documentation in
* frameworks/base/core/java/android/util/DisplayMetrics.java
* of the Android source tree which defines the different types. * of the Android source tree which defines the different types.
*/ */
enum class DensityType { enum class DensityType {

View file

@ -63,8 +63,7 @@ bool bindFbo(GLuint* fbo, GLuint tex) {
s_gles2.glGenFramebuffers(1, fbo); s_gles2.glGenFramebuffers(1, fbo);
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo); s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES,
GL_COLOR_ATTACHMENT0_OES,
GL_TEXTURE_2D, tex, 0); GL_TEXTURE_2D, tex, 0);
GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER); GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE_OES) { if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
@ -77,9 +76,7 @@ bool bindFbo(GLuint* fbo, GLuint tex) {
return true; return true;
} }
void unbindFbo() { void unbindFbo() { s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0); }
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Helper class to use a ColorBuffer::Helper context. // Helper class to use a ColorBuffer::Helper context.
// Usage is pretty simple: // Usage is pretty simple:
@ -102,9 +99,7 @@ public:
bool isOk() const { return mHelper != NULL; } bool isOk() const { return mHelper != NULL; }
~ScopedHelperContext() { ~ScopedHelperContext() { release(); }
release();
}
void release() { void release() {
if (mHelper) { if (mHelper) {
@ -112,6 +107,7 @@ public:
mHelper = NULL; mHelper = NULL;
} }
} }
private: private:
ColorBuffer::Helper* mHelper; ColorBuffer::Helper* mHelper;
}; };
@ -119,12 +115,9 @@ private:
} // namespace } // namespace
// static // static
ColorBuffer* ColorBuffer::create(EGLDisplay p_display, ColorBuffer* ColorBuffer::create(EGLDisplay p_display, int p_width,
int p_width, int p_height, GLenum p_internalFormat,
int p_height, bool has_eglimage_texture_2d, Helper* helper) {
GLenum p_internalFormat,
bool has_eglimage_texture_2d,
Helper* helper) {
GLenum texInternalFormat = 0; GLenum texInternalFormat = 0;
switch (p_internalFormat) { switch (p_internalFormat) {
@ -157,15 +150,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
int nComp = (texInternalFormat == GL_RGB ? 3 : 4); int nComp = (texInternalFormat == GL_RGB ? 3 : 4);
char* zBuff = static_cast<char*>(::calloc(nComp * p_width * p_height, 1)); char* zBuff = static_cast<char*>(::calloc(nComp * p_width * p_height, 1));
s_gles2.glTexImage2D(GL_TEXTURE_2D, s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, texInternalFormat, p_width, p_height,
0, 0, texInternalFormat, GL_UNSIGNED_BYTE, zBuff);
texInternalFormat,
p_width,
p_height,
0,
texInternalFormat,
GL_UNSIGNED_BYTE,
zBuff);
::free(zBuff); ::free(zBuff);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -178,15 +164,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
// //
s_gles2.glGenTextures(1, &cb->m_blitTex); s_gles2.glGenTextures(1, &cb->m_blitTex);
s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex); s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
s_gles2.glTexImage2D(GL_TEXTURE_2D, s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, texInternalFormat, p_width, p_height,
0, 0, texInternalFormat, GL_UNSIGNED_BYTE, NULL);
texInternalFormat,
p_width,
p_height,
0,
texInternalFormat,
GL_UNSIGNED_BYTE,
NULL);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -199,18 +178,12 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
if (has_eglimage_texture_2d) { if (has_eglimage_texture_2d) {
cb->m_eglImage = s_egl.eglCreateImageKHR( cb->m_eglImage = s_egl.eglCreateImageKHR(
p_display, p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
s_egl.eglGetCurrentContext(), (EGLClientBuffer)SafePointerFromUInt(cb->m_tex), NULL);
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)SafePointerFromUInt(cb->m_tex),
NULL);
cb->m_blitEGLImage = s_egl.eglCreateImageKHR( cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
p_display, p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
s_egl.eglGetCurrentContext(), (EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), NULL);
EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex),
NULL);
} }
cb->m_resizer = new TextureResize(p_width, p_height); cb->m_resizer = new TextureResize(p_width, p_height);
@ -218,8 +191,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
return cb; return cb;
} }
ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper) : ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper)
m_tex(0), : m_tex(0),
m_blitTex(0), m_blitTex(0),
m_eglImage(NULL), m_eglImage(NULL),
m_blitEGLImage(NULL), m_blitEGLImage(NULL),
@ -248,13 +221,8 @@ ColorBuffer::~ColorBuffer() {
delete m_resizer; delete m_resizer;
} }
void ColorBuffer::readPixels(int x, void ColorBuffer::readPixels(int x, int y, int width, int height,
int y, GLenum p_format, GLenum p_type, void* pixels) {
int width,
int height,
GLenum p_format,
GLenum p_type,
void* pixels) {
ScopedHelperContext context(m_helper); ScopedHelperContext context(m_helper);
if (!context.isOk()) { if (!context.isOk()) {
return; return;
@ -266,13 +234,8 @@ void ColorBuffer::readPixels(int x,
} }
} }
void ColorBuffer::subUpdate(int x, void ColorBuffer::subUpdate(int x, int y, int width, int height,
int y, GLenum p_format, GLenum p_type, void* pixels) {
int width,
int height,
GLenum p_format,
GLenum p_type,
void* pixels) {
ScopedHelperContext context(m_helper); ScopedHelperContext context(m_helper);
if (!context.isOk()) { if (!context.isOk()) {
return; return;
@ -280,12 +243,11 @@ void ColorBuffer::subUpdate(int x,
s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex); s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1); s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
s_gles2.glTexSubImage2D( s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, p_format,
GL_TEXTURE_2D, 0, x, y, width, height, p_format, p_type, pixels); p_type, pixels);
} }
bool ColorBuffer::blitFromCurrentReadBuffer() bool ColorBuffer::blitFromCurrentReadBuffer() {
{
RenderThreadInfo* tInfo = RenderThreadInfo::get(); RenderThreadInfo* tInfo = RenderThreadInfo::get();
if (!tInfo->currContext.Ptr()) { if (!tInfo->currContext.Ptr()) {
// no Current context // no Current context
@ -302,18 +264,17 @@ bool ColorBuffer::blitFromCurrentReadBuffer()
s_gles2.glGenTextures(1, &tmpTex); s_gles2.glGenTextures(1, &tmpTex);
s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex); s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage); s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
m_width, m_height); m_height);
s_gles2.glDeleteTextures(1, &tmpTex); s_gles2.glDeleteTextures(1, &tmpTex);
s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind); s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
} } else {
else {
s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind); s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
s_gles1.glGenTextures(1, &tmpTex); s_gles1.glGenTextures(1, &tmpTex);
s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex); s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage); s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
m_width, m_height); m_height);
s_gles1.glDeleteTextures(1, &tmpTex); s_gles1.glDeleteTextures(1, &tmpTex);
s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind); s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
} }
@ -328,7 +289,9 @@ bool ColorBuffer::blitFromCurrentReadBuffer()
} }
// Save current viewport and match it to the current colorbuffer size. // Save current viewport and match it to the current colorbuffer size.
GLint vport[4] = { 0, }; GLint vport[4] = {
0,
};
s_gles2.glGetIntegerv(GL_VIEWPORT, vport); s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
s_gles2.glViewport(0, 0, m_width, m_height); s_gles2.glViewport(0, 0, m_width, m_height);
@ -352,8 +315,7 @@ bool ColorBuffer::bindToTexture() {
} }
if (tInfo->currContext->isGL2()) { if (tInfo->currContext->isGL2()) {
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage); s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
} } else {
else {
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage); s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
} }
return true; return true;
@ -368,10 +330,11 @@ bool ColorBuffer::bindToRenderbuffer() {
return false; return false;
} }
if (tInfo->currContext->isGL2()) { if (tInfo->currContext->isGL2()) {
s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage); s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
} m_eglImage);
else { } else {
s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage); s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
m_eglImage);
} }
return true; return true;
} }
@ -382,8 +345,8 @@ void ColorBuffer::readback(unsigned char* img) {
return; return;
} }
if (bindFbo(&m_fbo, m_tex)) { if (bindFbo(&m_fbo, m_tex)) {
s_gles2.glReadPixels( s_gles2.glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE,
0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, img); img);
unbindFbo(); unbindFbo();
} }
} }

View file

@ -76,12 +76,9 @@ public:
// |has_eglimage_texture_2d| should be true iff the display supports // |has_eglimage_texture_2d| should be true iff the display supports
// the EGL_KHR_gl_texture_2D_image extension. // the EGL_KHR_gl_texture_2D_image extension.
// Returns NULL on failure. // Returns NULL on failure.
static ColorBuffer* create(EGLDisplay p_display, static ColorBuffer* create(EGLDisplay p_display, int p_width, int p_height,
int p_width,
int p_height,
GLenum p_internalFormat, GLenum p_internalFormat,
bool has_eglimage_texture_2d, bool has_eglimage_texture_2d, Helper* helper);
Helper* helper);
// Destructor. // Destructor.
~ColorBuffer(); ~ColorBuffer();
@ -91,22 +88,12 @@ public:
GLuint getHeight() const { return m_height; } GLuint getHeight() const { return m_height; }
// Read the ColorBuffer instance's pixel values into host memory. // Read the ColorBuffer instance's pixel values into host memory.
void readPixels(int x, void readPixels(int x, int y, int width, int height, GLenum p_format,
int y, GLenum p_type, void* pixels);
int width,
int height,
GLenum p_format,
GLenum p_type,
void *pixels);
// Update the ColorBuffer instance's pixel values from host memory. // Update the ColorBuffer instance's pixel values from host memory.
void subUpdate(int x, void subUpdate(int x, int y, int width, int height, GLenum p_format,
int y, GLenum p_type, void* pixels);
int width,
int height,
GLenum p_format,
GLenum p_type,
void *pixels);
// Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's // Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's
// EGLImage. This is intended to implement glEGLImageTargetTexture2DOES() // EGLImage. This is intended to implement glEGLImageTargetTexture2DOES()
@ -128,6 +115,7 @@ public:
void readback(unsigned char* img); void readback(unsigned char* img);
void bind(); void bind();
private: private:
ColorBuffer(); // no default constructor. ColorBuffer(); // no default constructor.

View file

@ -22,18 +22,14 @@ std::shared_ptr<DisplayManager> display_mgr;
class NullDisplayManager : public DisplayManager { class NullDisplayManager : public DisplayManager {
public: public:
DisplayInfo display_info() const override { DisplayInfo display_info() const override { return {1280, 720}; }
return {1280, 720};
}
}; };
} }
DisplayManager::~DisplayManager() { DisplayManager::~DisplayManager() {}
}
std::shared_ptr<DisplayManager> DisplayManager::get() { std::shared_ptr<DisplayManager> DisplayManager::get() {
if (!display_mgr) if (!display_mgr) display_mgr = std::make_shared<NullDisplayManager>();
display_mgr = std::make_shared<NullDisplayManager>();
return display_mgr; return display_mgr;
} }

View file

@ -14,28 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
#include "ReadBuffer.h" #include "ReadBuffer.h"
#include <string.h>
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <string.h>
#include "ErrorLog.h" #include "ErrorLog.h"
ReadBuffer::ReadBuffer(size_t bufsize) ReadBuffer::ReadBuffer(size_t bufsize) {
{
m_size = bufsize; m_size = bufsize;
m_buf = (unsigned char*)malloc(m_size * sizeof(unsigned char)); m_buf = (unsigned char*)malloc(m_size * sizeof(unsigned char));
m_validData = 0; m_validData = 0;
m_readPtr = m_buf; m_readPtr = m_buf;
} }
ReadBuffer::~ReadBuffer() ReadBuffer::~ReadBuffer() { free(m_buf); }
{
free(m_buf);
}
int ReadBuffer::getData(IOStream *stream) int ReadBuffer::getData(IOStream* stream) {
{ if (stream == NULL) return -1;
if(stream == NULL)
return -1;
if ((m_validData > 0) && (m_readPtr > m_buf)) { if ((m_validData > 0) && (m_readPtr > m_buf)) {
memmove(m_buf, m_readPtr, m_validData); memmove(m_buf, m_readPtr, m_validData);
} }
@ -66,8 +60,7 @@ int ReadBuffer::getData(IOStream *stream)
return -1; return -1;
} }
void ReadBuffer::consume(size_t amount) void ReadBuffer::consume(size_t amount) {
{
assert(amount <= m_validData); assert(amount <= m_validData);
m_validData -= amount; m_validData -= amount;
m_readPtr += amount; m_readPtr += amount;

View file

@ -24,7 +24,9 @@ public:
~ReadBuffer(); ~ReadBuffer();
int getData(IOStream *stream); // get fresh data from the stream int getData(IOStream *stream); // get fresh data from the stream
unsigned char *buf() { return m_readPtr; } // return the next read location unsigned char *buf() { return m_readPtr; } // return the next read location
size_t validData() { return m_validData; } // return the amount of valid data in readptr size_t validData() {
return m_validData;
} // return the amount of valid data in readptr
void consume(size_t amount); // notify that 'amount' data has been consumed; void consume(size_t amount); // notify that 'amount' data has been consumed;
private: private:
unsigned char *m_buf; unsigned char *m_buf;

View file

@ -44,8 +44,7 @@ static RenderWindow* s_renderWindow = NULL;
static IOStream* createRenderThread(int p_stream_buffer_size, static IOStream* createRenderThread(int p_stream_buffer_size,
unsigned int clientFlags); unsigned int clientFlags);
RENDER_APICALL int RENDER_APIENTRY initLibrary(void) RENDER_APICALL int RENDER_APIENTRY initLibrary(void) {
{
// //
// Load EGL Plugin // Load EGL Plugin
// //
@ -91,7 +90,8 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
// For now, this feature is disabled entirely for the following // For now, this feature is disabled entirely for the following
// reasons: // reasons:
// //
// - It must be disabled on Windows at all times, otherwise the main window becomes // - It must be disabled on Windows at all times, otherwise the main window
// becomes
// unresponsive after a few seconds of user interaction (e.g. trying to // unresponsive after a few seconds of user interaction (e.g. trying to
// move it over the desktop). Probably due to the subtle issues around // move it over the desktop). Probably due to the subtle issues around
// input on this platform (input-queue is global, message-queue is // input on this platform (input-queue is global, message-queue is
@ -100,11 +100,13 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
// //
// - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption // - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption
// issues with the GL state of the main window when using the SDL UI. // issues with the GL state of the main window when using the SDL UI.
// After the switch to Qt, this is no longer necessary and may actually cause // After the switch to Qt, this is no longer necessary and may actually
// cause
// undesired interactions between the UI thread and the RenderWindow thread: // undesired interactions between the UI thread and the RenderWindow thread:
// for example, in a multi-monitor setup the context might be recreated when // for example, in a multi-monitor setup the context might be recreated when
// dragging the window between monitors, triggering a Qt-specific callback // dragging the window between monitors, triggering a Qt-specific callback
// in the context of RenderWindow thread, which will become blocked on the UI // in the context of RenderWindow thread, which will become blocked on the
// UI
// thread, which may in turn be blocked on something else. // thread, which may in turn be blocked on something else.
bool kUseThread = false; bool kUseThread = false;
@ -137,8 +139,7 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
return true; return true;
} }
RENDER_APICALL void RENDER_APIENTRY getHardwareStrings( RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(const char** vendor,
const char** vendor,
const char** renderer, const char** renderer,
const char** version) { const char** version) {
if (s_renderWindow && if (s_renderWindow &&
@ -148,8 +149,7 @@ RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(
*vendor = *renderer = *version = NULL; *vendor = *renderer = *version = NULL;
} }
RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void) RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void) {
{
bool ret = false; bool ret = false;
// open a dummy connection to the renderer to make it // open a dummy connection to the renderer to make it
@ -176,31 +176,22 @@ RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void)
return ret; return ret;
} }
RENDER_APICALL bool RENDER_APIENTRY showOpenGLSubwindow( RENDER_APICALL bool RENDER_APIENTRY
FBNativeWindowType window_id, showOpenGLSubwindow(FBNativeWindowType window_id, int wx, int wy, int ww,
int wx, int wh, int fbw, int fbh, float dpr, float zRot) {
int wy,
int ww,
int wh,
int fbw,
int fbh,
float dpr,
float zRot)
{
RenderWindow* window = s_renderWindow; RenderWindow* window = s_renderWindow;
if (window) { if (window) {
return window->setupSubWindow(window_id,wx,wy,ww,wh,fbw,fbh,dpr,zRot); return window->setupSubWindow(window_id, wx, wy, ww, wh, fbw, fbh, dpr,
zRot);
} }
// XXX: should be implemented by sending the renderer process // XXX: should be implemented by sending the renderer process
// a request // a request
ERR("%s not implemented for separate renderer process !!!\n", ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__);
__FUNCTION__);
return false; return false;
} }
RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void) RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void) {
{
RenderWindow* window = s_renderWindow; RenderWindow* window = s_renderWindow;
if (window) { if (window) {
@ -209,8 +200,7 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
// XXX: should be implemented by sending the renderer process // XXX: should be implemented by sending the renderer process
// a request // a request
ERR("%s not implemented for separate renderer process !!!\n", ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__);
__FUNCTION__);
return false; return false;
} }
@ -218,8 +208,8 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
int gRendererStreamMode = DEFAULT_STREAM_MODE; int gRendererStreamMode = DEFAULT_STREAM_MODE;
IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) IOStream* createRenderThread(int p_stream_buffer_size,
{ unsigned int clientFlags) {
SocketStream* stream = NULL; SocketStream* stream = NULL;
if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) { if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) {

View file

@ -17,16 +17,12 @@
#include "OpenGLESDispatch/EGLDispatch.h" #include "OpenGLESDispatch/EGLDispatch.h"
RenderContext* RenderContext::create(EGLDisplay display, RenderContext* RenderContext::create(EGLDisplay display, EGLConfig config,
EGLConfig config, EGLContext sharedContext, bool isGl2) {
EGLContext sharedContext, const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, isGl2 ? 2 : 1,
bool isGl2) { EGL_NONE};
const EGLint contextAttribs[] = { EGLContext context =
EGL_CONTEXT_CLIENT_VERSION, isGl2 ? 2 : 1, s_egl.eglCreateContext(display, config, sharedContext, contextAttribs);
EGL_NONE
};
EGLContext context = s_egl.eglCreateContext(
display, config, sharedContext, contextAttribs);
if (context == EGL_NO_CONTEXT) { if (context == EGL_NO_CONTEXT) {
return NULL; return NULL;
} }
@ -34,13 +30,8 @@ RenderContext* RenderContext::create(EGLDisplay display,
return new RenderContext(display, context, isGl2); return new RenderContext(display, context, isGl2);
} }
RenderContext::RenderContext(EGLDisplay display, RenderContext::RenderContext(EGLDisplay display, EGLContext context, bool isGl2)
EGLContext context, : mDisplay(display), mContext(context), mIsGl2(isGl2), mContextData() {}
bool isGl2) :
mDisplay(display),
mContext(context),
mIsGl2(isGl2),
mContextData() {}
RenderContext::~RenderContext() { RenderContext::~RenderContext() {
if (mContext != EGL_NO_CONTEXT) { if (mContext != EGL_NO_CONTEXT) {

View file

@ -16,8 +16,8 @@
#ifndef _LIBRENDER_RENDER_CONTEXT_H #ifndef _LIBRENDER_RENDER_CONTEXT_H
#define _LIBRENDER_RENDER_CONTEXT_H #define _LIBRENDER_RENDER_CONTEXT_H
#include "emugl/common/smart_ptr.h"
#include "GLDecoderContextData.h" #include "GLDecoderContextData.h"
#include "emugl/common/smart_ptr.h"
#include <EGL/egl.h> #include <EGL/egl.h>
@ -32,10 +32,8 @@ public:
// |sharedContext| is either EGL_NO_CONTEXT of a host EGLContext handle. // |sharedContext| is either EGL_NO_CONTEXT of a host EGLContext handle.
// |isGl2| is true iff the new context will be used with GLESv2, or // |isGl2| is true iff the new context will be used with GLESv2, or
// GLESv1 otherwise. // GLESv1 otherwise.
static RenderContext *create(EGLDisplay display, static RenderContext* create(EGLDisplay display, EGLConfig config,
EGLConfig config, EGLContext sharedContext, bool isGL2 = false);
EGLContext sharedContext,
bool isGL2 = false);
// Destructor. // Destructor.
~RenderContext(); ~RenderContext();
@ -53,9 +51,7 @@ public:
private: private:
RenderContext(); RenderContext();
RenderContext(EGLDisplay display, RenderContext(EGLDisplay display, EGLContext context, bool isGl2);
EGLContext context,
bool isGl2);
private: private:
EGLDisplay mDisplay; EGLDisplay mDisplay;

View file

@ -15,12 +15,12 @@
*/ */
#include "RenderControl.h" #include "RenderControl.h"
#include "DispatchTables.h"
#include "RendererConfig.h"
#include "Renderer.h"
#include "RenderThreadInfo.h"
#include "ChecksumCalculatorThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h"
#include "DispatchTables.h"
#include "DisplayManager.h" #include "DisplayManager.h"
#include "RenderThreadInfo.h"
#include "Renderer.h"
#include "RendererConfig.h"
#include "OpenGLESDispatch/EGLDispatch.h" #include "OpenGLESDispatch/EGLDispatch.h"
@ -33,18 +33,14 @@
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;
void registerLayerComposer(const std::shared_ptr<anbox::graphics::LayerComposer> &c) void registerLayerComposer(
{ const std::shared_ptr<anbox::graphics::LayerComposer> &c) {
composer = c; composer = c;
} }
static GLint rcGetRendererVersion() static GLint rcGetRendererVersion() { return rendererVersion; }
{
return rendererVersion;
}
static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor) static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return EGL_FALSE; return EGL_FALSE;
@ -55,8 +51,7 @@ static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor)
return EGL_TRUE; return EGL_TRUE;
} }
static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) static EGLint rcQueryEGLString(EGLenum name, void *buffer, EGLint bufferSize) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -76,8 +71,7 @@ static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize)
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;
@ -88,8 +82,7 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
else else
str = reinterpret_cast<const char *>(s_gles1.glGetString(name)); str = reinterpret_cast<const char *>(s_gles1.glGetString(name));
if (str) if (str) result += 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
@ -110,8 +103,7 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
for (const auto &extension : unsupported_extensions) { for (const auto &extension : unsupported_extensions) {
size_t start_pos = approved_extensions.find(extension); size_t start_pos = approved_extensions.find(extension);
if(start_pos == std::string::npos) if (start_pos == std::string::npos) continue;
continue;
approved_extensions.replace(start_pos, extension.length(), ""); approved_extensions.replace(start_pos, extension.length(), "");
} }
@ -120,15 +112,13 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
int nextBufferSize = result.size() + 1; int nextBufferSize = result.size() + 1;
if (!buffer || nextBufferSize > bufferSize) if (!buffer || nextBufferSize > bufferSize) return -nextBufferSize;
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;
} }
static EGLint rcGetNumConfigs(uint32_t* p_numAttribs) static EGLint rcGetNumConfigs(uint32_t *p_numAttribs) {
{
int numConfigs = 0, numAttribs = 0; int numConfigs = 0, numAttribs = 0;
Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs); Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
@ -138,28 +128,23 @@ static EGLint rcGetNumConfigs(uint32_t* p_numAttribs)
return numConfigs; return numConfigs;
} }
static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) static EGLint rcGetConfigs(uint32_t bufSize, GLuint *buffer) {
{
GLuint bufferSize = (GLuint)bufSize; GLuint bufferSize = (GLuint)bufSize;
return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer); return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer);
} }
static EGLint rcChooseConfig(EGLint *attribs, static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size,
uint32_t attribs_size, uint32_t *configs, uint32_t configs_size) {
uint32_t *configs,
uint32_t configs_size)
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb || attribs_size == 0) { if (!fb || attribs_size == 0) {
return 0; return 0;
} }
return fb->getConfigs()->chooseConfig( return fb->getConfigs()->chooseConfig(attribs, (EGLint *)configs,
attribs, (EGLint*)configs, (EGLint)configs_size); (EGLint)configs_size);
} }
static EGLint rcGetFBParam(EGLint param) static EGLint rcGetFBParam(EGLint param) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -196,9 +181,8 @@ static EGLint rcGetFBParam(EGLint param)
return ret; return ret;
} }
static uint32_t rcCreateContext(uint32_t config, static uint32_t rcCreateContext(uint32_t config, uint32_t share,
uint32_t share, uint32_t glVersion) uint32_t glVersion) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -206,12 +190,12 @@ static uint32_t rcCreateContext(uint32_t config,
// To make it consistent with the guest, create GLES2 context when GL // To make it consistent with the guest, create GLES2 context when GL
// version==2 or 3 // version==2 or 3
HandleType ret = fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3); HandleType ret =
fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3);
return ret; return ret;
} }
static void rcDestroyContext(uint32_t context) static void rcDestroyContext(uint32_t context) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -220,9 +204,8 @@ static void rcDestroyContext(uint32_t context)
fb->DestroyRenderContext(context); fb->DestroyRenderContext(context);
} }
static uint32_t rcCreateWindowSurface(uint32_t config, static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width,
uint32_t width, uint32_t height) uint32_t height) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -231,8 +214,7 @@ static uint32_t rcCreateWindowSurface(uint32_t config,
return fb->createWindowSurface(config, width, height); return fb->createWindowSurface(config, width, height);
} }
static void rcDestroyWindowSurface(uint32_t windowSurface) static void rcDestroyWindowSurface(uint32_t windowSurface) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -241,9 +223,8 @@ static void rcDestroyWindowSurface(uint32_t windowSurface)
fb->DestroyWindowSurface(windowSurface); fb->DestroyWindowSurface(windowSurface);
} }
static uint32_t rcCreateColorBuffer(uint32_t width, static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height,
uint32_t height, GLenum internalFormat) GLenum internalFormat) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -252,8 +233,7 @@ static uint32_t rcCreateColorBuffer(uint32_t width,
return fb->createColorBuffer(width, height, internalFormat); return fb->createColorBuffer(width, height, internalFormat);
} }
static int rcOpenColorBuffer2(uint32_t colorbuffer) static int rcOpenColorBuffer2(uint32_t colorbuffer) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return -1; return -1;
@ -263,13 +243,11 @@ static int rcOpenColorBuffer2(uint32_t colorbuffer)
// Deprecated, kept for compatibility with old system images only. // Deprecated, kept for compatibility with old system images only.
// Use rcOpenColorBuffer2 instead. // Use rcOpenColorBuffer2 instead.
static void rcOpenColorBuffer(uint32_t colorbuffer) static void rcOpenColorBuffer(uint32_t colorbuffer) {
{
(void)rcOpenColorBuffer2(colorbuffer); (void)rcOpenColorBuffer2(colorbuffer);
} }
static void rcCloseColorBuffer(uint32_t colorbuffer) static void rcCloseColorBuffer(uint32_t colorbuffer) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -277,8 +255,7 @@ static void rcCloseColorBuffer(uint32_t colorbuffer)
fb->closeColorBuffer(colorbuffer); fb->closeColorBuffer(colorbuffer);
} }
static int rcFlushWindowColorBuffer(uint32_t windowSurface) static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return -1; return -1;
@ -290,8 +267,7 @@ static int rcFlushWindowColorBuffer(uint32_t windowSurface)
} }
static void rcSetWindowColorBuffer(uint32_t windowSurface, static void rcSetWindowColorBuffer(uint32_t windowSurface,
uint32_t colorBuffer) uint32_t colorBuffer) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -299,9 +275,8 @@ static void rcSetWindowColorBuffer(uint32_t windowSurface,
fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer); fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer);
} }
static EGLint rcMakeCurrent(uint32_t context, static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf,
uint32_t drawSurf, uint32_t readSurf) uint32_t readSurf) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return EGL_FALSE; return EGL_FALSE;
@ -312,18 +287,13 @@ static EGLint rcMakeCurrent(uint32_t context,
return (ret ? EGL_TRUE : EGL_FALSE); return (ret ? EGL_TRUE : EGL_FALSE);
} }
static void rcFBPost(uint32_t colorBuffer) static void rcFBPost(uint32_t colorBuffer) { WARNING("Not implemented"); }
{
WARNING("Not implemented");
}
static void rcFBSetSwapInterval(EGLint interval) static void rcFBSetSwapInterval(EGLint interval) {
{
// XXX: TBD - should be implemented // XXX: TBD - should be implemented
} }
static void rcBindTexture(uint32_t colorBuffer) static void rcBindTexture(uint32_t colorBuffer) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -332,8 +302,7 @@ static void rcBindTexture(uint32_t colorBuffer)
fb->bindColorBufferToTexture(colorBuffer); fb->bindColorBufferToTexture(colorBuffer);
} }
static void rcBindRenderbuffer(uint32_t colorBuffer) static void rcBindRenderbuffer(uint32_t colorBuffer) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -342,18 +311,15 @@ static void rcBindRenderbuffer(uint32_t colorBuffer)
fb->bindColorBufferToRenderbuffer(colorBuffer); fb->bindColorBufferToRenderbuffer(colorBuffer);
} }
static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount,
EGLint postCount, int forRead) int forRead) {
{
// XXX: TBD - should be implemented // XXX: TBD - should be implemented
return 0; return 0;
} }
static void rcReadColorBuffer(uint32_t colorBuffer, static void rcReadColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
GLint x, GLint y, GLint width, GLint height, GLenum format,
GLint width, GLint height, GLenum type, void *pixels) {
GLenum format, GLenum type, void* pixels)
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return; return;
@ -362,11 +328,9 @@ static void rcReadColorBuffer(uint32_t colorBuffer,
fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
} }
static int rcUpdateColorBuffer(uint32_t colorBuffer, static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
GLint x, GLint y, GLint width, GLint height, GLenum format,
GLint width, GLint height, GLenum type, void *pixels) {
GLenum format, GLenum type, void* pixels)
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return -1; return -1;
@ -376,8 +340,8 @@ static int rcUpdateColorBuffer(uint32_t colorBuffer,
return 0; return 0;
} }
static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer) static uint32_t rcCreateClientImage(uint32_t context, EGLenum target,
{ GLuint buffer) {
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -386,8 +350,7 @@ static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buf
return fb->createClientImage(context, target, buffer); return fb->createClientImage(context, target, buffer);
} }
static int rcDestroyClientImage(uint32_t image) static int rcDestroyClientImage(uint32_t image) {
{
Renderer *fb = Renderer::get(); Renderer *fb = Renderer::get();
if (!fb) { if (!fb) {
return 0; return 0;
@ -400,9 +363,7 @@ static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) {
ChecksumCalculatorThreadInfo::setVersion(protocol); ChecksumCalculatorThreadInfo::setVersion(protocol);
} }
int rcGetNumDisplays() { int rcGetNumDisplays() { return 1; }
return 1;
}
int rcGetDisplayWidth(uint32_t display_id) { int rcGetDisplayWidth(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id); printf("%s: display_id=%d\n", __func__, display_id);
@ -442,27 +403,23 @@ void rcPostLayer(const char *name, uint32_t color_buffer,
int32_t sourceCropLeft, int32_t sourceCropTop, int32_t sourceCropLeft, int32_t sourceCropTop,
int32_t sourceCropRight, int32_t sourceCropBottom, int32_t sourceCropRight, int32_t sourceCropBottom,
int32_t displayFrameLeft, int32_t displayFrameTop, int32_t displayFrameLeft, int32_t displayFrameTop,
int32_t displayFrameRight, int32_t displayFrameBottom) int32_t displayFrameRight, int32_t displayFrameBottom) {
{
Renderable r{ Renderable r{
name, name,
color_buffer, color_buffer,
{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom}, {displayFrameLeft, displayFrameTop, displayFrameRight,
{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom} displayFrameBottom},
}; {sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}};
frame_layers.push_back(r); frame_layers.push_back(r);
} }
void rcPostAllLayersDone() void rcPostAllLayersDone() {
{ if (composer) composer->submit_layers(frame_layers);
if (composer)
composer->submit_layers(frame_layers);
frame_layers.clear(); frame_layers.clear();
} }
void initRenderControlContext(renderControl_decoder_context_t *dec) void initRenderControlContext(renderControl_decoder_context_t *dec) {
{
dec->rcGetRendererVersion = rcGetRendererVersion; dec->rcGetRendererVersion = rcGetRendererVersion;
dec->rcGetEGLVersion = rcGetEGLVersion; dec->rcGetEGLVersion = rcGetEGLVersion;
dec->rcQueryEGLString = rcQueryEGLString; dec->rcQueryEGLString = rcQueryEGLString;

View file

@ -27,6 +27,7 @@ class LayerComposer;
} // namespace anbox } // namespace anbox
void initRenderControlContext(renderControl_decoder_context_t *dec); void initRenderControlContext(renderControl_decoder_context_t *dec);
void registerLayerComposer(const std::shared_ptr<anbox::graphics::LayerComposer> &c); void registerLayerComposer(
const std::shared_ptr<anbox::graphics::LayerComposer> &c);
#endif #endif

View file

@ -15,11 +15,11 @@
*/ */
#include "RenderServer.h" #include "RenderServer.h"
#include <pthread.h>
#include <signal.h>
#include "RenderThread.h" #include "RenderThread.h"
#include "TcpStream.h" #include "TcpStream.h"
#include "UnixStream.h" #include "UnixStream.h"
#include <signal.h>
#include <pthread.h>
#include "OpenglRender/render_api.h" #include "OpenglRender/render_api.h"
@ -29,23 +29,13 @@
typedef std::set<RenderThread *> RenderThreadsSet; typedef std::set<RenderThread *> RenderThreadsSet;
RenderServer::RenderServer() : RenderServer::RenderServer() : m_lock(), m_listenSock(NULL), m_exiting(false) {}
m_lock(),
m_listenSock(NULL),
m_exiting(false)
{
}
RenderServer::~RenderServer()
{
delete m_listenSock;
}
RenderServer::~RenderServer() { delete m_listenSock; }
extern "C" int gRendererStreamMode; extern "C" int gRendererStreamMode;
RenderServer *RenderServer::create(char* addr, size_t addrLen) RenderServer *RenderServer::create(char *addr, size_t addrLen) {
{
RenderServer *server = new RenderServer(); RenderServer *server = new RenderServer();
if (!server) { if (!server) {
return NULL; return NULL;
@ -76,8 +66,7 @@ RenderServer *RenderServer::create(char* addr, size_t addrLen)
return server; return server;
} }
intptr_t RenderServer::main() intptr_t RenderServer::main() {
{
RenderThreadsSet threads; RenderThreadsSet threads;
while (1) { while (1) {
@ -115,8 +104,7 @@ intptr_t RenderServer::main()
// remove from the threads list threads which are // remove from the threads list threads which are
// no longer running // no longer running
// //
for (RenderThreadsSet::iterator n,t = threads.begin(); for (RenderThreadsSet::iterator n, t = threads.begin(); t != threads.end();
t != threads.end();
t = n) { t = n) {
// first find next iterator // first find next iterator
n = t; n = t;
@ -131,15 +119,13 @@ intptr_t RenderServer::main()
} }
// if the thread has been created and started, insert it to the list // if the thread has been created and started, insert it to the list
if (rt) if (rt) threads.insert(rt);
threads.insert(rt);
} }
// //
// Wait for all threads to finish // Wait for all threads to finish
// //
for (RenderThreadsSet::iterator t = threads.begin(); for (RenderThreadsSet::iterator t = threads.begin(); t != threads.end();
t != threads.end();
t++) { t++) {
(*t)->forceStop(); (*t)->forceStop();
(*t)->wait(NULL); (*t)->wait(NULL);

View file

@ -20,8 +20,7 @@
#include "emugl/common/mutex.h" #include "emugl/common/mutex.h"
#include "emugl/common/thread.h" #include "emugl/common/thread.h"
class RenderServer : public emugl::Thread class RenderServer : public emugl::Thread {
{
public: public:
static RenderServer *create(char *addr, size_t addrLen); static RenderServer *create(char *addr, size_t addrLen);
virtual ~RenderServer(); virtual ~RenderServer();

View file

@ -15,36 +15,30 @@
*/ */
#include "RenderThread.h" #include "RenderThread.h"
#include "Renderer.h"
#include "ReadBuffer.h" #include "ReadBuffer.h"
#include "RenderControl.h" #include "RenderControl.h"
#include "RenderThreadInfo.h" #include "RenderThreadInfo.h"
#include "Renderer.h"
#include "TimeUtils.h" #include "TimeUtils.h"
#include "OpenGLESDispatch/EGLDispatch.h"
#include "OpenGLESDispatch/GLESv2Dispatch.h"
#include "OpenGLESDispatch/GLESv1Dispatch.h"
#include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h" #include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
#include "OpenGLESDispatch/EGLDispatch.h"
#include "OpenGLESDispatch/GLESv1Dispatch.h"
#include "OpenGLESDispatch/GLESv2Dispatch.h"
#define STREAM_BUFFER_SIZE 4 * 1024 * 1024 #define STREAM_BUFFER_SIZE 4 * 1024 * 1024
RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) : RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock)
emugl::Thread(), : emugl::Thread(), m_lock(lock), m_stream(stream) {}
m_lock(lock),
m_stream(stream) {}
RenderThread::~RenderThread() { RenderThread::~RenderThread() { delete m_stream; }
delete m_stream;
}
// static // static
RenderThread *RenderThread::create(IOStream *stream, emugl::Mutex *lock) { RenderThread *RenderThread::create(IOStream *stream, emugl::Mutex *lock) {
return new RenderThread(stream, lock); return new RenderThread(stream, lock);
} }
void RenderThread::forceStop() { void RenderThread::forceStop() { m_stream->forceStop(); }
m_stream->forceStop();
}
intptr_t RenderThread::main() { intptr_t RenderThread::main() {
RenderThreadInfo tInfo; RenderThreadInfo tInfo;
@ -60,7 +54,6 @@ intptr_t RenderThread::main() {
ReadBuffer readBuf(STREAM_BUFFER_SIZE); ReadBuffer readBuf(STREAM_BUFFER_SIZE);
while (1) { while (1) {
int stat = readBuf.getData(m_stream); int stat = readBuf.getData(m_stream);
if (stat <= 0) { if (stat <= 0) {
break; break;
@ -74,7 +67,8 @@ intptr_t RenderThread::main() {
// //
// try to process some of the command buffer using the GLESv1 decoder // try to process some of the command buffer using the GLESv1 decoder
// //
size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream); size_t last =
tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
if (last > 0) { if (last > 0) {
progress = true; progress = true;
readBuf.consume(last); readBuf.consume(last);
@ -83,7 +77,8 @@ intptr_t RenderThread::main() {
// //
// try to process some of the command buffer using the GLESv2 decoder // try to process some of the command buffer using the GLESv2 decoder
// //
last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream); last =
tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
if (last > 0) { if (last > 0) {
progress = true; progress = true;
readBuf.consume(last); readBuf.consume(last);
@ -102,7 +97,6 @@ intptr_t RenderThread::main() {
m_lock->unlock(); m_lock->unlock();
} while (progress); } while (progress);
} }
// //
@ -110,7 +104,8 @@ intptr_t RenderThread::main() {
// //
Renderer::get()->bindContext(0, 0, 0); Renderer::get()->bindContext(0, 0, 0);
if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) { if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n"); fprintf(stderr,
"ERROR: RenderThread exiting with current context/surfaces\n");
} }
Renderer::get()->drainWindowSurface(); Renderer::get()->drainWindowSurface();

View file

@ -30,13 +30,9 @@ public:
static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT; static ::emugl::LazyInstance<ThreadInfoStore> s_tls = LAZY_INSTANCE_INIT;
RenderThreadInfo::RenderThreadInfo() { RenderThreadInfo::RenderThreadInfo() { s_tls->set(this); }
s_tls->set(this);
}
RenderThreadInfo::~RenderThreadInfo() { RenderThreadInfo::~RenderThreadInfo() { s_tls->set(NULL); }
s_tls->set(NULL);
}
RenderThreadInfo* RenderThreadInfo::get() { RenderThreadInfo* RenderThreadInfo::get() {
return static_cast<RenderThreadInfo*>(s_tls->get()); return static_cast<RenderThreadInfo*>(s_tls->get());

View file

@ -16,10 +16,10 @@
#ifndef _LIB_OPENGL_RENDER_THREAD_INFO_H #ifndef _LIB_OPENGL_RENDER_THREAD_INFO_H
#define _LIB_OPENGL_RENDER_THREAD_INFO_H #define _LIB_OPENGL_RENDER_THREAD_INFO_H
#include "RenderContext.h"
#include "WindowSurface.h"
#include "GLESv1Decoder.h" #include "GLESv1Decoder.h"
#include "GLESv2Decoder.h" #include "GLESv2Decoder.h"
#include "RenderContext.h"
#include "WindowSurface.h"
#include "renderControl_dec.h" #include "renderControl_dec.h"
#include <set> #include <set>

View file

@ -14,16 +14,16 @@
#include "RenderWindow.h" #include "RenderWindow.h"
#include "Renderer.h"
#include "emugl/common/logging.h" #include "emugl/common/logging.h"
#include "emugl/common/message_channel.h" #include "emugl/common/message_channel.h"
#include "emugl/common/mutex.h" #include "emugl/common/mutex.h"
#include "emugl/common/thread.h" #include "emugl/common/thread.h"
#include "Renderer.h"
#include <pthread.h>
#include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h>
#include <pthread.h>
#define DEBUG 0 #define DEBUG 0
@ -129,8 +129,7 @@ struct RenderWindowMessage {
result = true; result = true;
break; break;
default: default:;
;
} }
return result; return result;
} }
@ -240,12 +239,8 @@ private:
} // namespace } // namespace
RenderWindow::RenderWindow(EGLNativeDisplayType native_display, RenderWindow::RenderWindow(EGLNativeDisplayType native_display, bool use_thread)
bool use_thread) : : mValid(false), mHasSubWindow(false), mThread(NULL), mChannel(NULL) {
mValid(false),
mHasSubWindow(false),
mThread(NULL),
mChannel(NULL) {
if (use_thread) { if (use_thread) {
mChannel = new RenderWindowChannel(); mChannel = new RenderWindowChannel();
mThread = new RenderWindowThread(mChannel); mThread = new RenderWindowThread(mChannel);
@ -284,20 +279,14 @@ bool RenderWindow::getHardwareStrings(const char** vendor,
return false; return false;
} }
fb->getGLStrings(vendor, renderer, version); fb->getGLStrings(vendor, renderer, version);
D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n", D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n", *vendor, *renderer,
*vendor, *renderer, *version); *version);
return true; return true;
} }
bool RenderWindow::setupSubWindow(FBNativeWindowType window, bool RenderWindow::setupSubWindow(FBNativeWindowType window, int wx, int wy,
int wx, int ww, int wh, int fbw, int fbh, float dpr,
int wy,
int ww,
int wh,
int fbw,
int fbh,
float dpr,
float zRot) { float zRot) {
D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false"); D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");

View file

@ -71,8 +71,7 @@ public:
// Return misc. GL strings to the caller. On success, return true and sets // Return misc. GL strings to the caller. On success, return true and sets
// |*vendor| to the GL vendor string, |*renderer| to the GL renderer one, // |*vendor| to the GL vendor string, |*renderer| to the GL renderer one,
// and |*version| to the GL version one. On failure, return false. // and |*version| to the GL version one. On failure, return false.
bool getHardwareStrings(const char** vendor, bool getHardwareStrings(const char** vendor, const char** renderer,
const char** renderer,
const char** version); const char** version);
// Start displaying the emulated framebuffer using a sub-window of a // Start displaying the emulated framebuffer using a sub-window of a
@ -89,15 +88,8 @@ public:
// pipeline to reflect the new values. // pipeline to reflect the new values.
// //
// One can call removeSubWindow() to remove the sub-window. // One can call removeSubWindow() to remove the sub-window.
bool setupSubWindow(FBNativeWindowType window, bool setupSubWindow(FBNativeWindowType window, int wx, int wy, int ww, int wh,
int wx, int fbw, int fbh, float dpr, float rotation);
int wy,
int ww,
int wh,
int fbw,
int fbh,
float dpr,
float rotation);
// Remove the sub-window created by calling setupSubWindow(). // Remove the sub-window created by calling setupSubWindow().
// Note that this doesn't discard the content of the emulated framebuffer, // Note that this doesn't discard the content of the emulated framebuffer,

View file

@ -16,56 +16,34 @@
#include "Renderable.h" #include "Renderable.h"
Renderable::Renderable(const std::string &name, Renderable::Renderable(const std::string &name, const std::uint32_t &buffer,
const std::uint32_t &buffer,
const anbox::graphics::Rect &screen_position, const anbox::graphics::Rect &screen_position,
const anbox::graphics::Rect &crop, const anbox::graphics::Rect &crop,
const glm::mat4 &transformation, const glm::mat4 &transformation, const float &alpha)
const float &alpha) : : name_(name),
name_(name),
buffer_(buffer), buffer_(buffer),
screen_position_(screen_position), screen_position_(screen_position),
crop_(crop), crop_(crop),
transformation_(transformation), transformation_(transformation),
alpha_(alpha) alpha_(alpha) {}
{
}
Renderable::~Renderable() Renderable::~Renderable() {}
{
}
std::string Renderable::name() const std::string Renderable::name() const { return name_; }
{
return name_;
}
std::uint32_t Renderable::buffer() const std::uint32_t Renderable::buffer() const { return buffer_; }
{
return buffer_;
}
anbox::graphics::Rect Renderable::screen_position() const anbox::graphics::Rect Renderable::screen_position() const {
{
return screen_position_; return screen_position_;
} }
anbox::graphics::Rect Renderable::crop() const anbox::graphics::Rect Renderable::crop() const { return crop_; }
{
return crop_;
}
glm::mat4 Renderable::transformation() const glm::mat4 Renderable::transformation() const { return transformation_; }
{
return transformation_;
}
float Renderable::alpha() const float Renderable::alpha() const { return alpha_; }
{
return alpha_;
}
void Renderable::set_screen_position(const anbox::graphics::Rect &screen_position) void Renderable::set_screen_position(
{ const anbox::graphics::Rect &screen_position) {
screen_position_ = screen_position; screen_position_ = screen_position;
} }

View file

@ -26,15 +26,12 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
class Renderable class Renderable {
{
public: public:
Renderable(const std::string &name, Renderable(const std::string &name, const std::uint32_t &buffer,
const std::uint32_t &buffer,
const anbox::graphics::Rect &screen_position, const anbox::graphics::Rect &screen_position,
const anbox::graphics::Rect &crop = {}, const anbox::graphics::Rect &crop = {},
const glm::mat4 &transformation = {}, const glm::mat4 &transformation = {}, const float &alpha = 1.0f);
const float &alpha = 1.0f);
~Renderable(); ~Renderable();
std::string name() const; std::string name() const;

View file

@ -30,8 +30,8 @@
#include <stdio.h> #include <stdio.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
namespace { namespace {
@ -59,9 +59,7 @@ public:
} }
// Destructor will call release(). // Destructor will call release().
~ScopedBind() { ~ScopedBind() { release(); }
release();
}
private: private:
Renderer *mFb; Renderer *mFb;
@ -73,17 +71,12 @@ class ColorBufferHelper : public ColorBuffer::Helper {
public: public:
ColorBufferHelper(Renderer *fb) : mFb(fb) {} ColorBufferHelper(Renderer *fb) : mFb(fb) {}
virtual bool setupContext() { virtual bool setupContext() { return mFb->bind_locked(); }
return mFb->bind_locked();
}
virtual void teardownContext() { virtual void teardownContext() { mFb->unbind_locked(); }
mFb->unbind_locked();
} virtual TextureDraw *getTextureDraw() const { return mFb->getTextureDraw(); }
virtual TextureDraw* getTextureDraw() const {
return mFb->getTextureDraw();
}
private: private:
Renderer *mFb; Renderer *mFb;
}; };
@ -93,31 +86,23 @@ private:
Renderer *Renderer::s_renderer = NULL; Renderer *Renderer::s_renderer = NULL;
HandleType Renderer::s_nextHandle = 0; HandleType Renderer::s_nextHandle = 0;
static char* getGLES1ExtensionString(EGLDisplay p_dpy) static char *getGLES1ExtensionString(EGLDisplay p_dpy) {
{
EGLConfig config; EGLConfig config;
EGLSurface surface; EGLSurface surface;
static const GLint configAttribs[] = { static const GLint configAttribs[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
EGL_NONE EGL_NONE};
};
int n; int n;
if (!s_egl.eglChooseConfig(p_dpy, configAttribs, if (!s_egl.eglChooseConfig(p_dpy, configAttribs, &config, 1, &n) || n == 0) {
&config, 1, &n) || n == 0) {
ERR("%s: Could not find GLES 1.x config!\n", __FUNCTION__); ERR("%s: Could not find GLES 1.x config!\n", __FUNCTION__);
return NULL; return NULL;
} }
DBG("%s: Found config %p\n", __FUNCTION__, (void *)config); DBG("%s: Found config %p\n", __FUNCTION__, (void *)config);
static const EGLint pbufAttribs[] = { static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
surface = s_egl.eglCreatePbufferSurface(p_dpy, config, pbufAttribs); surface = s_egl.eglCreatePbufferSurface(p_dpy, config, pbufAttribs);
if (surface == EGL_NO_SURFACE) { if (surface == EGL_NO_SURFACE) {
@ -125,13 +110,10 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy)
return NULL; return NULL;
} }
static const GLint gles1ContextAttribs[] = { static const GLint gles1ContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 1,
EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE};
EGL_NONE
};
EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, EGL_NO_CONTEXT,
EGL_NO_CONTEXT,
gles1ContextAttribs); gles1ContextAttribs);
if (ctx == EGL_NO_CONTEXT) { if (ctx == EGL_NO_CONTEXT) {
ERR("%s: Could not create GLES 1.x Context!\n", __FUNCTION__); ERR("%s: Could not create GLES 1.x Context!\n", __FUNCTION__);
@ -167,8 +149,7 @@ void Renderer::finalize(){
s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface); s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface);
} }
bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) {
{
GL_LOG("FrameBuffer::initialize"); GL_LOG("FrameBuffer::initialize");
if (s_renderer != NULL) { if (s_renderer != NULL) {
return true; return true;
@ -194,8 +175,7 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
} }
GL_LOG("call eglInitialize"); GL_LOG("call eglInitialize");
if (!s_egl.eglInitialize(fb->m_eglDisplay, if (!s_egl.eglInitialize(fb->m_eglDisplay, &fb->m_caps.eglMajor,
&fb->m_caps.eglMajor,
&fb->m_caps.eglMinor)) { &fb->m_caps.eglMinor)) {
ERR("Failed to eglInitialize\n"); ERR("Failed to eglInitialize\n");
GL_LOG("Failed to eglInitialize"); GL_LOG("Failed to eglInitialize");
@ -224,34 +204,33 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// Create EGL context for framebuffer post rendering. // Create EGL context for framebuffer post rendering.
// //
GLint surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; GLint surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
const GLint configAttribs[] = { const GLint configAttribs[] = {EGL_RED_SIZE,
EGL_RED_SIZE, 1, 1,
EGL_GREEN_SIZE, 1, EGL_GREEN_SIZE,
EGL_BLUE_SIZE, 1, 1,
EGL_SURFACE_TYPE, surfaceType, EGL_BLUE_SIZE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1,
EGL_NONE EGL_SURFACE_TYPE,
}; surfaceType,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_NONE};
int n; int n;
if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, &fb->m_eglConfig,
&fb->m_eglConfig, 1, &n)) { 1, &n)) {
ERR("Failed on eglChooseConfig\n"); ERR("Failed on eglChooseConfig\n");
free(gles1Extensions); free(gles1Extensions);
delete fb; delete fb;
return false; return false;
} }
static const GLint glContextAttribs[] = { static const GLint glContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGL_NONE
};
GL_LOG("attempting to create egl context"); GL_LOG("attempting to create egl context");
fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig,
fb->m_eglConfig, EGL_NO_CONTEXT, glContextAttribs);
EGL_NO_CONTEXT,
glContextAttribs);
if (fb->m_eglContext == EGL_NO_CONTEXT) { if (fb->m_eglContext == EGL_NO_CONTEXT) {
ERR("Failed to create context 0x%x\n", s_egl.eglGetError()); ERR("Failed to create context 0x%x\n", s_egl.eglGetError());
free(gles1Extensions); free(gles1Extensions);
@ -268,10 +247,8 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// on Mac platform when switching binded drawable for a context however // on Mac platform when switching binded drawable for a context however
// it is more efficient on other platforms as well. // it is more efficient on other platforms as well.
// //
fb->m_pbufContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_pbufContext = s_egl.eglCreateContext(
fb->m_eglConfig, fb->m_eglDisplay, fb->m_eglConfig, fb->m_eglContext, glContextAttribs);
fb->m_eglContext,
glContextAttribs);
if (fb->m_pbufContext == EGL_NO_CONTEXT) { if (fb->m_pbufContext == EGL_NO_CONTEXT) {
ERR("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError()); ERR("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError());
free(gles1Extensions); free(gles1Extensions);
@ -285,15 +262,10 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// the FB context. // the FB context.
// The FB output will go to a subwindow, if one exist. // The FB output will go to a subwindow, if one exist.
// //
static const EGLint pbufAttribs[] = { static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE
};
fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(fb->m_eglDisplay, fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(
fb->m_eglConfig, fb->m_eglDisplay, fb->m_eglConfig, pbufAttribs);
pbufAttribs);
if (fb->m_pbufSurface == EGL_NO_SURFACE) { if (fb->m_pbufSurface == EGL_NO_SURFACE) {
ERR("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError()); ERR("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError());
free(gles1Extensions); free(gles1Extensions);
@ -315,7 +287,8 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// //
// Initilize framebuffer capabilities // Initilize framebuffer capabilities
// //
//const char* gles2Extensions = (const char *)s_gles2.glGetString(GL_EXTENSIONS); // const char* gles2Extensions = (const char
// *)s_gles2.glGetString(GL_EXTENSIONS);
bool has_gl_oes_image = false; bool has_gl_oes_image = false;
// printf("GLES1 [%s]\n", gles1Extensions); // printf("GLES1 [%s]\n", gles1Extensions);
@ -329,16 +302,15 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
free((void *)gles1Extensions); free((void *)gles1Extensions);
gles1Extensions = NULL; gles1Extensions = NULL;
const char *eglExtensions = s_egl.eglQueryString(fb->m_eglDisplay, const char *eglExtensions =
EGL_EXTENSIONS); s_egl.eglQueryString(fb->m_eglDisplay, EGL_EXTENSIONS);
if (eglExtensions && has_gl_oes_image) { if (eglExtensions && has_gl_oes_image) {
fb->m_caps.has_eglimage_texture_2d = fb->m_caps.has_eglimage_texture_2d =
strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL; strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL;
fb->m_caps.has_eglimage_renderbuffer = fb->m_caps.has_eglimage_renderbuffer =
strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL; strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL;
} } else {
else {
fb->m_caps.has_eglimage_texture_2d = false; fb->m_caps.has_eglimage_texture_2d = false;
fb->m_caps.has_eglimage_renderbuffer = false; fb->m_caps.has_eglimage_renderbuffer = false;
} }
@ -435,21 +407,22 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
return true; return true;
} }
Renderer::Program::Program(GLuint program_id) Renderer::Program::Program(GLuint program_id) {
{
id = program_id; id = program_id;
position_attr = s_gles2.glGetAttribLocation(id, "position"); position_attr = s_gles2.glGetAttribLocation(id, "position");
texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord"); texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord");
tex_uniform = s_gles2.glGetUniformLocation(id, "tex"); tex_uniform = s_gles2.glGetUniformLocation(id, "tex");
center_uniform = s_gles2.glGetUniformLocation(id, "centre"); center_uniform = s_gles2.glGetUniformLocation(id, "centre");
display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform"); display_transform_uniform =
s_gles2.glGetUniformLocation(id, "display_transform");
transform_uniform = s_gles2.glGetUniformLocation(id, "transform"); transform_uniform = s_gles2.glGetUniformLocation(id, "transform");
screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords"); screen_to_gl_coords_uniform =
s_gles2.glGetUniformLocation(id, "screen_to_gl_coords");
alpha_uniform = s_gles2.glGetUniformLocation(id, "alpha"); alpha_uniform = s_gles2.glGetUniformLocation(id, "alpha");
} }
Renderer::Renderer() : Renderer::Renderer()
m_configs(NULL), : m_configs(NULL),
m_eglDisplay(EGL_NO_DISPLAY), m_eglDisplay(EGL_NO_DISPLAY),
m_colorBufferHelper(new ColorBufferHelper(this)), m_colorBufferHelper(new ColorBufferHelper(this)),
m_eglContext(EGL_NO_CONTEXT), m_eglContext(EGL_NO_CONTEXT),
@ -463,8 +436,7 @@ Renderer::Renderer() :
m_statsStartTime(0LL), m_statsStartTime(0LL),
m_glVendor(NULL), m_glVendor(NULL),
m_glRenderer(NULL), m_glRenderer(NULL),
m_glVersion(NULL) m_glVersion(NULL) {
{
m_fpsStats = getenv("SHOW_FPS_STATS") != NULL; m_fpsStats = getenv("SHOW_FPS_STATS") != NULL;
} }
@ -482,31 +454,28 @@ struct RendererWindow {
glm::mat4 display_transform; glm::mat4 display_transform;
}; };
RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window) RendererWindow *Renderer::createNativeWindow(
{ EGLNativeWindowType native_window) {
m_lock.lock(); m_lock.lock();
auto window = new RendererWindow; auto window = new RendererWindow;
window->native_window = native_window; window->native_window = native_window;
window->surface = s_egl.eglCreateWindowSurface( window->surface = s_egl.eglCreateWindowSurface(
m_eglDisplay, m_eglConfig, window->native_window, nullptr); m_eglDisplay, m_eglConfig, window->native_window, nullptr);
if (window->surface == EGL_NO_SURFACE) if (window->surface == EGL_NO_SURFACE) {
{
delete window; delete window;
m_lock.unlock(); m_lock.unlock();
return nullptr; return nullptr;
} }
if (!bindWindow_locked(window)) if (!bindWindow_locked(window)) {
{
s_egl.eglDestroySurface(m_eglDisplay, window->surface); s_egl.eglDestroySurface(m_eglDisplay, window->surface);
delete window; delete window;
m_lock.unlock(); m_lock.unlock();
return nullptr; return nullptr;
} }
s_gles2.glClear(GL_COLOR_BUFFER_BIT | s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT); GL_STENCIL_BUFFER_BIT);
s_egl.eglSwapBuffers(m_eglDisplay, window->surface); s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
@ -521,8 +490,7 @@ RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window)
void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) { void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) {
auto w = m_nativeWindows.find(native_window); auto w = m_nativeWindows.find(native_window);
if (w == m_nativeWindows.end()) if (w == m_nativeWindows.end()) return;
return;
m_lock.lock(); m_lock.lock();
@ -537,31 +505,24 @@ void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) {
m_lock.unlock(); m_lock.unlock();
} }
HandleType Renderer::genHandle() HandleType Renderer::genHandle() {
{
HandleType id; HandleType id;
do { do {
id = ++s_nextHandle; id = ++s_nextHandle;
} while( id == 0 || } while (id == 0 || m_contexts.find(id) != m_contexts.end() ||
m_contexts.find(id) != m_contexts.end() ||
m_windows.find(id) != m_windows.end()); m_windows.find(id) != m_windows.end());
return id; return id;
} }
HandleType Renderer::createColorBuffer(int p_width, int p_height, HandleType Renderer::createColorBuffer(int p_width, int p_height,
GLenum p_internalFormat) GLenum p_internalFormat) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0; HandleType ret = 0;
ColorBufferPtr cb(ColorBuffer::create( ColorBufferPtr cb(ColorBuffer::create(
getDisplay(), getDisplay(), p_width, p_height, p_internalFormat,
p_width, getCaps().has_eglimage_texture_2d, m_colorBufferHelper));
p_height,
p_internalFormat,
getCaps().has_eglimage_texture_2d,
m_colorBufferHelper));
if (cb.Ptr() != NULL) { if (cb.Ptr() != NULL) {
ret = genHandle(); ret = genHandle();
m_colorbuffers[ret].cb = cb; m_colorbuffers[ret].cb = cb;
@ -571,8 +532,7 @@ HandleType Renderer::createColorBuffer(int p_width, int p_height,
} }
HandleType Renderer::createRenderContext(int p_config, HandleType p_share, HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
bool p_isGL2) bool p_isGL2) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0; HandleType ret = 0;
@ -603,8 +563,8 @@ HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
return ret; return ret;
} }
HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height) HandleType Renderer::createWindowSurface(int p_config, int p_width,
{ int p_height) {
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
HandleType ret = 0; HandleType ret = 0;
@ -626,8 +586,7 @@ HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height
return ret; return ret;
} }
void Renderer::drainRenderContext() void Renderer::drainRenderContext() {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
RenderThreadInfo *tinfo = RenderThreadInfo::get(); RenderThreadInfo *tinfo = RenderThreadInfo::get();
if (tinfo->m_contextSet.empty()) return; if (tinfo->m_contextSet.empty()) return;
@ -639,8 +598,7 @@ void Renderer::drainRenderContext()
tinfo->m_contextSet.clear(); tinfo->m_contextSet.clear();
} }
void Renderer::drainWindowSurface() void Renderer::drainWindowSurface() {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
RenderThreadInfo *tinfo = RenderThreadInfo::get(); RenderThreadInfo *tinfo = RenderThreadInfo::get();
if (tinfo->m_windowSet.empty()) return; if (tinfo->m_windowSet.empty()) return;
@ -652,7 +610,9 @@ void Renderer::drainWindowSurface()
if (oldColorBufferHandle) { if (oldColorBufferHandle) {
ColorBufferMap::iterator cit(m_colorbuffers.find(oldColorBufferHandle)); ColorBufferMap::iterator cit(m_colorbuffers.find(oldColorBufferHandle));
if (cit != m_colorbuffers.end()) { if (cit != m_colorbuffers.end()) {
if (--(*cit).second.refcount == 0) { m_colorbuffers.erase(cit); } if (--(*cit).second.refcount == 0) {
m_colorbuffers.erase(cit);
}
} }
} }
m_windows.erase(windowHandle); m_windows.erase(windowHandle);
@ -661,8 +621,7 @@ void Renderer::drainWindowSurface()
tinfo->m_windowSet.clear(); tinfo->m_windowSet.clear();
} }
void Renderer::DestroyRenderContext(HandleType p_context) void Renderer::DestroyRenderContext(HandleType p_context) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
m_contexts.erase(p_context); m_contexts.erase(p_context);
RenderThreadInfo *tinfo = RenderThreadInfo::get(); RenderThreadInfo *tinfo = RenderThreadInfo::get();
@ -670,8 +629,7 @@ void Renderer::DestroyRenderContext(HandleType p_context)
tinfo->m_contextSet.erase(p_context); tinfo->m_contextSet.erase(p_context);
} }
void Renderer::DestroyWindowSurface(HandleType p_surface) void Renderer::DestroyWindowSurface(HandleType p_surface) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
if (m_windows.find(p_surface) != m_windows.end()) { if (m_windows.find(p_surface) != m_windows.end()) {
m_windows.erase(p_surface); m_windows.erase(p_surface);
@ -681,8 +639,7 @@ void Renderer::DestroyWindowSurface(HandleType p_surface)
} }
} }
int Renderer::openColorBuffer(HandleType p_colorbuffer) int Renderer::openColorBuffer(HandleType p_colorbuffer) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
@ -694,8 +651,7 @@ int Renderer::openColorBuffer(HandleType p_colorbuffer)
return 0; return 0;
} }
void Renderer::closeColorBuffer(HandleType p_colorbuffer) void Renderer::closeColorBuffer(HandleType p_colorbuffer) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
@ -710,13 +666,13 @@ void Renderer::closeColorBuffer(HandleType p_colorbuffer)
} }
} }
bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfaceMap::iterator w(m_windows.find(p_surface)); WindowSurfaceMap::iterator w(m_windows.find(p_surface));
if (w == m_windows.end()) { if (w == m_windows.end()) {
ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n", p_surface); ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n",
p_surface);
// bad surface handle // bad surface handle
return false; return false;
} }
@ -728,8 +684,7 @@ bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface)
} }
bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface, bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
HandleType p_colorbuffer) HandleType p_colorbuffer) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfaceMap::iterator w(m_windows.find(p_surface)); WindowSurfaceMap::iterator w(m_windows.find(p_surface));
@ -751,10 +706,9 @@ bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
return true; return true;
} }
void Renderer::readColorBuffer(HandleType p_colorbuffer, void Renderer::readColorBuffer(HandleType p_colorbuffer, int x, int y,
int x, int y, int width, int height, int width, int height, GLenum format,
GLenum format, GLenum type, void *pixels) GLenum type, void *pixels) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
@ -766,10 +720,9 @@ void Renderer::readColorBuffer(HandleType p_colorbuffer,
(*c).second.cb->readPixels(x, y, width, height, format, type, pixels); (*c).second.cb->readPixels(x, y, width, height, format, type, pixels);
} }
bool Renderer::updateColorBuffer(HandleType p_colorbuffer, bool Renderer::updateColorBuffer(HandleType p_colorbuffer, int x, int y,
int x, int y, int width, int height, int width, int height, GLenum format,
GLenum format, GLenum type, void *pixels) GLenum type, void *pixels) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
@ -783,8 +736,7 @@ bool Renderer::updateColorBuffer(HandleType p_colorbuffer,
return true; return true;
} }
bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
@ -796,8 +748,7 @@ bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer)
return (*c).second.cb->bindToTexture(); return (*c).second.cb->bindToTexture();
} }
bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
@ -809,10 +760,8 @@ bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
return (*c).second.cb->bindToRenderbuffer(); return (*c).second.cb->bindToRenderbuffer();
} }
bool Renderer::bindContext(HandleType p_context, bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface,
HandleType p_drawSurface, HandleType p_readSurface) {
HandleType p_readSurface)
{
emugl::Mutex::AutoLock mutex(m_lock); emugl::Mutex::AutoLock mutex(m_lock);
WindowSurfacePtr draw(NULL), read(NULL); WindowSurfacePtr draw(NULL), read(NULL);
@ -843,8 +792,7 @@ bool Renderer::bindContext(HandleType p_context,
return false; return false;
} }
read = (*w).second.first; read = (*w).second.first;
} } else {
else {
read = draw; read = draw;
} }
} }
@ -875,8 +823,7 @@ bool Renderer::bindContext(HandleType p_context,
if (bindDraw.Ptr() != bindRead.Ptr()) { if (bindDraw.Ptr() != bindRead.Ptr()) {
bindDraw->bind(ctx, WindowSurface::BIND_DRAW); bindDraw->bind(ctx, WindowSurface::BIND_DRAW);
bindRead->bind(ctx, WindowSurface::BIND_READ); bindRead->bind(ctx, WindowSurface::BIND_READ);
} } else {
else {
bindDraw->bind(ctx, WindowSurface::BIND_READDRAW); bindDraw->bind(ctx, WindowSurface::BIND_READDRAW);
} }
} }
@ -888,18 +835,19 @@ bool Renderer::bindContext(HandleType p_context,
tinfo->currDrawSurf = draw; tinfo->currDrawSurf = draw;
tinfo->currReadSurf = read; tinfo->currReadSurf = read;
if (ctx) { if (ctx) {
if (ctx->isGL2()) tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData()); if (ctx->isGL2())
else tinfo->m_glDec.setContextData(&ctx->decoderContextData()); tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
} else
else { tinfo->m_glDec.setContextData(&ctx->decoderContextData());
} else {
tinfo->m_glDec.setContextData(NULL); tinfo->m_glDec.setContextData(NULL);
tinfo->m_gl2Dec.setContextData(NULL); tinfo->m_gl2Dec.setContextData(NULL);
} }
return true; return true;
} }
HandleType Renderer::createClientImage(HandleType context, EGLenum target, GLuint buffer) HandleType Renderer::createClientImage(HandleType context, EGLenum target,
{ GLuint buffer) {
RenderContextPtr ctx(NULL); RenderContextPtr ctx(NULL);
if (context) { if (context) {
@ -913,15 +861,14 @@ HandleType Renderer::createClientImage(HandleType context, EGLenum target, GLuin
} }
EGLContext eglContext = ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT; EGLContext eglContext = ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT;
EGLImageKHR image = s_egl.eglCreateImageKHR( EGLImageKHR image =
m_eglDisplay, eglContext, target, s_egl.eglCreateImageKHR(m_eglDisplay, eglContext, target,
reinterpret_cast<EGLClientBuffer>(buffer), NULL); reinterpret_cast<EGLClientBuffer>(buffer), NULL);
return (HandleType) reinterpret_cast<uintptr_t>(image); return (HandleType) reinterpret_cast<uintptr_t>(image);
} }
EGLBoolean Renderer::destroyClientImage(HandleType image) EGLBoolean Renderer::destroyClientImage(HandleType image) {
{
return s_egl.eglDestroyImageKHR(m_eglDisplay, return s_egl.eglDestroyImageKHR(m_eglDisplay,
reinterpret_cast<EGLImageKHR>(image)); reinterpret_cast<EGLImageKHR>(image));
} }
@ -929,14 +876,13 @@ EGLBoolean Renderer::destroyClientImage(HandleType image)
// //
// The framebuffer lock should be held when calling this function ! // The framebuffer lock should be held when calling this function !
// //
bool Renderer::bind_locked() bool Renderer::bind_locked() {
{
EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLContext prevContext = s_egl.eglGetCurrentContext();
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, m_pbufSurface,
m_pbufSurface, m_pbufContext)) { m_pbufContext)) {
ERR("eglMakeCurrent failed\n"); ERR("eglMakeCurrent failed\n");
return false; return false;
} }
@ -947,14 +893,13 @@ bool Renderer::bind_locked()
return true; return true;
} }
bool Renderer::bindWindow_locked(RendererWindow *window) bool Renderer::bindWindow_locked(RendererWindow *window) {
{
EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLContext prevContext = s_egl.eglGetCurrentContext();
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface, if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface, window->surface,
window->surface, m_eglContext)) { m_eglContext)) {
ERR("eglMakeCurrent failed\n"); ERR("eglMakeCurrent failed\n");
return false; return false;
} }
@ -965,10 +910,9 @@ bool Renderer::bindWindow_locked(RendererWindow *window)
return true; return true;
} }
bool Renderer::unbind_locked() bool Renderer::unbind_locked() {
{ if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, m_prevReadSurf,
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, m_prevContext)) {
m_prevReadSurf, m_prevContext)) {
return false; return false;
} }
@ -978,8 +922,7 @@ bool Renderer::unbind_locked()
return true; return true;
} }
const GLchar* const Renderer::vshader = const GLchar *const Renderer::vshader = {
{
"attribute vec3 position;\n" "attribute vec3 position;\n"
"attribute vec2 texcoord;\n" "attribute vec2 texcoord;\n"
"uniform mat4 screen_to_gl_coords;\n" "uniform mat4 screen_to_gl_coords;\n"
@ -992,11 +935,9 @@ const GLchar* const Renderer::vshader =
" vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n" " vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n"
" gl_Position = display_transform * screen_to_gl_coords * transformed;\n" " gl_Position = display_transform * screen_to_gl_coords * transformed;\n"
" v_texcoord = texcoord;\n" " v_texcoord = texcoord;\n"
"}\n" "}\n"};
};
const GLchar* const Renderer::alphaFShader = const GLchar *const Renderer::alphaFShader = {
{
"precision mediump float;\n" "precision mediump float;\n"
"uniform sampler2D tex;\n" "uniform sampler2D tex;\n"
"uniform float alpha;\n" "uniform float alpha;\n"
@ -1004,8 +945,7 @@ const GLchar* const Renderer::alphaFShader =
"void main() {\n" "void main() {\n"
" vec4 frag = texture2D(tex, v_texcoord);\n" " vec4 frag = texture2D(tex, v_texcoord);\n"
" gl_FragColor = alpha*frag;\n" " gl_FragColor = alpha*frag;\n"
"}\n" "}\n"};
};
const GLchar *const Renderer::defaultFShader = const GLchar *const Renderer::defaultFShader =
{ // This is the fastest fragment shader. Use it when you can. { // This is the fastest fragment shader. Use it when you can.
@ -1014,11 +954,10 @@ const GLchar* const Renderer::defaultFShader =
"varying vec2 v_texcoord;\n" "varying vec2 v_texcoord;\n"
"void main() {\n" "void main() {\n"
" gl_FragColor = texture2D(tex, v_texcoord);\n" " gl_FragColor = texture2D(tex, v_texcoord);\n"
"}\n" "}\n"};
};
void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect &rect) void Renderer::setupViewport(RendererWindow *window,
{ const anbox::graphics::Rect &rect) {
/* /*
* Here we provide a 3D perspective projection with a default 30 degrees * Here we provide a 3D perspective projection with a default 30 degrees
* vertical field of view. This projection matrix is carefully designed * vertical field of view. This projection matrix is carefully designed
@ -1028,7 +967,8 @@ void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect
* a different depth and it will appear to come out of or go into the * a different depth and it will appear to come out of or go into the
* screen. * screen.
*/ */
window->screen_to_gl_coords = glm::translate(glm::mat4(1.0f), glm::vec3{-1.0f, 1.0f, 0.0f}); window->screen_to_gl_coords =
glm::translate(glm::mat4(1.0f), glm::vec3{-1.0f, 1.0f, 0.0f});
/* /*
* Perspective division is one thing that can't be done in a matrix * Perspective division is one thing that can't be done in a matrix
@ -1039,27 +979,23 @@ void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect
window->screen_to_gl_coords[2][3] = -1.0f; window->screen_to_gl_coords[2][3] = -1.0f;
float const vertical_fov_degrees = 30.0f; float const vertical_fov_degrees = 30.0f;
float const near = float const near = (rect.height() / 2.0f) /
(rect.height() / 2.0f) /
std::tan((vertical_fov_degrees * M_PI / 180.0f) / 2.0f); std::tan((vertical_fov_degrees * M_PI / 180.0f) / 2.0f);
float const far = -near; float const far = -near;
window->screen_to_gl_coords = glm::scale(window->screen_to_gl_coords, window->screen_to_gl_coords =
glm::vec3{2.0f / rect.width(), glm::scale(window->screen_to_gl_coords,
-2.0f / rect.height(), glm::vec3{2.0f / rect.width(), -2.0f / rect.height(),
2.0f / (near - far)}); 2.0f / (near - far)});
window->screen_to_gl_coords = glm::translate(window->screen_to_gl_coords, window->screen_to_gl_coords = glm::translate(
glm::vec3{-rect.left(), window->screen_to_gl_coords, glm::vec3{-rect.left(), -rect.top(), 0.0f});
-rect.top(),
0.0f});
window->viewport = rect; window->viewport = rect;
} }
void Renderer::tessellate(std::vector<anbox::graphics::Primitive> &primitives, void Renderer::tessellate(std::vector<anbox::graphics::Primitive> &primitives,
const anbox::graphics::Rect &buf_size, const anbox::graphics::Rect &buf_size,
const Renderable &renderable) const Renderable &renderable) {
{
auto rect = renderable.screen_position(); auto rect = renderable.screen_position();
GLfloat left = rect.left(); GLfloat left = rect.left();
GLfloat right = rect.right(); GLfloat right = rect.right();
@ -1070,10 +1006,8 @@ void Renderer::tessellate(std::vector<anbox::graphics::Primitive>& primitives,
rectangle.tex_id = 0; rectangle.tex_id = 0;
rectangle.type = GL_TRIANGLE_STRIP; rectangle.type = GL_TRIANGLE_STRIP;
GLfloat tex_right = static_cast<GLfloat>(rect.width()) / GLfloat tex_right = static_cast<GLfloat>(rect.width()) / buf_size.width();
buf_size.width(); GLfloat tex_bottom = static_cast<GLfloat>(rect.height()) / buf_size.height();
GLfloat tex_bottom = static_cast<GLfloat>(rect.height()) /
buf_size.height();
auto &vertices = rectangle.vertices; auto &vertices = rectangle.vertices;
vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}}; vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}};
@ -1085,11 +1019,10 @@ void Renderer::tessellate(std::vector<anbox::graphics::Primitive>& primitives,
primitives[0] = rectangle; primitives[0] = rectangle;
} }
void Renderer::draw(RendererWindow *window, const Renderable &renderable, const Program &prog) void Renderer::draw(RendererWindow *window, const Renderable &renderable,
{ const Program &prog) {
const auto &color_buffer = m_colorbuffers.find(renderable.buffer()); const auto &color_buffer = m_colorbuffers.find(renderable.buffer());
if (color_buffer == m_colorbuffers.end()) if (color_buffer == m_colorbuffers.end()) return;
return;
const auto &cb = color_buffer->second.cb; const auto &cb = color_buffer->second.cb;
@ -1103,10 +1036,8 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
s_gles2.glActiveTexture(GL_TEXTURE0); s_gles2.glActiveTexture(GL_TEXTURE0);
auto const &rect = renderable.screen_position(); auto const &rect = renderable.screen_position();
GLfloat centerx = rect.left() + GLfloat centerx = rect.left() + rect.width() / 2.0f;
rect.width() / 2.0f; GLfloat centery = rect.top() + rect.height() / 2.0f;
GLfloat centery = rect.top() +
rect.height() / 2.0f;
s_gles2.glUniform2f(prog.center_uniform, centerx, centery); s_gles2.glUniform2f(prog.center_uniform, centerx, centery);
s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE, s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE,
@ -1121,20 +1052,19 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
m_primitives.clear(); m_primitives.clear();
tessellate(m_primitives, {cb->getWidth(), cb->getHeight()}, renderable); tessellate(m_primitives, {cb->getWidth(), cb->getHeight()}, renderable);
for (auto const& p : m_primitives) for (auto const &p : m_primitives) {
{
cb->bind(); cb->bind();
s_gles2.glVertexAttribPointer(prog.position_attr, 3, GL_FLOAT, s_gles2.glVertexAttribPointer(prog.position_attr, 3, GL_FLOAT, GL_FALSE,
GL_FALSE, sizeof(anbox::graphics::Vertex), sizeof(anbox::graphics::Vertex),
&p.vertices[0].position); &p.vertices[0].position);
s_gles2.glVertexAttribPointer(prog.texcoord_attr, 2, GL_FLOAT, s_gles2.glVertexAttribPointer(prog.texcoord_attr, 2, GL_FLOAT, GL_FALSE,
GL_FALSE, sizeof(anbox::graphics::Vertex), sizeof(anbox::graphics::Vertex),
&p.vertices[0].texcoord); &p.vertices[0].texcoord);
s_gles2.glEnable(GL_BLEND); s_gles2.glEnable(GL_BLEND);
s_gles2.glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, s_gles2.glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA); GL_ONE_MINUS_SRC_ALPHA);
s_gles2.glDrawArrays(p.type, 0, p.nvertices); s_gles2.glDrawArrays(p.type, 0, p.nvertices);
} }
@ -1143,14 +1073,13 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
s_gles2.glDisableVertexAttribArray(prog.position_attr); s_gles2.glDisableVertexAttribArray(prog.position_attr);
} }
bool Renderer::draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables) bool Renderer::draw(EGLNativeWindowType native_window,
{ const anbox::graphics::Rect &window_frame,
const RenderableList &renderables) {
auto w = m_nativeWindows.find(native_window); auto w = m_nativeWindows.find(native_window);
if (w == m_nativeWindows.end()) if (w == m_nativeWindows.end()) return false;
return false;
if (!bindWindow_locked(w->second)) if (!bindWindow_locked(w->second)) {
{
m_lock.unlock(); m_lock.unlock();
return false; return false;
} }

View file

@ -17,18 +17,18 @@
#define _LIBRENDER_FRAMEBUFFER_H #define _LIBRENDER_FRAMEBUFFER_H
#include "ColorBuffer.h" #include "ColorBuffer.h"
#include "emugl/common/mutex.h"
#include "RendererConfig.h"
#include "RenderContext.h" #include "RenderContext.h"
#include "RendererConfig.h"
#include "TextureDraw.h" #include "TextureDraw.h"
#include "WindowSurface.h" #include "WindowSurface.h"
#include "emugl/common/mutex.h"
#include "OpenglRender/render_api.h" #include "OpenglRender/render_api.h"
#include "Renderable.h" #include "Renderable.h"
#include "anbox/graphics/program_family.h"
#include "anbox/graphics/primitives.h" #include "anbox/graphics/primitives.h"
#include "anbox/graphics/program_family.h"
#include <EGL/egl.h> #include <EGL/egl.h>
@ -45,7 +45,8 @@ struct ColorBufferRef {
uint32_t refcount; // number of client-side references uint32_t refcount; // number of client-side references
}; };
typedef std::map<HandleType, RenderContextPtr> RenderContextMap; typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
typedef std::map<HandleType, std::pair<WindowSurfacePtr, HandleType> > WindowSurfaceMap; typedef std::map<HandleType, std::pair<WindowSurfacePtr, HandleType>>
WindowSurfaceMap;
typedef std::map<HandleType, ColorBufferRef> ColorBufferMap; typedef std::map<HandleType, ColorBufferRef> ColorBufferMap;
// A structure used to list the capabilities of the underlying EGL // A structure used to list the capabilities of the underlying EGL
@ -104,8 +105,7 @@ public:
// Retrieve the GL strings of the underlying EGL/GLES implementation. // Retrieve the GL strings of the underlying EGL/GLES implementation.
// On return, |*vendor|, |*renderer| and |*version| will point to strings // On return, |*vendor|, |*renderer| and |*version| will point to strings
// that are owned by the instance (and must not be freed by the caller). // that are owned by the instance (and must not be freed by the caller).
void getGLStrings(const char** vendor, void getGLStrings(const char** vendor, const char** renderer,
const char** renderer,
const char** version) const { const char** version) const {
*vendor = m_glVendor; *vendor = m_glVendor;
*renderer = m_glRenderer; *renderer = m_glRenderer;
@ -122,8 +122,8 @@ public:
// |p_isGL2| is true to create a GLES 2.x context, or false for a GLES 1.x // |p_isGL2| is true to create a GLES 2.x context, or false for a GLES 1.x
// one. // one.
// Return a new handle value, which will be 0 in case of error. // Return a new handle value, which will be 0 in case of error.
HandleType createRenderContext( HandleType createRenderContext(int p_config, HandleType p_share,
int p_config, HandleType p_share, bool p_isGL2 = false); bool p_isGL2 = false);
// Create a new WindowSurface instance from this display instance. // Create a new WindowSurface instance from this display instance.
// |p_config| is the index of one of the configs returned by getConfigs(). // |p_config| is the index of one of the configs returned by getConfigs().
@ -137,8 +137,8 @@ public:
// list of valid values. Note that ColorBuffer instances are reference- // list of valid values. Note that ColorBuffer instances are reference-
// counted. Use openColorBuffer / closeColorBuffer to operate on the // counted. Use openColorBuffer / closeColorBuffer to operate on the
// internal count. // internal count.
HandleType createColorBuffer( HandleType createColorBuffer(int p_width, int p_height,
int p_width, int p_height, GLenum p_internalFormat); GLenum p_internalFormat);
// Call this function when a render thread terminates to destroy all // Call this function when a render thread terminates to destroy all
// the remaining contexts it created. Necessary to avoid leaking host // the remaining contexts it created. Necessary to avoid leaking host
@ -174,8 +174,7 @@ public:
// of the context, the draw surface and the read surface, respectively. // of the context, the draw surface and the read surface, respectively.
// Returns true on success, false on failure. // Returns true on success, false on failure.
// Note: if all handle values are 0, this is an unbind operation. // Note: if all handle values are 0, this is an unbind operation.
bool bindContext(HandleType p_context, bool bindContext(HandleType p_context, HandleType p_drawSurface,
HandleType p_drawSurface,
HandleType p_readSurface); HandleType p_readSurface);
// Attach a ColorBuffer to a WindowSurface instance. // Attach a ColorBuffer to a WindowSurface instance.
@ -183,8 +182,8 @@ public:
// |p_surface| is the target WindowSurface's handle value. // |p_surface| is the target WindowSurface's handle value.
// |p_colorbuffer| is the ColorBuffer handle value. // |p_colorbuffer| is the ColorBuffer handle value.
// Returns true on success, false otherwise. // Returns true on success, false otherwise.
bool setWindowSurfaceColorBuffer( bool setWindowSurfaceColorBuffer(HandleType p_surface,
HandleType p_surface, HandleType p_colorbuffer); HandleType p_colorbuffer);
// Copy the content of a WindowSurface's Pbuffer to its attached // Copy the content of a WindowSurface's Pbuffer to its attached
// ColorBuffer. See the documentation for WindowSurface::flushColorBuffer() // ColorBuffer. See the documentation for WindowSurface::flushColorBuffer()
@ -215,9 +214,8 @@ public:
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE. // |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
// |pixels| is the address of a caller-provided buffer that will be filled // |pixels| is the address of a caller-provided buffer that will be filled
// with the pixel data. // with the pixel data.
void readColorBuffer(HandleType p_colorbuffer, void readColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
int x, int y, int width, int height, int height, GLenum format, GLenum type, void* pixels);
GLenum format, GLenum type, void *pixels);
// Update the content of a given ColorBuffer from client data. // Update the content of a given ColorBuffer from client data.
// |p_colorbuffer| is the ColorBuffer's handle value. Similar // |p_colorbuffer| is the ColorBuffer's handle value. Similar
@ -228,11 +226,12 @@ public:
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE. // |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
// |pixels| is the address of a buffer containing the new pixel data. // |pixels| is the address of a buffer containing the new pixel data.
// Returns true on success, false otherwise. // Returns true on success, false otherwise.
bool updateColorBuffer(HandleType p_colorbuffer, bool updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
int x, int y, int width, int height, int height, GLenum format, GLenum type, void* pixels);
GLenum format, GLenum type, void *pixels);
bool draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables); bool draw(EGLNativeWindowType native_window,
const anbox::graphics::Rect& window_frame,
const RenderableList& renderables);
// Return the host EGLDisplay used by this instance. // Return the host EGLDisplay used by this instance.
EGLDisplay getDisplay() const { return m_eglDisplay; } EGLDisplay getDisplay() const { return m_eglDisplay; }
@ -241,7 +240,8 @@ public:
// and windows created by this instance. // and windows created by this instance.
TextureDraw* getTextureDraw() const { return m_textureDraw; } TextureDraw* getTextureDraw() const { return m_textureDraw; }
HandleType createClientImage(HandleType context, EGLenum target, GLuint buffer); HandleType createClientImage(HandleType context, EGLenum target,
GLuint buffer);
EGLBoolean destroyClientImage(HandleType image); EGLBoolean destroyClientImage(HandleType image);
// Used internally. // Used internally.
@ -257,7 +257,8 @@ private:
void setupViewport(RendererWindow* window, const anbox::graphics::Rect& rect); void setupViewport(RendererWindow* window, const anbox::graphics::Rect& rect);
struct Program; struct Program;
void draw(RendererWindow *window, const Renderable &renderable, const Program &prog); void draw(RendererWindow* window, const Renderable& renderable,
const Program& prog);
void tessellate(std::vector<anbox::graphics::Primitive>& primitives, void tessellate(std::vector<anbox::graphics::Primitive>& primitives,
const anbox::graphics::Rect& buf_size, const anbox::graphics::Rect& buf_size,
const Renderable& renderable); const Renderable& renderable);
@ -297,8 +298,7 @@ private:
std::map<EGLNativeWindowType, RendererWindow*> m_nativeWindows; std::map<EGLNativeWindowType, RendererWindow*> m_nativeWindows;
anbox::graphics::ProgramFamily m_family; anbox::graphics::ProgramFamily m_family;
struct Program struct Program {
{
GLuint id = 0; GLuint id = 0;
GLint tex_uniform = -1; GLint tex_uniform = -1;
GLint position_attr = -1; GLint position_attr = -1;

View file

@ -29,35 +29,17 @@ const GLuint kConfigAttributes[] = {
EGL_RENDERABLE_TYPE, // must be third - see getRenderableType() EGL_RENDERABLE_TYPE, // must be third - see getRenderableType()
EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType() EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType()
EGL_CONFIG_ID, // must be fifth - see chooseConfig() EGL_CONFIG_ID, // must be fifth - see chooseConfig()
EGL_BUFFER_SIZE, EGL_BUFFER_SIZE, EGL_ALPHA_SIZE, EGL_BLUE_SIZE, EGL_GREEN_SIZE,
EGL_ALPHA_SIZE, EGL_RED_SIZE, EGL_CONFIG_CAVEAT, EGL_LEVEL, EGL_MAX_PBUFFER_HEIGHT,
EGL_BLUE_SIZE, EGL_MAX_PBUFFER_PIXELS, EGL_MAX_PBUFFER_WIDTH, EGL_NATIVE_RENDERABLE,
EGL_GREEN_SIZE, EGL_NATIVE_VISUAL_ID, EGL_NATIVE_VISUAL_TYPE, EGL_SAMPLES,
EGL_RED_SIZE, EGL_SAMPLE_BUFFERS, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_BLUE_VALUE,
EGL_CONFIG_CAVEAT, EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_RED_VALUE,
EGL_LEVEL, EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_MIN_SWAP_INTERVAL,
EGL_MAX_PBUFFER_HEIGHT, EGL_MAX_SWAP_INTERVAL, EGL_LUMINANCE_SIZE, EGL_ALPHA_MASK_SIZE,
EGL_MAX_PBUFFER_PIXELS,
EGL_MAX_PBUFFER_WIDTH,
EGL_NATIVE_RENDERABLE,
EGL_NATIVE_VISUAL_ID,
EGL_NATIVE_VISUAL_TYPE,
EGL_SAMPLES,
EGL_SAMPLE_BUFFERS,
EGL_TRANSPARENT_TYPE,
EGL_TRANSPARENT_BLUE_VALUE,
EGL_TRANSPARENT_GREEN_VALUE,
EGL_TRANSPARENT_RED_VALUE,
EGL_BIND_TO_TEXTURE_RGB,
EGL_BIND_TO_TEXTURE_RGBA,
EGL_MIN_SWAP_INTERVAL,
EGL_MAX_SWAP_INTERVAL,
EGL_LUMINANCE_SIZE,
EGL_ALPHA_MASK_SIZE,
EGL_COLOR_BUFFER_TYPE, EGL_COLOR_BUFFER_TYPE,
// EGL_MATCH_NATIVE_PIXMAP, // EGL_MATCH_NATIVE_PIXMAP,
EGL_CONFORMANT EGL_CONFORMANT};
};
const size_t kConfigAttributesLen = const size_t kConfigAttributesLen =
sizeof(kConfigAttributes) / sizeof(kConfigAttributes[0]); sizeof(kConfigAttributes) / sizeof(kConfigAttributes[0]);
@ -66,22 +48,17 @@ bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) {
// Filter out configs which do not support pbuffers, since they // Filter out configs which do not support pbuffers, since they
// are used to implement window surfaces. // are used to implement window surfaces.
EGLint surfaceType; EGLint surfaceType;
s_egl.eglGetConfigAttrib( s_egl.eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
display, config, EGL_SURFACE_TYPE, &surfaceType);
if (!(surfaceType & EGL_PBUFFER_BIT)) { if (!(surfaceType & EGL_PBUFFER_BIT)) {
return false; return false;
} }
// Filter out configs that do not support RGB pixel values. // Filter out configs that do not support RGB pixel values.
EGLint redSize = 0, greenSize = 0, blueSize = 0, alphaSize = 0; EGLint redSize = 0, greenSize = 0, blueSize = 0, alphaSize = 0;
s_egl.eglGetConfigAttrib( s_egl.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
display, config,EGL_RED_SIZE, &redSize); s_egl.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
s_egl.eglGetConfigAttrib( s_egl.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
display, config, EGL_GREEN_SIZE, &greenSize); s_egl.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
s_egl.eglGetConfigAttrib(
display, config, EGL_BLUE_SIZE, &blueSize);
s_egl.eglGetConfigAttrib(
display, config, EGL_ALPHA_SIZE, &alphaSize);
if (!redSize || !greenSize || !blueSize || !alphaSize) { if (!redSize || !greenSize || !blueSize || !alphaSize) {
return false; return false;
@ -92,18 +69,14 @@ bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) {
} // namespace } // namespace
RendererConfig::~RendererConfig() { RendererConfig::~RendererConfig() { delete[] mAttribValues; }
delete [] mAttribValues;
}
RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) : RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay)
mEglConfig(hostConfig), mAttribValues(NULL) { : mEglConfig(hostConfig), mAttribValues(NULL) {
mAttribValues = new GLint[kConfigAttributesLen]; mAttribValues = new GLint[kConfigAttributesLen];
for (size_t i = 0; i < kConfigAttributesLen; ++i) { for (size_t i = 0; i < kConfigAttributesLen; ++i) {
mAttribValues[i] = 0; mAttribValues[i] = 0;
s_egl.eglGetConfigAttrib(hostDisplay, s_egl.eglGetConfigAttrib(hostDisplay, hostConfig, kConfigAttributes[i],
hostConfig,
kConfigAttributes[i],
&mAttribValues[i]); &mAttribValues[i]);
// This implementation supports guest window surfaces by wrapping // This implementation supports guest window surfaces by wrapping
@ -114,11 +87,11 @@ RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) :
} }
} }
RendererConfigList::RendererConfigList(EGLDisplay display) : RendererConfigList::RendererConfigList(EGLDisplay display)
mCount(0), mConfigs(NULL), mDisplay(display) { : mCount(0), mConfigs(NULL), mDisplay(display) {
if (display == EGL_NO_DISPLAY) { if (display == EGL_NO_DISPLAY) {
E("%s: Invalid display value %p (EGL_NO_DISPLAY)\n", E("%s: Invalid display value %p (EGL_NO_DISPLAY)\n", __FUNCTION__,
__FUNCTION__, (void*)display); (void*)display);
return; return;
} }
@ -150,8 +123,7 @@ RendererConfigList::~RendererConfigList() {
delete[] mConfigs; delete[] mConfigs;
} }
int RendererConfigList::chooseConfig(const EGLint* attribs, int RendererConfigList::chooseConfig(const EGLint* attribs, EGLint* configs,
EGLint* configs,
EGLint configsSize) const { EGLint configsSize) const {
EGLint numHostConfigs = 0; EGLint numHostConfigs = 0;
if (!s_egl.eglGetConfigs(mDisplay, NULL, 0, &numHostConfigs)) { if (!s_egl.eglGetConfigs(mDisplay, NULL, 0, &numHostConfigs)) {
@ -201,11 +173,8 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
newAttribs[numAttribs + 2] = EGL_NONE; newAttribs[numAttribs + 2] = EGL_NONE;
} }
if (!s_egl.eglChooseConfig(mDisplay, if (!s_egl.eglChooseConfig(mDisplay, newAttribs ? newAttribs : attribs,
newAttribs ? newAttribs : attribs, matchedConfigs, numHostConfigs, &numHostConfigs)) {
matchedConfigs,
numHostConfigs,
&numHostConfigs)) {
numHostConfigs = 0; numHostConfigs = 0;
} }
@ -224,8 +193,8 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
} }
// Find the FbConfig with the same EGL_CONFIG_ID // Find the FbConfig with the same EGL_CONFIG_ID
EGLint hostConfigId; EGLint hostConfigId;
s_egl.eglGetConfigAttrib( s_egl.eglGetConfigAttrib(mDisplay, matchedConfigs[n], EGL_CONFIG_ID,
mDisplay, matchedConfigs[n], EGL_CONFIG_ID, &hostConfigId); &hostConfigId);
for (int k = 0; k < mCount; ++k) { for (int k = 0; k < mCount; ++k) {
int guestConfigId = mConfigs[k]->getConfigId(); int guestConfigId = mConfigs[k]->getConfigId();
if (guestConfigId == hostConfigId) { if (guestConfigId == hostConfigId) {
@ -244,7 +213,6 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
return result; return result;
} }
void RendererConfigList::getPackInfo(EGLint* numConfigs, void RendererConfigList::getPackInfo(EGLint* numConfigs,
EGLint* numAttributes) const { EGLint* numAttributes) const {
if (numConfigs) { if (numConfigs) {
@ -255,7 +223,8 @@ void RendererConfigList::getPackInfo(EGLint* numConfigs,
} }
} }
EGLint RendererConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) const { EGLint RendererConfigList::packConfigs(GLuint bufferByteSize,
GLuint* buffer) const {
GLuint numAttribs = static_cast<GLuint>(kConfigAttributesLen); GLuint numAttribs = static_cast<GLuint>(kConfigAttributesLen);
GLuint kGLuintSize = static_cast<GLuint>(sizeof(GLuint)); GLuint kGLuintSize = static_cast<GLuint>(sizeof(GLuint));
GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize; GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize;
@ -267,8 +236,7 @@ EGLint RendererConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) co
memcpy(buffer, kConfigAttributes, kConfigAttributesLen * kGLuintSize); memcpy(buffer, kConfigAttributes, kConfigAttributesLen * kGLuintSize);
for (int i = 0; i < mCount; ++i) { for (int i = 0; i < mCount; ++i) {
memcpy(buffer + (i + 1) * kConfigAttributesLen, memcpy(buffer + (i + 1) * kConfigAttributesLen, mConfigs[i]->mAttribValues,
mConfigs[i]->mAttribValues,
kConfigAttributesLen * kGLuintSize); kConfigAttributesLen * kGLuintSize);
} }
return mCount; return mCount;

View file

@ -134,8 +134,7 @@ public:
// |configsSize| is the number of entries in the |configs| array. The // |configsSize| is the number of entries in the |configs| array. The
// function will never write more than |configsSize| entries into // function will never write more than |configsSize| entries into
// |configsSize|. // |configsSize|.
EGLint chooseConfig(const EGLint* attribs, EGLint chooseConfig(const EGLint* attribs, EGLint* configs,
EGLint* configs,
EGLint configsSize) const; EGLint configsSize) const;
// Retrieve information that can be sent to the guest before packed // Retrieve information that can be sent to the guest before packed

View file

@ -15,36 +15,24 @@
*/ */
#include "SocketStream.h" #include "SocketStream.h"
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h>
SocketStream::SocketStream(size_t bufSize) : SocketStream::SocketStream(size_t bufSize)
IOStream(bufSize), : IOStream(bufSize), m_sock(-1), m_bufsize(bufSize), m_buf(NULL) {}
m_sock(-1),
m_bufsize(bufSize),
m_buf(NULL)
{
}
SocketStream::SocketStream(int sock, size_t bufSize) : SocketStream::SocketStream(int sock, size_t bufSize)
IOStream(bufSize), : IOStream(bufSize), m_sock(sock), m_bufsize(bufSize), m_buf(NULL) {}
m_sock(sock),
m_bufsize(bufSize),
m_buf(NULL)
{
}
SocketStream::~SocketStream() SocketStream::~SocketStream() {
{
if (m_sock >= 0) { if (m_sock >= 0) {
forceStop(); forceStop();
if(close(m_sock) < 0) if (close(m_sock) < 0) perror("Closing SocketStream failed");
perror("Closing SocketStream failed");
// DBG("SocketStream::~close @ %d \n", m_sock); // DBG("SocketStream::~close @ %d \n", m_sock);
m_sock = -1; m_sock = -1;
} }
@ -54,14 +42,11 @@ SocketStream::~SocketStream()
} }
} }
void *SocketStream::allocBuffer(size_t minSize) {
void *SocketStream::allocBuffer(size_t minSize)
{
size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize);
if (!m_buf) { if (!m_buf) {
m_buf = (unsigned char *)malloc(allocSize); m_buf = (unsigned char *)malloc(allocSize);
} } else if (m_bufsize < allocSize) {
else if (m_bufsize < allocSize) {
unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); unsigned char *p = (unsigned char *)realloc(m_buf, allocSize);
if (p != NULL) { if (p != NULL) {
m_buf = p; m_buf = p;
@ -77,13 +62,9 @@ void *SocketStream::allocBuffer(size_t minSize)
return m_buf; return m_buf;
}; };
int SocketStream::commitBuffer(size_t size) int SocketStream::commitBuffer(size_t size) { return writeFully(m_buf, size); }
{
return writeFully(m_buf, size);
}
int SocketStream::writeFully(const void* buffer, size_t size) int SocketStream::writeFully(const void *buffer, size_t size) {
{
if (!valid()) return -1; if (!valid()) return -1;
size_t res = size; size_t res = size;
@ -104,8 +85,7 @@ int SocketStream::writeFully(const void* buffer, size_t size)
return retval; return retval;
} }
const unsigned char *SocketStream::readFully(void *buf, size_t len) const unsigned char *SocketStream::readFully(void *buf, size_t len) {
{
if (!valid()) return NULL; if (!valid()) return NULL;
if (!buf) { if (!buf) {
return NULL; // do not allow NULL buf in that implementation return NULL; // do not allow NULL buf in that implementation
@ -124,8 +104,7 @@ const unsigned char *SocketStream::readFully(void *buf, size_t len)
return (const unsigned char *)buf; return (const unsigned char *)buf;
} }
const unsigned char *SocketStream::read( void *buf, size_t *inout_len) const unsigned char *SocketStream::read(void *buf, size_t *inout_len) {
{
if (!valid()) return NULL; if (!valid()) return NULL;
if (!buf) { if (!buf) {
return NULL; // do not allow NULL buf in that implementation return NULL; // do not allow NULL buf in that implementation
@ -144,8 +123,7 @@ const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
return NULL; return NULL;
} }
int SocketStream::recv(void *buf, size_t len) int SocketStream::recv(void *buf, size_t len) {
{
if (!valid()) return int(ERR_INVALID_SOCKET); if (!valid()) return int(ERR_INVALID_SOCKET);
int res = 0; int res = 0;
while (true) { while (true) {

View file

@ -19,8 +19,8 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
@ -29,8 +29,7 @@
TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {} TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {}
TcpStream::TcpStream(int sock, size_t bufSize) : TcpStream::TcpStream(int sock, size_t bufSize) : SocketStream(sock, bufSize) {
SocketStream(sock, bufSize) {
// disable Nagle algorithm to improve bandwidth of small // disable Nagle algorithm to improve bandwidth of small
// packets which are quite common in our implementation. // packets which are quite common in our implementation.
emugl::socketTcpDisableNagle(sock); emugl::socketTcpDisableNagle(sock);
@ -38,8 +37,7 @@ TcpStream::TcpStream(int sock, size_t bufSize) :
int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) { int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM); m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM);
if (!valid()) if (!valid()) return int(ERR_INVALID_SOCKET);
return int(ERR_INVALID_SOCKET);
int port = emugl::socketGetPort(m_sock); int port = emugl::socketGetPort(m_sock);
if (port < 0) { if (port < 0) {
@ -55,8 +53,7 @@ int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
SocketStream* TcpStream::accept() { SocketStream* TcpStream::accept() {
int clientSock = emugl::socketAccept(m_sock); int clientSock = emugl::socketAccept(m_sock);
if (clientSock < 0) if (clientSock < 0) return NULL;
return NULL;
return new TcpStream(clientSock, m_bufsize); return new TcpStream(clientSock, m_bufsize);
} }
@ -67,8 +64,7 @@ int TcpStream::connect(const char* addr) {
return valid() ? 0 : -1; return valid() ? 0 : -1;
} }
int TcpStream::connect(const char* hostname, unsigned short port) int TcpStream::connect(const char* hostname, unsigned short port) {
{
m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM); m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM);
return valid() ? 0 : -1; return valid() ? 0 : -1;
} }

View file

@ -25,6 +25,7 @@ public:
virtual SocketStream* accept(); virtual SocketStream* accept();
virtual int connect(const char* addr); virtual int connect(const char* addr);
int connect(const char* hostname, unsigned short port); int connect(const char* hostname, unsigned short port);
private: private:
TcpStream(int sock, size_t bufSize); TcpStream(int sock, size_t bufSize);
}; };

View file

@ -96,8 +96,8 @@ const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]);
} // namespace } // namespace
TextureDraw::TextureDraw(EGLDisplay display) : TextureDraw::TextureDraw(EGLDisplay display)
mDisplay(display), : mDisplay(display),
mVertexShader(0), mVertexShader(0),
mFragmentShader(0), mFragmentShader(0),
mProgram(0), mProgram(0),
@ -119,8 +119,7 @@ TextureDraw::TextureDraw(EGLDisplay display) :
s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success); s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
if (success == GL_FALSE) { if (success == GL_FALSE) {
GLchar messages[256]; GLchar messages[256];
s_gles2.glGetProgramInfoLog( s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
mProgram, sizeof(messages), 0, &messages[0]);
ERR("%s: Could not create/link program: %s\n", __FUNCTION__, messages); ERR("%s: Could not create/link program: %s\n", __FUNCTION__, messages);
s_gles2.glDeleteProgram(mProgram); s_gles2.glDeleteProgram(mProgram);
mProgram = 0; mProgram = 0;
@ -141,14 +140,12 @@ TextureDraw::TextureDraw(EGLDisplay display) :
// Create vertex and index buffers. // Create vertex and index buffers.
s_gles2.glGenBuffers(1, &mVertexBuffer); s_gles2.glGenBuffers(1, &mVertexBuffer);
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
s_gles2.glBufferData( s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices,
GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW); GL_STATIC_DRAW);
s_gles2.glGenBuffers(1, &mIndexBuffer); s_gles2.glGenBuffers(1, &mIndexBuffer);
s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer); s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER, s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndices), kIndices,
sizeof(kIndices),
kIndices,
GL_STATIC_DRAW); GL_STATIC_DRAW);
} }
@ -165,26 +162,19 @@ bool TextureDraw::draw(GLuint texture) {
s_gles2.glUseProgram(mProgram); s_gles2.glUseProgram(mProgram);
err = s_gles2.glGetError(); err = s_gles2.glGetError();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERR("%s: Could not use program error=0x%x\n", ERR("%s: Could not use program error=0x%x\n", __FUNCTION__, err);
__FUNCTION__, err);
} }
// Setup the |position| attribute values. // Setup the |position| attribute values.
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
err = s_gles2.glGetError(); err = s_gles2.glGetError();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n", ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n", __FUNCTION__, err);
__FUNCTION__, err);
} }
s_gles2.glEnableVertexAttribArray(mPositionSlot); s_gles2.glEnableVertexAttribArray(mPositionSlot);
s_gles2.glVertexAttribPointer(mPositionSlot, s_gles2.glVertexAttribPointer(mPositionSlot, 3, GL_FLOAT, GL_FALSE,
3, sizeof(Vertex), 0);
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
0);
err = s_gles2.glGetError(); err = s_gles2.glGetError();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n", ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n",
@ -193,14 +183,9 @@ bool TextureDraw::draw(GLuint texture) {
// Setup the |inCoord| attribute values. // Setup the |inCoord| attribute values.
s_gles2.glEnableVertexAttribArray(mInCoordSlot); s_gles2.glEnableVertexAttribArray(mInCoordSlot);
s_gles2.glVertexAttribPointer(mInCoordSlot, s_gles2.glVertexAttribPointer(
2, mInCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
GL_FLOAT, reinterpret_cast<GLvoid*>(static_cast<uintptr_t>(sizeof(float) * 3)));
GL_FALSE,
sizeof(Vertex),
reinterpret_cast<GLvoid*>(
static_cast<uintptr_t>(
sizeof(float) * 3)));
// setup the |texture| uniform value. // setup the |texture| uniform value.
s_gles2.glActiveTexture(GL_TEXTURE0); s_gles2.glActiveTexture(GL_TEXTURE0);
@ -213,8 +198,7 @@ bool TextureDraw::draw(GLuint texture) {
s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState); s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState);
if (validState == GL_FALSE) { if (validState == GL_FALSE) {
GLchar messages[256]; GLchar messages[256];
s_gles2.glGetProgramInfoLog( s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
mProgram, sizeof(messages), 0, &messages[0]);
ERR("%s: Could not run program: %s\n", __FUNCTION__, messages); ERR("%s: Could not run program: %s\n", __FUNCTION__, messages);
return false; return false;
} }
@ -230,8 +214,7 @@ bool TextureDraw::draw(GLuint texture) {
s_gles2.glDrawElements(GL_TRIANGLES, kIndicesLen, GL_UNSIGNED_BYTE, 0); s_gles2.glDrawElements(GL_TRIANGLES, kIndicesLen, GL_UNSIGNED_BYTE, 0);
err = s_gles2.glGetError(); err = s_gles2.glGetError();
if (err != GL_NO_ERROR) { if (err != GL_NO_ERROR) {
ERR("%s: Could not glDrawElements() error=0x%x\n", ERR("%s: Could not glDrawElements() error=0x%x\n", __FUNCTION__, err);
__FUNCTION__, err);
} }
// TODO(digit): Restore previous program state. // TODO(digit): Restore previous program state.

View file

@ -137,7 +137,8 @@ static void detachShaders(GLuint program) {
} }
} }
static GLuint createShader(GLenum type, const std::initializer_list<const char*>& source) { static GLuint createShader(GLenum type,
const std::initializer_list<const char*>& source) {
GLint success, infoLength; GLint success, infoLength;
GLuint shader = s_gles2.glCreateShader(type); GLuint shader = s_gles2.glCreateShader(type);
@ -150,8 +151,7 @@ static GLuint createShader(GLenum type, const std::initializer_list<const char*>
std::string infoLog(infoLength + 1, '\0'); std::string infoLog(infoLength + 1, '\0');
s_gles2.glGetShaderInfoLog(shader, infoLength, nullptr, &infoLog[0]); s_gles2.glGetShaderInfoLog(shader, infoLength, nullptr, &infoLog[0]);
ERR("%s shader compile failed:\n%s\n", ERR("%s shader compile failed:\n%s\n",
(type == GL_VERTEX_SHADER) ? "Vertex" : "Fragment", (type == GL_VERTEX_SHADER) ? "Vertex" : "Fragment", infoLog.c_str());
infoLog.c_str());
s_gles2.glDeleteShader(shader); s_gles2.glDeleteShader(shader);
shader = 0; shader = 0;
} }
@ -159,19 +159,19 @@ static GLuint createShader(GLenum type, const std::initializer_list<const char*>
return shader; return shader;
} }
static void attachShaders(TextureResize::Framebuffer* fb, const char* factorDefine, static void attachShaders(TextureResize::Framebuffer* fb,
const char* dimensionDefine, GLuint width, GLuint height) { const char* factorDefine, const char* dimensionDefine,
GLuint width, GLuint height) {
std::ostringstream dimensionConst; std::ostringstream dimensionConst;
dimensionConst << "const vec2 kDimension = vec2(" << width << ", " << height << ");\n"; dimensionConst << "const vec2 kDimension = vec2(" << width << ", " << height
<< ");\n";
GLuint vShader = createShader(GL_VERTEX_SHADER, { GLuint vShader = createShader(
factorDefine, dimensionDefine, GL_VERTEX_SHADER, {factorDefine, dimensionDefine, kCommonShaderSource,
kCommonShaderSource, dimensionConst.str().c_str(), kVertexShaderSource dimensionConst.str().c_str(), kVertexShaderSource});
}); GLuint fShader = createShader(
GLuint fShader = createShader(GL_FRAGMENT_SHADER, { GL_FRAGMENT_SHADER, {factorDefine, dimensionDefine, kCommonShaderSource,
factorDefine, dimensionDefine, kCommonShaderSource, kFragmentShaderSource kFragmentShaderSource});
});
if (!vShader || !fShader) { if (!vShader || !fShader) {
return; return;
@ -186,12 +186,16 @@ static void attachShaders(TextureResize::Framebuffer* fb, const char* factorDefi
fb->uTexture = s_gles2.glGetUniformLocation(fb->program, "uTexture"); fb->uTexture = s_gles2.glGetUniformLocation(fb->program, "uTexture");
} }
TextureResize::TextureResize(GLuint width, GLuint height) : TextureResize::TextureResize(GLuint width, GLuint height)
mWidth(width), : mWidth(width),
mHeight(height), mHeight(height),
mFactor(1), mFactor(1),
mFBWidth({0,}), mFBWidth({
mFBHeight({0,}) { 0,
}),
mFBHeight({
0,
}) {
s_gles2.glGenTextures(1, &mFBWidth.texture); s_gles2.glGenTextures(1, &mFBWidth.texture);
s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture); s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -214,7 +218,8 @@ TextureResize::TextureResize(GLuint width, GLuint height) :
s_gles2.glGenBuffers(1, &mVertexBuffer); s_gles2.glGenBuffers(1, &mVertexBuffer);
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData, GL_STATIC_DRAW); s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexData), kVertexData,
GL_STATIC_DRAW);
} }
TextureResize::~TextureResize() { TextureResize::~TextureResize() {
@ -232,7 +237,9 @@ TextureResize::~TextureResize() {
GLuint TextureResize::update(GLuint texture) { GLuint TextureResize::update(GLuint texture) {
// Store the viewport. The viewport is clobbered due to the framebuffers. // Store the viewport. The viewport is clobbered due to the framebuffers.
GLint vport[4] = { 0, }; GLint vport[4] = {
0,
};
s_gles2.glGetIntegerv(GL_VIEWPORT, vport); s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
// Correctly deal with rotated screens. // Correctly deal with rotated screens.
@ -241,7 +248,8 @@ GLuint TextureResize::update(GLuint texture) {
std::swap(tWidth, tHeight); std::swap(tWidth, tHeight);
} }
// Compute the scaling factor needed to get an image just larger than the target viewport. // Compute the scaling factor needed to get an image just larger than the
// target viewport.
unsigned int factor = 1; unsigned int factor = 1;
for (int i = 0, w = mWidth / 2, h = mHeight / 2; for (int i = 0, w = mWidth / 2, h = mHeight / 2;
i < MAX_FACTOR_POWER && w >= tWidth && h >= tHeight; i < MAX_FACTOR_POWER && w >= tWidth && h >= tHeight;
@ -256,7 +264,8 @@ GLuint TextureResize::update(GLuint texture) {
s_gles2.glGetError(); // Clear any GL errors. s_gles2.glGetError(); // Clear any GL errors.
setupFramebuffers(factor); setupFramebuffers(factor);
resize(texture); resize(texture);
s_gles2.glViewport(vport[0], vport[1], vport[2], vport[3]); // Restore the viewport. s_gles2.glViewport(vport[0], vport[1], vport[2],
vport[3]); // Restore the viewport.
// If there was an error while resizing, just use the unscaled texture. // If there was an error while resizing, just use the unscaled texture.
GLenum error = s_gles2.glGetError(); GLenum error = s_gles2.glGetError();
@ -276,18 +285,18 @@ void TextureResize::setupFramebuffers(unsigned int factor) {
// Update the framebuffer sizes to match the new factor. // Update the framebuffer sizes to match the new factor.
s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture); s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture);
s_gles2.glTexImage2D( s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth / factor, mHeight, 0,
GL_TEXTURE_2D, 0, GL_RGBA, mWidth / factor, mHeight, 0, GL_RGBA, GL_FLOAT, nullptr); GL_RGBA, GL_FLOAT, nullptr);
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBWidth.framebuffer); s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBWidth.framebuffer);
s_gles2.glFramebufferTexture2D( s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFBWidth.texture, 0); GL_TEXTURE_2D, mFBWidth.texture, 0);
s_gles2.glBindTexture(GL_TEXTURE_2D, mFBHeight.texture); s_gles2.glBindTexture(GL_TEXTURE_2D, mFBHeight.texture);
s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth / factor, mHeight / factor, 0, GL_RGBA, s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth / factor,
GL_UNSIGNED_BYTE, nullptr); mHeight / factor, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBHeight.framebuffer); s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBHeight.framebuffer);
s_gles2.glFramebufferTexture2D( s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFBHeight.texture, 0); GL_TEXTURE_2D, mFBHeight.texture, 0);
// Update the shaders to the new factor. First detach the old shaders... // Update the shaders to the new factor. First detach the old shaders...
detachShaders(mFBWidth.program); detachShaders(mFBWidth.program);
@ -296,8 +305,10 @@ void TextureResize::setupFramebuffers(unsigned int factor) {
// ... then attach the new ones. // ... then attach the new ones.
std::ostringstream factorDefine; std::ostringstream factorDefine;
factorDefine << "#define FACTOR " << factor << "\n"; factorDefine << "#define FACTOR " << factor << "\n";
attachShaders(&mFBWidth, factorDefine.str().c_str(), "#define HORIZONTAL\n", mWidth, mHeight); attachShaders(&mFBWidth, factorDefine.str().c_str(), "#define HORIZONTAL\n",
attachShaders(&mFBHeight, factorDefine.str().c_str(), "#define VERTICAL\n", mWidth, mHeight); mWidth, mHeight);
attachShaders(&mFBHeight, factorDefine.str().c_str(), "#define VERTICAL\n",
mWidth, mHeight);
mFactor = factor; mFactor = factor;
} }
@ -306,22 +317,27 @@ void TextureResize::resize(GLuint texture) {
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
s_gles2.glActiveTexture(GL_TEXTURE0); s_gles2.glActiveTexture(GL_TEXTURE0);
// First scale the horizontal dimension by rendering the input texture to a scaled framebuffer. // First scale the horizontal dimension by rendering the input texture to a
// scaled framebuffer.
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBWidth.framebuffer); s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, mFBWidth.framebuffer);
s_gles2.glViewport(0, 0, mWidth / mFactor, mHeight); s_gles2.glViewport(0, 0, mWidth / mFactor, mHeight);
s_gles2.glUseProgram(mFBWidth.program); s_gles2.glUseProgram(mFBWidth.program);
s_gles2.glEnableVertexAttribArray(mFBWidth.aPosition); s_gles2.glEnableVertexAttribArray(mFBWidth.aPosition);
s_gles2.glVertexAttribPointer(mFBWidth.aPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); s_gles2.glVertexAttribPointer(mFBWidth.aPosition, 2, GL_FLOAT, GL_FALSE, 0,
0);
s_gles2.glBindTexture(GL_TEXTURE_2D, texture); s_gles2.glBindTexture(GL_TEXTURE_2D, texture);
// Store the current texture filters and set to nearest for scaling. // Store the current texture filters and set to nearest for scaling.
GLint mag_filter, min_filter; GLint mag_filter, min_filter;
s_gles2.glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &mag_filter); s_gles2.glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
s_gles2.glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_filter); &mag_filter);
s_gles2.glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
&min_filter);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
s_gles2.glUniform1i(mFBWidth.uTexture, 0); s_gles2.glUniform1i(mFBWidth.uTexture, 0);
s_gles2.glDrawArrays(GL_TRIANGLES, 0, sizeof(kVertexData) / (2 * sizeof(float))); s_gles2.glDrawArrays(GL_TRIANGLES, 0,
sizeof(kVertexData) / (2 * sizeof(float)));
// Restore the previous texture filters. // Restore the previous texture filters.
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
@ -332,10 +348,12 @@ void TextureResize::resize(GLuint texture) {
s_gles2.glViewport(0, 0, mWidth / mFactor, mHeight / mFactor); s_gles2.glViewport(0, 0, mWidth / mFactor, mHeight / mFactor);
s_gles2.glUseProgram(mFBHeight.program); s_gles2.glUseProgram(mFBHeight.program);
s_gles2.glEnableVertexAttribArray(mFBHeight.aPosition); s_gles2.glEnableVertexAttribArray(mFBHeight.aPosition);
s_gles2.glVertexAttribPointer(mFBHeight.aPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); s_gles2.glVertexAttribPointer(mFBHeight.aPosition, 2, GL_FLOAT, GL_FALSE, 0,
0);
s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture); s_gles2.glBindTexture(GL_TEXTURE_2D, mFBWidth.texture);
s_gles2.glUniform1i(mFBHeight.uTexture, 0); s_gles2.glUniform1i(mFBHeight.uTexture, 0);
s_gles2.glDrawArrays(GL_TRIANGLES, 0, sizeof(kVertexData) / (2 * sizeof(float))); s_gles2.glDrawArrays(GL_TRIANGLES, 0,
sizeof(kVertexData) / (2 * sizeof(float)));
// Clear the bindings. // Clear the bindings.
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, 0); s_gles2.glBindBuffer(GL_ARRAY_BUFFER, 0);

View file

@ -15,21 +15,16 @@
*/ */
#include "TimeUtils.h" #include "TimeUtils.h"
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
long long GetCurrentTimeMS() long long GetCurrentTimeMS() {
{
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
long long iDiff = (now.tv_sec * 1000LL) + now.tv_nsec / 1000000LL; long long iDiff = (now.tv_sec * 1000LL) + now.tv_nsec / 1000000LL;
return iDiff; return iDiff;
} }
void TimeSleepMS(int p_mili) void TimeSleepMS(int p_mili) { usleep(p_mili * 1000); }
{
usleep(p_mili * 1000);
}

View file

@ -20,13 +20,13 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <sys/un.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/un.h>
/* Not all systems define PATH_MAX, those who don't generally don't /* Not all systems define PATH_MAX, those who don't generally don't
* have a limit on the maximum path size, so use a value that is * have a limit on the maximum path size, so use a value that is
@ -36,20 +36,13 @@
#define PATH_MAX 128 #define PATH_MAX 128
#endif #endif
UnixStream::UnixStream(size_t bufSize) : UnixStream::UnixStream(size_t bufSize)
SocketStream(bufSize), : SocketStream(bufSize), bound_socket_path(NULL) {}
bound_socket_path(NULL)
{
}
UnixStream::UnixStream(int sock, size_t bufSize) : UnixStream::UnixStream(int sock, size_t bufSize)
SocketStream(sock, bufSize), : SocketStream(sock, bufSize), bound_socket_path(NULL) {}
bound_socket_path(NULL)
{
}
UnixStream::~UnixStream() UnixStream::~UnixStream() {
{
if (bound_socket_path != NULL) { if (bound_socket_path != NULL) {
int ret = 0; int ret = 0;
do { do {
@ -66,9 +59,7 @@ UnixStream::~UnixStream()
/* Initialize a sockaddr_un with the appropriate values corresponding /* Initialize a sockaddr_un with the appropriate values corresponding
* to a given 'virtual port'. Returns 0 on success, -1 on error. * to a given 'virtual port'. Returns 0 on success, -1 on error.
*/ */
static int static int make_unix_path(char *path, size_t pathlen, int port_number) {
make_unix_path(char *path, size_t pathlen, int port_number)
{
char tmp[PATH_MAX]; // temp directory char tmp[PATH_MAX]; // temp directory
int ret = 0; int ret = 0;
@ -89,8 +80,7 @@ make_unix_path(char *path, size_t pathlen, int port_number)
ERR("Could not create temp directory: %s", tmp); ERR("Could not create temp directory: %s", tmp);
user = NULL; // will fall-back to /tmp user = NULL; // will fall-back to /tmp
} }
} } else if (ret < 0) {
else if (ret < 0) {
user = NULL; // will fallback to /tmp user = NULL; // will fallback to /tmp
} }
} }
@ -109,7 +99,8 @@ make_unix_path(char *path, size_t pathlen, int port_number)
if (::access(path, F_OK) == 0) { if (::access(path, F_OK) == 0) {
ret = ::remove(path); ret = ::remove(path);
if (ret < 0) { if (ret < 0) {
ERR("Failed to remove stale socket file at %s: %s\n", path, strerror(errno)); ERR("Failed to remove stale socket file at %s: %s\n", path,
strerror(errno));
} else { } else {
DBG("Stale socket file at %s was removed.\n", path); DBG("Stale socket file at %s was removed.\n", path);
} }
@ -118,17 +109,14 @@ make_unix_path(char *path, size_t pathlen, int port_number)
return 0; return 0;
} }
int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
{
if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) { if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) {
return -1; return -1;
} }
m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM); m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM);
if (!valid()) if (!valid()) return int(ERR_INVALID_SOCKET);
return int(ERR_INVALID_SOCKET);
bound_socket_path = strdup(addrstr); bound_socket_path = strdup(addrstr);
if (bound_socket_path == NULL) { if (bound_socket_path == NULL) {
@ -140,8 +128,7 @@ int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
return 0; return 0;
} }
SocketStream * UnixStream::accept() SocketStream *UnixStream::accept() {
{
int clientSock = -1; int clientSock = -1;
while (true) { while (true) {
@ -164,8 +151,7 @@ SocketStream * UnixStream::accept()
return clientStream; return clientStream;
} }
int UnixStream::connect(const char* addr) int UnixStream::connect(const char *addr) {
{
m_sock = emugl::socketLocalClient(addr, SOCK_STREAM); m_sock = emugl::socketLocalClient(addr, SOCK_STREAM);
// DBG("UnixStream::connect @ %d \n", m_sock); // DBG("UnixStream::connect @ %d \n", m_sock);
if (!valid()) return -1; if (!valid()) return -1;

View file

@ -25,6 +25,7 @@ public:
virtual int listen(char addrstr[MAX_ADDRSTR_LEN]); virtual int listen(char addrstr[MAX_ADDRSTR_LEN]);
virtual SocketStream *accept(); virtual SocketStream *accept();
virtual int connect(const char *addr); virtual int connect(const char *addr);
private: private:
char *bound_socket_path; char *bound_socket_path;
UnixStream(int sock, size_t bufSize); UnixStream(int sock, size_t bufSize);

View file

@ -25,10 +25,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
WindowSurface::WindowSurface(EGLDisplay display, EGLConfig config)
WindowSurface::WindowSurface(EGLDisplay display, : mSurface(NULL),
EGLConfig config) :
mSurface(NULL),
mAttachedColorBuffer(NULL), mAttachedColorBuffer(NULL),
mReadContext(NULL), mReadContext(NULL),
mDrawContext(NULL), mDrawContext(NULL),
@ -43,10 +41,8 @@ WindowSurface::~WindowSurface() {
} }
} }
WindowSurface *WindowSurface::create(EGLDisplay display, WindowSurface *WindowSurface::create(EGLDisplay display, EGLConfig config,
EGLConfig config, int p_width, int p_height) {
int p_width,
int p_height) {
// allocate space for the WindowSurface object // allocate space for the WindowSurface object
WindowSurface *win = new WindowSurface(display, config); WindowSurface *win = new WindowSurface(display, config);
if (!win) { if (!win) {
@ -63,7 +59,6 @@ WindowSurface *WindowSurface::create(EGLDisplay display,
return win; return win;
} }
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) { void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) {
mAttachedColorBuffer = p_colorBuffer; mAttachedColorBuffer = p_colorBuffer;
@ -113,9 +108,7 @@ bool WindowSurface::flushColorBuffer() {
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
if (!s_egl.eglMakeCurrent(mDisplay, if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface,
mSurface,
mSurface,
mDrawContext->getEGLContext())) { mDrawContext->getEGLContext())) {
fprintf(stderr, "Error making draw context current\n"); fprintf(stderr, "Error making draw context current\n");
return false; return false;
@ -129,8 +122,7 @@ bool WindowSurface::flushColorBuffer() {
return true; return true;
} }
bool WindowSurface::resize(unsigned int p_width, unsigned int p_height) bool WindowSurface::resize(unsigned int p_width, unsigned int p_height) {
{
if (mSurface && mWidth == p_width && mHeight == p_height) { if (mSurface && mWidth == p_width && mHeight == p_height) {
// no need to resize // no need to resize
return true; return true;
@ -140,13 +132,12 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
EGLSurface prevPbuf = mSurface; EGLSurface prevPbuf = mSurface;
bool needRebindContext = mSurface && bool needRebindContext =
(prevReadSurf == mSurface || mSurface && (prevReadSurf == mSurface || prevDrawSurf == mSurface);
prevDrawSurf == mSurface);
if (needRebindContext) { if (needRebindContext) {
s_egl.eglMakeCurrent( s_egl.eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); EGL_NO_CONTEXT);
} }
// //
@ -164,9 +155,7 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
EGL_WIDTH, (EGLint)p_width, EGL_HEIGHT, (EGLint)p_height, EGL_NONE, EGL_WIDTH, (EGLint)p_width, EGL_HEIGHT, (EGLint)p_height, EGL_NONE,
}; };
mSurface = s_egl.eglCreatePbufferSurface(mDisplay, mSurface = s_egl.eglCreatePbufferSurface(mDisplay, mConfig, pbufAttribs);
mConfig,
pbufAttribs);
if (mSurface == EGL_NO_SURFACE) { if (mSurface == EGL_NO_SURFACE) {
fprintf(stderr, "Renderer error: failed to create/resize pbuffer!!\n"); fprintf(stderr, "Renderer error: failed to create/resize pbuffer!!\n");
return false; return false;
@ -177,10 +166,8 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
if (needRebindContext) { if (needRebindContext) {
s_egl.eglMakeCurrent( s_egl.eglMakeCurrent(
mDisplay, mDisplay, (prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf,
(prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf, (prevReadSurf == prevPbuf) ? mSurface : prevReadSurf, prevContext);
(prevReadSurf == prevPbuf) ? mSurface : prevReadSurf,
prevContext);
} }
return true; return true;

View file

@ -33,9 +33,7 @@ public:
// |config| is the host EGLConfig value. // |config| is the host EGLConfig value.
// |width| and |height| are the initial size of the Pbuffer. // |width| and |height| are the initial size of the Pbuffer.
// Return a new WindowSurface instance on success, or NULL on failure. // Return a new WindowSurface instance on success, or NULL on failure.
static WindowSurface* create(EGLDisplay display, static WindowSurface* create(EGLDisplay display, EGLConfig config, int width,
EGLConfig config,
int width,
int height); int height);
// Destructor. // Destructor.
@ -58,11 +56,7 @@ public:
bool flushColorBuffer(); bool flushColorBuffer();
// Used by bind() below. // Used by bind() below.
enum BindType { enum BindType { BIND_READ, BIND_DRAW, BIND_READDRAW };
BIND_READ,
BIND_DRAW,
BIND_READDRAW
};
// TODO(digit): What is this used for exactly? For example, the // TODO(digit): What is this used for exactly? For example, the
// mReadContext is never used by this class. The mDrawContext is only // mReadContext is never used by this class. The mDrawContext is only

View file

@ -15,46 +15,52 @@
* *
*/ */
#include "anbox/logger.h"
#include "anbox/graphics/gl_renderer_server.h" #include "anbox/graphics/gl_renderer_server.h"
#include "anbox/graphics/layer_composer.h"
#include "anbox/graphics/emugl/RenderControl.h" #include "anbox/graphics/emugl/RenderControl.h"
#include "anbox/graphics/layer_composer.h"
#include "anbox/logger.h"
#include "anbox/wm/manager.h" #include "anbox/wm/manager.h"
#include "OpenglRender/render_api.h" #include "OpenglRender/render_api.h"
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <stdexcept>
#include <cstdarg> #include <cstdarg>
#include <stdexcept>
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm) : GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm)
wm_(wm), : wm_(wm), composer_(std::make_shared<LayerComposer>(wm)) {
composer_(std::make_shared<LayerComposer>(wm))
{
if (utils::is_env_set("USE_HOST_GLES")) { if (utils::is_env_set("USE_HOST_GLES")) {
// Force the host EGL/GLES libraries as translator implementation // Force the host EGL/GLES libraries as translator implementation
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0); ::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0);
::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0); ::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0);
::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0); ::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0);
} else { } else {
auto translator_dir = utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP"); auto translator_dir =
::setenv("ANDROID_EGL_LIB", utils::string_format("%s/libEGL_translator.so", translator_dir).c_str(), 0); utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP");
::setenv("ANDROID_GLESv1_LIB", utils::string_format("%s/libGLES_CM_translator.so", translator_dir).c_str(), 0); ::setenv(
::setenv("ANDROID_GLESv2_LIB", utils::string_format("%s/libGLES_V2_translator.so", translator_dir).c_str(), 0); "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);
} }
if (!initLibrary()) if (!initLibrary())
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to initialize OpenGL renderer"));
registerLayerComposer(composer_); registerLayerComposer(composer_);
} }
GLRendererServer::~GLRendererServer() { GLRendererServer::~GLRendererServer() { stopOpenGLRenderer(); }
stopOpenGLRenderer();
}
void logger_write(const char *format, ...) { void logger_write(const char *format, ...) {
char message[2048]; char message[2048];
@ -73,17 +79,19 @@ void GLRendererServer::start() {
log_funcs.fine = logger_write; log_funcs.fine = logger_write;
char server_addr[256] = {0}; char server_addr[256] = {0};
// The width & height we supply here are the dimensions the internal framebuffer // The width & height we supply here are the dimensions the internal
// will use. Making this static prevents us for now to resize the window we create // framebuffer
// will use. Making this static prevents us for now to resize the window we
// create
// later for the actual display. // later for the actual display.
if (!initOpenGLRenderer(0, server_addr, sizeof(server_addr), log_funcs, logger_write)) if (!initOpenGLRenderer(0, server_addr, sizeof(server_addr), log_funcs,
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer")); logger_write))
BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to setup OpenGL renderer"));
socket_path_ = server_addr; socket_path_ = server_addr;
} }
std::string GLRendererServer::socket_path() const { std::string GLRendererServer::socket_path() const { return socket_path_; }
return socket_path_;
}
} // namespace graphics } // namespace graphics
} // namespace anbox } // namespace anbox

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_ #ifndef ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
#define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_ #define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
#include <string>
#include <memory> #include <memory>
#include <string>
namespace anbox { namespace anbox {
namespace input { namespace input {

View file

@ -17,36 +17,31 @@
#include "anbox/graphics/layer_composer.h" #include "anbox/graphics/layer_composer.h"
#include "anbox/graphics/emugl/Renderer.h" #include "anbox/graphics/emugl/Renderer.h"
#include "anbox/wm/manager.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include "anbox/wm/manager.h"
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
LayerComposer::LayerComposer(const std::shared_ptr<wm::Manager> &wm) : LayerComposer::LayerComposer(const std::shared_ptr<wm::Manager> &wm)
wm_(wm) : wm_(wm) {}
{
}
LayerComposer::~LayerComposer() LayerComposer::~LayerComposer() {}
{
}
void LayerComposer::submit_layers(const RenderableList &renderables) void LayerComposer::submit_layers(const RenderableList &renderables) {
{
std::map<std::shared_ptr<wm::Window>, RenderableList> win_layers; std::map<std::shared_ptr<wm::Window>, RenderableList> win_layers;
for (const auto &renderable : renderables) for (const auto &renderable : renderables) {
{
// Ignore all surfaces which are not meant for a task // Ignore all surfaces which are not meant for a task
if (!utils::string_starts_with(renderable.name(), "org.anbox.surface.")) if (!utils::string_starts_with(renderable.name(), "org.anbox.surface."))
continue; continue;
wm::Task::Id task_id = 0; wm::Task::Id task_id = 0;
if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) != 1 || !task_id) if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) !=
1 ||
!task_id)
continue; continue;
auto w = wm_->find_window_for_task(task_id); auto w = wm_->find_window_for_task(task_id);
if (!w) if (!w) continue;
continue;
if (win_layers.find(w) == win_layers.end()) { if (win_layers.find(w) == win_layers.end()) {
win_layers.insert({w, {renderable}}); win_layers.insert({w, {renderable}});
@ -56,23 +51,20 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
win_layers[w].push_back(renderable); win_layers[w].push_back(renderable);
} }
for (const auto &w : win_layers) for (const auto &w : win_layers) {
{
const auto &window = w.first; const auto &window = w.first;
const auto &renderables = w.second; const auto &renderables = w.second;
RenderableList final_renderables; RenderableList final_renderables;
auto new_window_frame = Rect::Invalid; auto new_window_frame = Rect::Invalid;
for (auto &r : renderables) for (auto &r : renderables) {
{
if (new_window_frame == Rect::Invalid) if (new_window_frame == Rect::Invalid)
new_window_frame = r.screen_position(); new_window_frame = r.screen_position();
else else
new_window_frame.merge(r.screen_position()); new_window_frame.merge(r.screen_position());
} }
for (auto &r : renderables) for (auto &r : renderables) {
{
// As we get absolute display coordinates from the Android hwcomposer we // As we get absolute display coordinates from the Android hwcomposer we
// need to recalculate all layer coordinates into relatives ones to the // need to recalculate all layer coordinates into relatives ones to the
// window they are drawn into. // window they are drawn into.
@ -80,8 +72,7 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
auto top = r.screen_position().top() - new_window_frame.top(); auto top = r.screen_position().top() - new_window_frame.top();
auto rect = Rect{ auto rect = Rect{
left - r.crop().left(), left - r.crop().left(), top - r.crop().top(),
top - r.crop().top(),
r.screen_position().width() + left, r.screen_position().width() + left,
r.screen_position().height() + top, r.screen_position().height() + top,
}; };
@ -93,7 +84,8 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
w.first->update_frame(new_window_frame); w.first->update_frame(new_window_frame);
Renderer::get()->draw(window->native_handle(), Renderer::get()->draw(
window->native_handle(),
Rect{0, 0, window->frame().width(), window->frame().height()}, Rect{0, 0, window->frame().width(), window->frame().height()},
final_renderables); final_renderables);
} }

View file

@ -15,43 +15,44 @@
* *
*/ */
#include "anbox/logger.h"
#include "anbox/graphics/opengles_message_processor.h" #include "anbox/graphics/opengles_message_processor.h"
#include "anbox/network/local_socket_messenger.h" #include "anbox/logger.h"
#include "anbox/network/connections.h" #include "anbox/network/connections.h"
#include "anbox/network/delegate_message_processor.h" #include "anbox/network/delegate_message_processor.h"
#include "anbox/network/local_socket_messenger.h"
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::string &renderer_socket_path, OpenGlesMessageProcessor::OpenGlesMessageProcessor(
const std::shared_ptr<Runtime> &rt, const std::string &renderer_socket_path, const std::shared_ptr<Runtime> &rt,
const std::shared_ptr<network::SocketMessenger> &messenger) : const std::shared_ptr<network::SocketMessenger> &messenger)
client_messenger_(messenger) { : client_messenger_(messenger) {
connect_and_attach(renderer_socket_path, rt); connect_and_attach(renderer_socket_path, rt);
} }
OpenGlesMessageProcessor::~OpenGlesMessageProcessor() { OpenGlesMessageProcessor::~OpenGlesMessageProcessor() {}
}
void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path, void OpenGlesMessageProcessor::connect_and_attach(
const std::shared_ptr<Runtime> &rt) { const std::string &socket_path, const std::shared_ptr<Runtime> &rt) {
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(rt->service()); rt->service());
socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path)); socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path));
messenger_ = std::make_shared<network::LocalSocketMessenger>(socket); messenger_ = std::make_shared<network::LocalSocketMessenger>(socket);
renderer_ = std::make_shared<network::SocketConnection>( renderer_ = std::make_shared<network::SocketConnection>(
messenger_, messenger_, 0, nullptr, messenger_, messenger_, 0, nullptr,
std::make_shared<network::DelegateMessageProcessor>([&](const std::vector<std::uint8_t> &data) { std::make_shared<network::DelegateMessageProcessor>(
client_messenger_->send(reinterpret_cast<const char*>(data.data()), data.size()); [&](const std::vector<std::uint8_t> &data) {
client_messenger_->send(reinterpret_cast<const char *>(data.data()),
data.size());
return true; return true;
})); }));
renderer_->set_name("opengles-renderer"); renderer_->set_name("opengles-renderer");
renderer_->read_next_message(); renderer_->read_next_message();
} }
bool OpenGlesMessageProcessor::process_data(const std::vector<std::uint8_t> &data) { bool OpenGlesMessageProcessor::process_data(
const std::vector<std::uint8_t> &data) {
messenger_->send(reinterpret_cast<const char *>(data.data()), data.size()); messenger_->send(reinterpret_cast<const char *>(data.data()), data.size());
return true; return true;
} }

View file

@ -22,16 +22,17 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "anbox/runtime.h"
#include "anbox/network/message_processor.h" #include "anbox/network/message_processor.h"
#include "anbox/network/socket_messenger.h"
#include "anbox/network/socket_connection.h" #include "anbox/network/socket_connection.h"
#include "anbox/network/socket_messenger.h"
#include "anbox/runtime.h"
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
class OpenGlesMessageProcessor : public network::MessageProcessor { class OpenGlesMessageProcessor : public network::MessageProcessor {
public: public:
OpenGlesMessageProcessor(const std::string &renderer_socket_path, OpenGlesMessageProcessor(
const std::string &renderer_socket_path,
const std::shared_ptr<Runtime> &rt, const std::shared_ptr<Runtime> &rt,
const std::shared_ptr<network::SocketMessenger> &messenger); const std::shared_ptr<network::SocketMessenger> &messenger);
~OpenGlesMessageProcessor(); ~OpenGlesMessageProcessor();

View file

@ -17,7 +17,6 @@
* Kevin DuBois <kevin.dubois@canonical.com> * Kevin DuBois <kevin.dubois@canonical.com>
*/ */
#ifndef ANBOX_GRAPHICS_PRIMITIVES_H_ #ifndef ANBOX_GRAPHICS_PRIMITIVES_H_
#define ANBOX_GRAPHICS_PRIMITIVES_H_ #define ANBOX_GRAPHICS_PRIMITIVES_H_
@ -25,19 +24,15 @@
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
struct Vertex struct Vertex {
{
GLfloat position[3]; GLfloat position[3];
GLfloat texcoord[2]; GLfloat texcoord[2];
}; };
struct Primitive struct Primitive {
{
enum { max_vertices = 4 }; enum { max_vertices = 4 };
Primitive() Primitive() : type(GL_TRIANGLE_FAN), nvertices(4) {
: type(GL_TRIANGLE_FAN), nvertices(4)
{
// Default is a quad. Just need to assign vertices[] and tex_id. // Default is a quad. Just need to assign vertices[] and tex_id.
} }

View file

@ -22,59 +22,47 @@
namespace anbox { namespace anbox {
namespace graphics { namespace graphics {
void ProgramFamily::Shader::init(GLenum type, const GLchar* src) void ProgramFamily::Shader::init(GLenum type, const GLchar* src) {
{ if (!id) {
if (!id)
{
id = s_gles2.glCreateShader(type); id = s_gles2.glCreateShader(type);
if (id) if (id) {
{
s_gles2.glShaderSource(id, 1, &src, NULL); s_gles2.glShaderSource(id, 1, &src, NULL);
s_gles2.glCompileShader(id); s_gles2.glCompileShader(id);
GLint ok; GLint ok;
s_gles2.glGetShaderiv(id, GL_COMPILE_STATUS, &ok); s_gles2.glGetShaderiv(id, GL_COMPILE_STATUS, &ok);
if (!ok) if (!ok) {
{
GLchar log[1024]; GLchar log[1024];
s_gles2.glGetShaderInfoLog(id, sizeof log - 1, NULL, log); s_gles2.glGetShaderInfoLog(id, sizeof log - 1, NULL, log);
log[sizeof log - 1] = '\0'; log[sizeof log - 1] = '\0';
s_gles2.glDeleteShader(id); s_gles2.glDeleteShader(id);
id = 0; id = 0;
throw std::runtime_error(std::string("Compile failed: ")+ throw std::runtime_error(std::string("Compile failed: ") + log +
log + " for:\n" + src); " for:\n" + src);
} }
} }
} }
} }
ProgramFamily::~ProgramFamily() noexcept ProgramFamily::~ProgramFamily() noexcept {
{
// shader and program lifetimes are managed manually, so that we don't // shader and program lifetimes are managed manually, so that we don't
// need any reference counting or to worry about how many copy constructions // need any reference counting or to worry about how many copy constructions
// might have been followed by destructor calls during container resizes. // might have been followed by destructor calls during container resizes.
for (auto& p : program) for (auto& p : program) {
{ if (p.second.id) s_gles2.glDeleteProgram(p.second.id);
if (p.second.id)
s_gles2.glDeleteProgram(p.second.id);
} }
for (auto& v : vshader) for (auto& v : vshader) {
{ if (v.second.id) s_gles2.glDeleteShader(v.second.id);
if (v.second.id)
s_gles2.glDeleteShader(v.second.id);
} }
for (auto& f : fshader) for (auto& f : fshader) {
{ if (f.second.id) s_gles2.glDeleteShader(f.second.id);
if (f.second.id)
s_gles2.glDeleteShader(f.second.id);
} }
} }
GLuint ProgramFamily::add_program(const GLchar* const vshader_src, GLuint ProgramFamily::add_program(const GLchar* const vshader_src,
const GLchar* const fshader_src) const GLchar* const fshader_src) {
{
auto& v = vshader[vshader_src]; auto& v = vshader[vshader_src];
if (!v.id) v.init(GL_VERTEX_SHADER, vshader_src); if (!v.id) v.init(GL_VERTEX_SHADER, vshader_src);
@ -82,16 +70,14 @@ GLuint ProgramFamily::add_program(const GLchar* const vshader_src,
if (!f.id) f.init(GL_FRAGMENT_SHADER, fshader_src); if (!f.id) f.init(GL_FRAGMENT_SHADER, fshader_src);
auto& p = program[{v.id, f.id}]; auto& p = program[{v.id, f.id}];
if (!p.id) if (!p.id) {
{
p.id = s_gles2.glCreateProgram(); p.id = s_gles2.glCreateProgram();
s_gles2.glAttachShader(p.id, v.id); s_gles2.glAttachShader(p.id, v.id);
s_gles2.glAttachShader(p.id, f.id); s_gles2.glAttachShader(p.id, f.id);
s_gles2.glLinkProgram(p.id); s_gles2.glLinkProgram(p.id);
GLint ok; GLint ok;
s_gles2.glGetProgramiv(p.id, GL_LINK_STATUS, &ok); s_gles2.glGetProgramiv(p.id, GL_LINK_STATUS, &ok);
if (!ok) if (!ok) {
{
GLchar log[1024]; GLchar log[1024];
s_gles2.glGetProgramInfoLog(p.id, sizeof log - 1, NULL, log); s_gles2.glGetProgramInfoLog(p.id, sizeof log - 1, NULL, log);
log[sizeof log - 1] = '\0'; log[sizeof log - 1] = '\0';

View file

@ -19,9 +19,9 @@
#ifndef ANBOX_GRAPHICS_PROGRAM_FAMILY_H_ #ifndef ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
#define ANBOX_GRAPHICS_PROGRAM_FAMILY_H_ #define ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
#include <utility>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <utility>
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
@ -35,8 +35,7 @@ namespace graphics {
* different programs within the family to share common patterns of uniform * different programs within the family to share common patterns of uniform
* usage too. * usage too.
*/ */
class ProgramFamily class ProgramFamily {
{
public: public:
ProgramFamily() = default; ProgramFamily() = default;
ProgramFamily(ProgramFamily const&) = delete; ProgramFamily(ProgramFamily const&) = delete;
@ -47,8 +46,7 @@ public:
const GLchar* const static_fshader_src); const GLchar* const static_fshader_src);
private: private:
struct Shader struct Shader {
{
GLuint id = 0; GLuint id = 0;
void init(GLenum type, const GLchar* src); void init(GLenum type, const GLchar* src);
}; };
@ -56,8 +54,7 @@ private:
ShaderMap vshader, fshader; ShaderMap vshader, fshader;
typedef std::pair<GLuint, GLuint> ShaderPair; typedef std::pair<GLuint, GLuint> ShaderPair;
struct Program struct Program {
{
GLuint id = 0; GLuint id = 0;
}; };
std::map<ShaderPair, Program> program; std::map<ShaderPair, Program> program;

View file

@ -25,17 +25,16 @@ namespace graphics {
const Rect Rect::Invalid{-1, -1, -1, -1}; const Rect Rect::Invalid{-1, -1, -1, -1};
const Rect Rect::Empty{0, 0, 0, 0}; const Rect Rect::Empty{0, 0, 0, 0};
void Rect::merge(const Rect &rhs) void Rect::merge(const Rect &rhs) {
{
left_ = std::min(left_, rhs.left()); left_ = std::min(left_, rhs.left());
top_ = std::min(top_, rhs.top()); top_ = std::min(top_, rhs.top());
right_ = std::max(right_, rhs.right()); right_ = std::max(right_, rhs.right());
bottom_ = std::max(bottom_, rhs.bottom()); bottom_ = std::max(bottom_, rhs.bottom());
} }
std::ostream& operator<<(std::ostream &out, const Rect &rect) std::ostream &operator<<(std::ostream &out, const Rect &rect) {
{ return out << "{" << rect.left() << "," << rect.top() << "," << rect.right()
return out << "{" << rect.left() << "," << rect.top() << ","<< rect.right() << "," << rect.bottom() << "}"; << "," << rect.bottom() << "}";
} }
} // namespace graphics } // namespace graphics
} // namespace anbox } // namespace anbox

View file

@ -31,65 +31,35 @@ public:
inline Rect() : Rect(Empty) {} inline Rect() : Rect(Empty) {}
inline Rect(const std::int32_t &left, inline Rect(const std::int32_t &left, const std::int32_t &top,
const std::int32_t &top, const std::int32_t &right, const std::int32_t &bottom)
const std::int32_t &right, : left_(left), top_(top), right_(right), bottom_(bottom) {}
const std::int32_t &bottom) :
left_(left),
top_(top),
right_(right),
bottom_(bottom) {
}
inline Rect(const std::int32_t &width, const std::int32_t &height) : inline Rect(const std::int32_t &width, const std::int32_t &height)
left_(0), : left_(0), top_(0), right_(width), bottom_(height) {}
top_(0),
right_(width),
bottom_(height) {
}
inline void clear() { inline void clear() { left_ = top_ = right_ = bottom_ = 0; }
left_ = top_ = right_ = bottom_ = 0;
}
inline bool valid() const { inline bool valid() const { return width() >= 0 && height() >= 0; }
return width() >= 0 && height() >= 0;
}
inline std::int32_t width() const { inline std::int32_t width() const { return right_ - left_; }
return right_ - left_;
}
inline std::int32_t height() const { inline std::int32_t height() const { return bottom_ - top_; }
return bottom_ - top_;
}
inline std::int32_t left() const { inline std::int32_t left() const { return left_; }
return left_;
}
inline std::int32_t top() const { inline std::int32_t top() const { return top_; }
return top_;
}
inline std::int32_t right() const { inline std::int32_t right() const { return right_; }
return right_;
}
inline std::int32_t bottom() const { inline std::int32_t bottom() const { return bottom_; }
return bottom_;
}
inline bool operator==(const Rect &rhs) const { inline bool operator==(const Rect &rhs) const {
return (left_ == rhs.left() && return (left_ == rhs.left() && top_ == rhs.top() && right_ == rhs.right() &&
top_ == rhs.top() &&
right_ == rhs.right() &&
bottom_ == rhs.bottom()); bottom_ == rhs.bottom());
} }
inline bool operator != (const Rect &rhs) const { inline bool operator!=(const Rect &rhs) const { return !operator==(rhs); }
return !operator == (rhs);
}
void merge(const Rect &rhs); void merge(const Rect &rhs);

View file

@ -16,37 +16,39 @@
*/ */
#include "anbox/input/device.h" #include "anbox/input/device.h"
#include "anbox/logger.h"
#include "anbox/network/delegate_connection_creator.h" #include "anbox/network/delegate_connection_creator.h"
#include "anbox/network/delegate_message_processor.h" #include "anbox/network/delegate_message_processor.h"
#include "anbox/network/local_socket_messenger.h" #include "anbox/network/local_socket_messenger.h"
#include "anbox/qemu/null_message_processor.h" #include "anbox/qemu/null_message_processor.h"
#include "anbox/logger.h"
#include <time.h> #include <time.h>
namespace anbox { namespace anbox {
namespace input { namespace input {
std::shared_ptr<Device> Device::create(const std::string &path, const std::shared_ptr<Runtime> &runtime) { std::shared_ptr<Device> Device::create(
const std::string &path, const std::shared_ptr<Runtime> &runtime) {
auto sp = std::make_shared<Device>(); auto sp = std::make_shared<Device>();
auto delegate_connector = std::make_shared<network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>( auto delegate_connector = std::make_shared<
[sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) { network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>(
sp->new_client(socket); [sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const
}); &socket) { sp->new_client(socket); });
sp->connector_ = std::make_shared<network::PublishedSocketConnector>(path, runtime, delegate_connector); sp->connector_ = std::make_shared<network::PublishedSocketConnector>(
path, runtime, delegate_connector);
return sp; return sp;
} }
Device::Device() : Device::Device()
next_connection_id_(0), : next_connection_id_(0),
connections_(std::make_shared<network::Connections<network::SocketConnection>>()) { connections_(
std::make_shared<network::Connections<network::SocketConnection>>()) {
::memset(&info_, 0, sizeof(info_)); ::memset(&info_, 0, sizeof(info_));
} }
Device::~Device() { Device::~Device() {}
}
void Device::send_events(const std::vector<Event> &events) { void Device::send_events(const std::vector<Event> &events) {
struct CompatEvent { struct CompatEvent {
@ -143,16 +145,15 @@ void Device::set_unique_id(const std::string &unique_id) {
snprintf(info_.unique_id, 80, "%s", unique_id.c_str()); snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
} }
std::string Device::socket_path() const { std::string Device::socket_path() const { return connector_->socket_file(); }
return connector_->socket_file();
}
int Device::next_id() { int Device::next_id() { return next_connection_id_++; }
return next_connection_id_++;
}
void Device::new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) { void Device::new_client(
auto const messenger = std::make_shared<network::LocalSocketMessenger>(socket); std::shared_ptr<boost::asio::local::stream_protocol::socket> const
&socket) {
auto const messenger =
std::make_shared<network::LocalSocketMessenger>(socket);
auto const &connection = std::make_shared<network::SocketConnection>( auto const &connection = std::make_shared<network::SocketConnection>(
messenger, messenger, next_id(), connections_, messenger, messenger, next_id(), connections_,
std::make_shared<qemu::NullMessageProcessor>()); std::make_shared<qemu::NullMessageProcessor>());

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_INPUT_DEVICE_H_ #ifndef ANBOX_INPUT_DEVICE_H_
#define ANBOX_INPUT_DEVICE_H_ #define ANBOX_INPUT_DEVICE_H_
#include "anbox/network/published_socket_connector.h"
#include "anbox/network/connections.h" #include "anbox/network/connections.h"
#include "anbox/network/published_socket_connector.h"
#include "anbox/network/socket_connection.h" #include "anbox/network/socket_connection.h"
#include "anbox/runtime.h" #include "anbox/runtime.h"
@ -37,13 +37,15 @@ struct Event {
class Device : public std::enable_shared_from_this<Device> { class Device : public std::enable_shared_from_this<Device> {
public: public:
static std::shared_ptr<Device> create(const std::string &path, const std::shared_ptr<Runtime> &runtime); static std::shared_ptr<Device> create(
const std::string &path, const std::shared_ptr<Runtime> &runtime);
Device(); Device();
~Device(); ~Device();
void send_events(const std::vector<Event> &events); void send_events(const std::vector<Event> &events);
void send_event(const std::uint16_t &code, const std::uint16_t &event, const std::int32_t &value); void send_event(const std::uint16_t &code, const std::uint16_t &event,
const std::int32_t &value);
void set_name(const std::string &name); void set_name(const std::string &name);
void set_driver_version(const int &version); void set_driver_version(const int &version);
@ -65,10 +67,12 @@ public:
private: private:
int next_id(); int next_id();
void new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket); void new_client(std::shared_ptr<
boost::asio::local::stream_protocol::socket> const &socket);
// NOTE: If you modify this struct you have to modify the version on // NOTE: If you modify this struct you have to modify the version on
// the Android side too. See frameworks/native/services/inputflinger/EventHub.cpp // the Android side too. See
// frameworks/native/services/inputflinger/EventHub.cpp
struct Info { struct Info {
char name[80]; char name[80];
int driver_version; int driver_version;

View file

@ -16,22 +16,20 @@
*/ */
#include "anbox/input/manager.h" #include "anbox/input/manager.h"
#include "anbox/config.h"
#include "anbox/input/device.h" #include "anbox/input/device.h"
#include "anbox/runtime.h" #include "anbox/runtime.h"
#include "anbox/config.h"
#include "anbox/utils.h" #include "anbox/utils.h"
#include <boost/format.hpp> #include <boost/format.hpp>
namespace anbox { namespace anbox {
namespace input { namespace input {
Manager::Manager(const std::shared_ptr<Runtime> &runtime) : Manager::Manager(const std::shared_ptr<Runtime> &runtime) : runtime_(runtime) {
runtime_(runtime) {
utils::ensure_paths({config::host_input_device_path()}); utils::ensure_paths({config::host_input_device_path()});
} }
Manager::~Manager() { Manager::~Manager() {}
}
std::shared_ptr<Device> Manager::create_device() { std::shared_ptr<Device> Manager::create_device() {
const auto id = next_id(); const auto id = next_id();
@ -47,7 +45,8 @@ std::uint32_t Manager::next_id() {
} }
std::string Manager::build_device_path(const std::uint32_t &id) { std::string Manager::build_device_path(const std::uint32_t &id) {
return (boost::format("%1%/event%2%") % config::host_input_device_path() % id).str(); return (boost::format("%1%/event%2%") % config::host_input_device_path() % id)
.str();
} }
} // namespace input } // namespace input

View file

@ -18,8 +18,8 @@
#ifndef ANBOX_INPUT_MANAGER_H_ #ifndef ANBOX_INPUT_MANAGER_H_
#define ANBOX_INPUT_MANAGER_H_ #define ANBOX_INPUT_MANAGER_H_
#include <memory>
#include <map> #include <map>
#include <memory>
namespace anbox { namespace anbox {
class Runtime; class Runtime;

Some files were not shown because too many files have changed in this diff Show more