Reformat all code and use the Google cpp code style

This commit is contained in:
Simon Fels 2016-12-02 17:36:54 +01:00
commit b10382d2d8
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

@ -33,9 +33,8 @@ struct Intent {
std::vector<std::string> categories; std::vector<std::string> categories;
}; };
std::ostream& operator<<(std::ostream &out, const Intent &intent); 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

@ -28,7 +28,7 @@
namespace anbox { namespace anbox {
namespace application { namespace application {
class LauncherStorage { class LauncherStorage {
public: public:
LauncherStorage(const boost::filesystem::path &path); LauncherStorage(const boost::filesystem::path &path);
~LauncherStorage(); ~LauncherStorage();
@ -40,7 +40,7 @@ public:
void add(const Item &item); void add(const Item &item);
private: private:
boost::filesystem::path path_; boost::filesystem::path path_;
}; };
} // namespace application } // namespace application

View file

@ -18,14 +18,14 @@
#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>
namespace anbox { namespace anbox {
class ApplicationManager : public DoNotCopyOrMove { class ApplicationManager : public DoNotCopyOrMove {
public: public:
virtual void launch(const android::Intent &intent) = 0; virtual void launch(const android::Intent &intent) = 0;
}; };
} // namespace anbox } // namespace anbox

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,39 +58,34 @@ 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(
(void) request; Request<protobuf::rpc::Void> *request) {
(void)request;
launch_wait_handle_.result_received(); launch_wait_handle_.result_received();
} }
@ -111,19 +102,17 @@ 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) {
(void) request; (void)request;
set_focused_task_handle_.result_received(); set_focused_task_handle_.result_received();
} }
} // namespace bridge } // namespace bridge

View file

@ -35,7 +35,7 @@ class Channel;
} // namespace rpc } // namespace rpc
namespace bridge { namespace bridge {
class AndroidApiStub : public anbox::ApplicationManager { class AndroidApiStub : public anbox::ApplicationManager {
public: public:
AndroidApiStub(); AndroidApiStub();
~AndroidApiStub(); ~AndroidApiStub();
@ -46,12 +46,12 @@ public:
void set_focused_task(const std::int32_t &id); void set_focused_task(const std::int32_t &id);
private: private:
void ensure_rpc_channel(); void ensure_rpc_channel();
template<typename Response> template <typename Response>
struct Request { struct Request {
Request() : response(std::make_shared<Response>()), success(true) { } Request() : response(std::make_shared<Response>()), success(true) {}
std::shared_ptr<Response> response; std::shared_ptr<Response> response;
bool success; bool success;
}; };

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() {}
void PlatformApiSkeleton::handle_boot_finished_event(
const anbox::protobuf::bridge::BootFinishedEvent &event) {
(void)event;
if (boot_finished_handler_) boot_finished_handler_();
} }
PlatformApiSkeleton::~PlatformApiSkeleton() { void PlatformApiSkeleton::handle_window_state_update_event(
} const anbox::protobuf::bridge::WindowStateUpdateEvent &event) {
auto convert_window_state = [](
void PlatformApiSkeleton::handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event) { const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState
(void) event; &window) {
if (boot_finished_handler_)
boot_finished_handler_();
}
void PlatformApiSkeleton::handle_window_state_update_event(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

@ -48,19 +48,23 @@ class LauncherStorage;
} // namespace application } // namespace application
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);
private: private:
std::shared_ptr<rpc::PendingCallCache> pending_calls_; std::shared_ptr<rpc::PendingCallCache> pending_calls_;
std::shared_ptr<wm::Manager> window_manager_; std::shared_ptr<wm::Manager> window_manager_;
std::shared_ptr<application::LauncherStorage> launcher_storage_; std::shared_ptr<application::LauncherStorage> launcher_storage_;

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

@ -24,16 +24,17 @@ namespace anbox {
namespace bridge { 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();
void dispatch(rpc::Invocation const& invocation) override; void dispatch(rpc::Invocation const &invocation) override;
void process_event_sequence(const std::string &event) override; void process_event_sequence(const std::string &event) override;
private: private:
std::shared_ptr<PlatformApiSkeleton> server_; std::shared_ptr<PlatformApiSkeleton> server_;
}; };
} // namespace anbox } // namespace anbox

View file

@ -28,11 +28,11 @@ namespace po = boost::program_options;
namespace { namespace {
namespace pattern { namespace pattern {
static constexpr const char* help_for_command_with_subcommands = static constexpr const char* help_for_command_with_subcommands =
"NAME:\n" "NAME:\n"
" %1% - %2%\n" " %1% - %2%\n"
"\n" "\n"
"USAGE:\n" "USAGE:\n"
" %3% [command options] [arguments...]"; " %3% [command options] [arguments...]";
static constexpr const char* commands = "COMMANDS:"; static constexpr const char* commands = "COMMANDS:";
static constexpr const char* command = " %1% %2%"; static constexpr const char* command = " %1% %2%";
@ -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

@ -34,45 +34,37 @@
namespace anbox { 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,9 +74,8 @@ 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;
@ -95,129 +86,118 @@ public:
/// @brief description returns a human-readable description of the flag. /// @brief description returns a human-readable description of the flag.
const Description& description() const; const Description& description() const;
protected: protected:
/// @brief Flag creates a new instance, initializing name and description /// @brief Flag creates a new instance, initializing name and description
/// from the given values. /// from the given values.
Flag(const Name& name, const Description& description); Flag(const Name& name, const Description& description);
private: private:
Name name_; Name name_;
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
template<typename T> /// read/write values to/from strings.
class TypedFlag : public Flag template <typename T>
{ 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;
} }
private: 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();
} }
private: 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
template<typename T> /// a value is always read on notify, even if the Optional<T> wasn't initialized
class OptionalTypedReferenceFlag : public Flag /// previously.
{ template <typename T>
public: class OptionalTypedReferenceFlag : public Flag {
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;
} }
private: private:
std::reference_wrapper<Optional<T>> value_; std::reference_wrapper<Optional<T>> value_;
}; };
/// @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.
@ -238,8 +218,9 @@ public:
/// @brief help prints information about a command to out. /// @brief help prints information about a command to out.
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.
@ -249,21 +230,23 @@ protected:
/// @brief description adjusts the description string of the command to d. /// @brief description adjusts the description string of the command to d.
// virtual void description(const Description& d); // virtual void description(const Description& d);
private: private:
Name name_; Name name_;
Usage usage_; Usage usage_;
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);
@ -273,22 +256,24 @@ public:
// From Command // From Command
int run(const Context& context) override; int run(const Context& context) override;
void help(std::ostream &out) override; void help(std::ostream& out) override;
private: private:
std::unordered_map<std::string, Command::Ptr> commands_; std::unordered_map<std::string, Command::Ptr> commands_;
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);
@ -298,27 +283,26 @@ public:
// From Command // From Command
int run(const Context& context) override; int run(const Context& context) override;
void help(std::ostream &out) override; void help(std::ostream& out) override;
private: private:
std::set<Flag::Ptr> flags_; std::set<Flag::Ptr> flags_;
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
/// @brief HelpFor initializes a new instance with the given reference to a cmd. /// cmd.
explicit Help(Command& cmd); explicit Help(Command& cmd);
// From Command // From Command
int run(const Context &context) override; int run(const Context& context) override;
void help(std::ostream &out) override; void help(std::ostream& out) override;
private: private:
/// @cond /// @cond
Command& command; Command& command;
/// @endcond /// @endcond
@ -329,28 +313,31 @@ private:
std::vector<std::string> args(int argc, char** argv); 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,
template<typename T> /// notifying updates to value.
typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, T& value) template <typename T>
{ 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,
template<typename T> /// updating the given optional value.
typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, Optional<T>& value) template <typename T>
{ 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,18 +17,19 @@
#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

@ -27,7 +27,7 @@
namespace anbox { namespace anbox {
namespace cmds { namespace cmds {
class ContainerManager : public cli::CommandWithFlagsAndAction { class ContainerManager : public cli::CommandWithFlagsAndAction {
public: public:
ContainerManager(); ContainerManager();
}; };
} // namespace cmds } // namespace cmds

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

@ -27,10 +27,10 @@
namespace anbox { namespace anbox {
namespace cmds { namespace cmds {
class Install : public cli::CommandWithFlagsAndAction { class Install : public cli::CommandWithFlagsAndAction {
public: public:
Install(); Install();
private: private:
std::string apk_; std::string apk_;
}; };
} // namespace cmds } // namespace cmds

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,16 +22,16 @@
#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 {
class Launch : public cli::CommandWithFlagsAndAction { class Launch : public cli::CommandWithFlagsAndAction {
public: public:
Launch(); Launch();
private: private:
android::Intent intent_; android::Intent intent_;
}; };
} // 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<
public: boost::asio::local::stream_protocol> {
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();
} }
@ -65,26 +67,30 @@ 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,11 +110,12 @@ 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
// container for things like sensors, vibrtator etc. // container for things like sensors, vibrtator etc.
#if 0 #if 0
auto qemud_connector = std::make_shared<network::PublishedSocketConnector>( auto qemud_connector = std::make_shared<network::PublishedSocketConnector>(
utils::string_format("%s/qemud", config::socket_path()), utils::string_format("%s/qemud", config::socket_path()),
@ -117,53 +125,52 @@ 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);
container::Configuration container_configuration; container::Configuration container_configuration;
container_configuration.bind_mounts = { container_configuration.bind_mounts = {
// { qemud_connector->socket_file(), "/dev/qemud" }, // { qemud_connector->socket_file(), "/dev/qemud" },
{ qemu_pipe_connector->socket_file(), "/dev/qemu_pipe" }, {qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"},
{ bridge_connector->socket_file(), "/dev/anbox_bridge" }, {bridge_connector->socket_file(), "/dev/anbox_bridge"},
{ config::host_input_device_path(), "/dev/input" }, {config::host_input_device_path(), "/dev/input"},
{ "/dev/binder", "/dev/binder" }, {"/dev/binder", "/dev/binder"},
{ "/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

@ -29,14 +29,14 @@
namespace anbox { namespace anbox {
namespace cmds { namespace cmds {
class Run : public cli::CommandWithFlagsAndAction { class Run : public cli::CommandWithFlagsAndAction {
public: public:
typedef std::function<core::dbus::Bus::Ptr()> BusFactory; typedef std::function<core::dbus::Bus::Ptr()> BusFactory;
static BusFactory session_bus_factory(); static BusFactory session_bus_factory();
Run(const BusFactory& bus_factory = session_bus_factory()); Run(const BusFactory& bus_factory = session_bus_factory());
private: private:
BusFactory bus_factory_; BusFactory bus_factory_;
std::string desktop_file_hint_; std::string desktop_file_hint_;
std::string icon_; std::string icon_;

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

@ -29,7 +29,7 @@
namespace anbox { namespace anbox {
namespace cmds { namespace cmds {
class Version : public cli::CommandWithFlagsAndAction { class Version : public cli::CommandWithFlagsAndAction {
public: public:
Version(); Version();
}; };
} // namespace cmds } // namespace cmds

View file

@ -21,23 +21,20 @@
namespace { 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;
boost::asio::io_service::strand strand; boost::asio::io_service::strand strand;
}; };
} }
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

@ -28,15 +28,16 @@
namespace anbox { namespace anbox {
namespace common { namespace common {
class Dispatcher : public DoNotCopyOrMove { class Dispatcher : public DoNotCopyOrMove {
public: public:
typedef std::function<void()> Task; typedef std::function<void()> Task;
virtual void dispatch(const Task& task) = 0; virtual void dispatch(const Task& task) = 0;
protected: 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,27 +22,27 @@
#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
//transfer ownership of the POD-int to the object. The int no longer needs close()ing, // 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);
static int const invalid{-1}; static int const invalid{-1};
Fd(); //Initializes fd to the anbox::Fd::invalid; Fd(); // Initializes fd to the anbox::Fd::invalid;
Fd(Fd&&); Fd(Fd&&);
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:
std::shared_ptr<int> fd; std::shared_ptr<int> fd;
}; };
} // namespace anbox } // namespace anbox

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
@ -46,8 +43,8 @@ public:
unsigned char* data() const { return effective_buffer.get(); } unsigned char* data() const { return effective_buffer.get(); }
size_t size() const { return size_; } size_t size() const { return size_; }
private: private:
typedef std::unique_ptr<unsigned char,void (*)(unsigned char*)> BufferUPtr; typedef std::unique_ptr<unsigned char, void (*)(unsigned char*)> BufferUPtr;
static void null_deleter(unsigned char*) {} static void null_deleter(unsigned char*) {}
static void heap_deleter(unsigned char* b) { delete[] b; } static void heap_deleter(unsigned char* b) { delete[] b; }

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++;
@ -52,39 +43,35 @@ void WaitHandle::wait_for_all() // wait for all results you expect
{ {
std::unique_lock<std::mutex> lock(guard); std::unique_lock<std::mutex> lock(guard);
wait_condition.wait(lock, [&]{ return received == expecting; }); wait_condition.wait(lock, [&] { return received == expecting; });
received = 0; received = 0;
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);
wait_condition.wait(lock, [&]{ return received != 0; }); wait_condition.wait(lock, [&] { return received != 0; });
--received; --received;
--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,9 +26,8 @@
namespace anbox { namespace anbox {
namespace common { namespace common {
struct WaitHandle struct WaitHandle {
{ public:
public:
WaitHandle(); WaitHandle();
~WaitHandle(); ~WaitHandle();
@ -41,7 +40,7 @@ public:
bool has_result(); bool has_result();
bool is_pending(); bool is_pending();
private: private:
std::mutex guard; std::mutex guard;
std::condition_variable wait_condition; std::condition_variable wait_condition;

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 {
@ -33,15 +33,16 @@ class LocalSocketMessenger;
namespace container { namespace container {
class ManagementApiStub; class ManagementApiStub;
class Client { class Client {
public: public:
Client(const std::shared_ptr<Runtime> &rt); Client(const std::shared_ptr<Runtime> &rt);
~Client(); ~Client();
void start_container(const Configuration &configuration); void start_container(const Configuration &configuration);
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,13 +18,13 @@
#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 {
struct Configuration { struct Configuration {
std::map<std::string,std::string> bind_mounts; std::map<std::string, std::string> bind_mounts;
}; };
} // namespace container } // namespace container
} // namespace anbox } // namespace anbox

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,13 +20,13 @@
#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 {
class Container { class Container {
public: public:
virtual ~Container(); virtual ~Container();
enum class State { enum class State {

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");
@ -89,13 +93,14 @@ void LxcContainer::start(const Configuration &configuration) {
set_config_item("lxc.tty", "0"); set_config_item("lxc.tty", "0");
set_config_item("lxc.utsname", "anbox"); set_config_item("lxc.utsname", "anbox");
set_config_item("lxc.group.devices.deny",""); set_config_item("lxc.group.devices.deny", "");
set_config_item("lxc.group.devices.allow",""); set_config_item("lxc.group.devices.allow", "");
// 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

@ -27,7 +27,7 @@
namespace anbox { namespace anbox {
namespace container { namespace container {
class LxcContainer : public Container { class LxcContainer : public Container {
public: public:
LxcContainer(); LxcContainer();
~LxcContainer(); ~LxcContainer();
@ -35,7 +35,7 @@ public:
void stop() override; void stop() override;
State state() override; State state() override;
private: private:
void set_config_item(const std::string &key, const std::string &value); void set_config_item(const std::string &key, const std::string &value);
State state_; State state_;

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

@ -24,16 +24,17 @@ namespace anbox {
namespace container { 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();
void dispatch(rpc::Invocation const& invocation) override; void dispatch(rpc::Invocation const &invocation) override;
void process_event_sequence(const std::string &event) override; void process_event_sequence(const std::string &event) override;
private: private:
std::shared_ptr<ManagementApiSkeleton> server_; std::shared_ptr<ManagementApiSkeleton> server_;
}; };
} // namespace anbox } // namespace anbox

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

@ -41,16 +41,17 @@ class PendingCallCache;
namespace container { 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_;
std::shared_ptr<Container> container_; std::shared_ptr<Container> container_;
}; };

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,19 +49,19 @@ 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(
(void) request; Request<protobuf::rpc::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>
@ -35,16 +35,16 @@ class Channel;
} // namespace rpc } // namespace rpc
namespace container { namespace container {
class ManagementApiStub : public DoNotCopyOrMove { class ManagementApiStub : public DoNotCopyOrMove {
public: public:
ManagementApiStub(const std::shared_ptr<rpc::Channel> &channel); ManagementApiStub(const std::shared_ptr<rpc::Channel> &channel);
~ManagementApiStub(); ~ManagementApiStub();
void start_container(const Configuration &configuration); void start_container(const Configuration &configuration);
private: private:
template<typename Response> template <typename Response>
struct Request { struct Request {
Request() : response(std::make_shared<Response>()), success(true) { } Request() : response(std::make_shared<Response>()), success(true) {}
std::shared_ptr<Response> response; std::shared_ptr<Response> response;
bool success; bool success;
}; };

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());
@ -80,7 +81,7 @@ void Service::new_client(std::shared_ptr<boost::asio::local::stream_protocol::so
auto processor = std::make_shared<container::ManagementApiMessageProcessor>( auto processor = std::make_shared<container::ManagementApiMessageProcessor>(
messenger, pending_calls, server); messenger, pending_calls, server);
auto const& connection = std::make_shared<network::SocketConnection>( auto const &connection = std::make_shared<network::SocketConnection>(
messenger, messenger, next_id(), connections_, processor); messenger, messenger, next_id(), connections_, processor);
connection->set_name("container-service"); connection->set_name("container-service");

View file

@ -18,26 +18,27 @@
#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 {
namespace container { namespace container {
class Service : public std::enable_shared_from_this<Service> { class Service : public std::enable_shared_from_this<Service> {
public: public:
static std::shared_ptr<Service> create(const std::shared_ptr<Runtime> &rt); static std::shared_ptr<Service> create(const std::shared_ptr<Runtime> &rt);
Service(const std::shared_ptr<Runtime> &rt); Service(const std::shared_ptr<Runtime> &rt);
~Service(); ~Service();
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,20 +18,20 @@
#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 {
public: public:
Daemon(); Daemon();
int Run(const std::vector<std::string> &arguments); int Run(const std::vector<std::string> &arguments);
private: private:
cli::CommandWithSubcommands cmd; cli::CommandWithSubcommands cmd;
}; };
} // namespace anbox } // namespace anbox

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

@ -28,15 +28,15 @@ namespace anbox {
namespace dbus { namespace dbus {
namespace skeleton { namespace skeleton {
class ApplicationManager : public anbox::ApplicationManager { class ApplicationManager : public anbox::ApplicationManager {
public: public:
ApplicationManager(const core::dbus::Bus::Ptr &bus, ApplicationManager(const core::dbus::Bus::Ptr &bus,
const core::dbus::Object::Ptr& object, const core::dbus::Object::Ptr &object,
const std::shared_ptr<anbox::ApplicationManager> &impl); const std::shared_ptr<anbox::ApplicationManager> &impl);
~ApplicationManager(); ~ApplicationManager();
void launch(const android::Intent &intent) override; void launch(const android::Intent &intent) override;
private: private:
core::dbus::Bus::Ptr bus_; core::dbus::Bus::Ptr bus_;
core::dbus::Service::Ptr service_; core::dbus::Service::Ptr service_;
core::dbus::Object::Ptr object_; core::dbus::Object::Ptr object_;

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>
@ -30,17 +30,18 @@ namespace dbus {
namespace skeleton { 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();
private: private:
core::dbus::Bus::Ptr bus_; core::dbus::Bus::Ptr bus_;
core::dbus::Service::Ptr service_; core::dbus::Service::Ptr service_;
core::dbus::Object::Ptr object_; core::dbus::Object::Ptr object_;

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

@ -28,17 +28,18 @@ namespace anbox {
namespace dbus { 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,
const core::dbus::Object::Ptr& object); const core::dbus::Object::Ptr &object);
~ApplicationManager(); ~ApplicationManager();
void launch(const android::Intent &intent) override; void launch(const android::Intent &intent) override;
private: private:
core::dbus::Bus::Ptr bus_; core::dbus::Bus::Ptr bus_;
core::dbus::Service::Ptr service_; core::dbus::Service::Ptr service_;
core::dbus::Object::Ptr object_; core::dbus::Object::Ptr object_;

View file

@ -25,17 +25,14 @@
namespace anbox { 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:
std::function<void()> action_; std::function<void()> action_;
}; };

View file

@ -20,19 +20,17 @@
namespace anbox { namespace anbox {
class DoNotCopyOrMove class DoNotCopyOrMove {
{ public:
public:
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete; DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete; DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
virtual ~DoNotCopyOrMove() = default; virtual ~DoNotCopyOrMove() = default;
DoNotCopyOrMove& operator=(const DoNotCopyOrMove&) = delete; DoNotCopyOrMove& operator=(const DoNotCopyOrMove&) = delete;
DoNotCopyOrMove& operator=(DoNotCopyOrMove&&) = delete; DoNotCopyOrMove& operator=(DoNotCopyOrMove&&) = delete;
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:
@ -93,7 +90,7 @@ void unbindFbo() {
// } // automatically calls m_helper->teardownContext(); // } // automatically calls m_helper->teardownContext();
// //
class ScopedHelperContext { class ScopedHelperContext {
public: public:
ScopedHelperContext(ColorBuffer::Helper* helper) : mHelper(helper) { ScopedHelperContext(ColorBuffer::Helper* helper) : mHelper(helper) {
if (!helper->setupContext()) { if (!helper->setupContext()) {
mHelper = NULL; mHelper = NULL;
@ -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,19 +107,17 @@ public:
mHelper = NULL; mHelper = NULL;
} }
} }
private:
private:
ColorBuffer::Helper* mHelper; ColorBuffer::Helper* mHelper;
}; };
} // 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) {
@ -149,7 +142,7 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
return NULL; return NULL;
} }
ColorBuffer *cb = new ColorBuffer(p_display, helper); ColorBuffer* cb = new ColorBuffer(p_display, helper);
s_gles2.glGenTextures(1, &cb->m_tex); s_gles2.glGenTextures(1, &cb->m_tex);
s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex); s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex);
@ -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,13 +243,12 @@ 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
return false; return false;
@ -299,21 +261,20 @@ bool ColorBuffer::blitFromCurrentReadBuffer()
GLint currTexBind; GLint currTexBind;
if (tInfo->currContext->isGL2()) { if (tInfo->currContext->isGL2()) {
s_gles2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind); s_gles2.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
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);
@ -346,14 +309,13 @@ bool ColorBuffer::bindToTexture() {
if (!m_eglImage) { if (!m_eglImage) {
return false; return false;
} }
RenderThreadInfo *tInfo = RenderThreadInfo::get(); RenderThreadInfo* tInfo = RenderThreadInfo::get();
if (!tInfo->currContext.Ptr()) { if (!tInfo->currContext.Ptr()) {
return false; return false;
} }
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;
@ -363,15 +325,16 @@ bool ColorBuffer::bindToRenderbuffer() {
if (!m_eglImage) { if (!m_eglImage) {
return false; return false;
} }
RenderThreadInfo *tInfo = RenderThreadInfo::get(); RenderThreadInfo* tInfo = RenderThreadInfo::get();
if (!tInfo->currContext.Ptr()) { if (!tInfo->currContext.Ptr()) {
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

@ -55,7 +55,7 @@ class TextureResize;
// As an additional twist. // As an additional twist.
class ColorBuffer { class ColorBuffer {
public: public:
// Helper interface class used during ColorBuffer operations. This is // Helper interface class used during ColorBuffer operations. This is
// introduced to remove coupling from the FrameBuffer class implementation. // introduced to remove coupling from the FrameBuffer class implementation.
class Helper { class Helper {
@ -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,12 +115,13 @@ 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.
explicit ColorBuffer(EGLDisplay display, Helper* helper); explicit ColorBuffer(EGLDisplay display, Helper* helper);
private: private:
GLuint m_tex; GLuint m_tex;
GLuint m_blitTex; GLuint m_blitTex;
EGLImageKHR m_eglImage; EGLImageKHR m_eglImage;
@ -144,7 +132,7 @@ private:
GLenum m_internalFormat; GLenum m_internalFormat;
EGLDisplay m_display; EGLDisplay m_display;
Helper* m_helper; Helper* m_helper;
TextureResize * m_resizer; TextureResize* m_resizer;
}; };
typedef emugl::SmartPtr<ColorBuffer> ColorBufferPtr; typedef emugl::SmartPtr<ColorBuffer> ColorBufferPtr;

View file

@ -21,19 +21,15 @@ namespace {
std::shared_ptr<DisplayManager> display_mgr; 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

@ -21,7 +21,7 @@
#include <memory> #include <memory>
class DisplayManager { class DisplayManager {
public: public:
virtual ~DisplayManager(); virtual ~DisplayManager();
struct DisplayInfo { struct DisplayInfo {

View file

@ -14,36 +14,30 @@
* 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);
} }
// get fresh data into the buffer; // get fresh data into the buffer;
size_t len = m_size - m_validData; size_t len = m_size - m_validData;
if (len==0) { if (len == 0) {
//we need to inc our buffer // we need to inc our buffer
size_t new_size = m_size*2; size_t new_size = m_size * 2;
unsigned char* new_buf; unsigned char* new_buf;
if (new_size < m_size) { // overflow check if (new_size < m_size) { // overflow check
new_size = INT_MAX; new_size = INT_MAX;
@ -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

@ -19,14 +19,16 @@
#include "IOStream.h" #include "IOStream.h"
class ReadBuffer { class ReadBuffer {
public: public:
ReadBuffer(size_t bufSize); ReadBuffer(size_t bufSize);
~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;
unsigned char *m_readPtr; unsigned char *m_readPtr;
size_t m_size; size_t m_size;

View file

@ -41,11 +41,10 @@ static char s_renderAddr[256];
static RenderWindow* s_renderWindow = NULL; 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,14 +149,13 @@ 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
// realize the exit request. // realize the exit request.
// (send the exit request in clientFlags) // (send the exit request in clientFlags)
IOStream *dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER); IOStream* dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER);
if (!dummy) return false; if (!dummy) return false;
if (s_renderThread) { if (s_renderThread) {
@ -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) {
@ -241,8 +231,8 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
// //
// send clientFlags to the renderer // send clientFlags to the renderer
// //
unsigned int *pClientFlags = unsigned int* pClientFlags =
(unsigned int *)stream->allocBuffer(sizeof(unsigned int)); (unsigned int*)stream->allocBuffer(sizeof(unsigned int));
*pClientFlags = clientFlags; *pClientFlags = clientFlags;
stream->commitBuffer(sizeof(unsigned int)); stream->commitBuffer(sizeof(unsigned int));

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>
@ -25,17 +25,15 @@
// EGLContext, associated with an GLDecoderContextData instance that is // EGLContext, associated with an GLDecoderContextData instance that is
// used to store copies of guest-side arrays. // used to store copies of guest-side arrays.
class RenderContext { class RenderContext {
public: public:
// Create a new RenderContext instance. // Create a new RenderContext instance.
// |display| is the host EGLDisplay handle. // |display| is the host EGLDisplay handle.
// |config| is the host EGLConfig to use. // |config| is the host EGLConfig to use.
// |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();
@ -50,14 +48,12 @@ public:
// RenderContext instance. // RenderContext instance.
GLDecoderContextData& decoderContextData() { return mContextData; } GLDecoderContextData& decoderContextData() { return mContextData; }
private: private:
RenderContext(); RenderContext();
RenderContext(EGLDisplay display, RenderContext(EGLDisplay display, EGLContext context, bool isGl2);
EGLContext context,
bool isGl2);
private: private:
EGLDisplay mDisplay; EGLDisplay mDisplay;
EGLContext mContext; EGLContext mContext;
bool mIsGl2; bool mIsGl2;

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,20 +71,18 @@ 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;
if (tInfo && tInfo->currContext) { if (tInfo && tInfo->currContext) {
const char *str = nullptr; const char *str = nullptr;
if (tInfo->currContext->isGL2()) if (tInfo->currContext->isGL2())
str = reinterpret_cast<const char*>(s_gles2.glGetString(name)); str = reinterpret_cast<const char *>(s_gles2.glGetString(name));
else else
str = reinterpret_cast<const char*>(s_gles1.glGetString(name)); str = reinterpret_cast<const char *>(s_gles1.glGetString(name));
if (str) 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;
@ -167,7 +152,7 @@ static EGLint rcGetFBParam(EGLint param)
EGLint ret = 0; EGLint ret = 0;
switch(param) { switch (param) {
case FB_WIDTH: case FB_WIDTH:
ret = DisplayManager::get()->display_info().horizontal_resolution; ret = DisplayManager::get()->display_info().horizontal_resolution;
break; break;
@ -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,19 +214,17 @@ 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;
} }
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,33 +233,29 @@ 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;
} }
return fb->openColorBuffer( colorbuffer ); return fb->openColorBuffer(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;
} }
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,20 +66,19 @@ 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) {
SocketStream *stream = m_listenSock->accept(); SocketStream *stream = m_listenSock->accept();
if (!stream) { if (!stream) {
fprintf(stderr,"Error accepting gles connection, ignoring.\n"); fprintf(stderr, "Error accepting gles connection, ignoring.\n");
continue; continue;
} }
unsigned int clientFlags; unsigned int clientFlags;
if (!stream->readFully(&clientFlags, sizeof(unsigned int))) { if (!stream->readFully(&clientFlags, sizeof(unsigned int))) {
fprintf(stderr,"Error reading clientFlags\n"); fprintf(stderr, "Error reading clientFlags\n");
delete stream; delete stream;
continue; continue;
} }
@ -103,10 +92,10 @@ intptr_t RenderServer::main()
RenderThread *rt = RenderThread::create(stream, &m_lock); RenderThread *rt = RenderThread::create(stream, &m_lock);
if (!rt) { if (!rt) {
fprintf(stderr,"Failed to create RenderThread\n"); fprintf(stderr, "Failed to create RenderThread\n");
delete stream; delete stream;
} else if (!rt->start()) { } else if (!rt->start()) {
fprintf(stderr,"Failed to start RenderThread\n"); fprintf(stderr, "Failed to start RenderThread\n");
delete rt; delete rt;
delete stream; delete stream;
} }
@ -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,20 +20,19 @@
#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();
virtual intptr_t main(); virtual intptr_t main();
bool isExiting() const { return m_exiting; } bool isExiting() const { return m_exiting; }
private: private:
RenderServer(); RenderServer();
private: private:
emugl::Mutex m_lock; emugl::Mutex m_lock;
SocketStream *m_listenSock; SocketStream *m_listenSock;
bool m_exiting; bool m_exiting;

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);
@ -101,8 +96,7 @@ 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

@ -24,7 +24,7 @@
// A class used to model a thread of the RenderServer. Each one of them // A class used to model a thread of the RenderServer. Each one of them
// handles a single guest client / protocol byte stream. // handles a single guest client / protocol byte stream.
class RenderThread : public emugl::Thread { class RenderThread : public emugl::Thread {
public: public:
// Create a new RenderThread instance. // Create a new RenderThread instance.
// |stream| is an input stream that will be read from the thread, // |stream| is an input stream that will be read from the thread,
// and deleted by it when it exits. // and deleted by it when it exits.
@ -44,7 +44,7 @@ public:
// Force a thread to stop. // Force a thread to stop.
void forceStop(); void forceStop();
private: private:
RenderThread(); // No default constructor RenderThread(); // No default constructor
RenderThread(IOStream* stream, emugl::Mutex* mutex); RenderThread(IOStream* stream, emugl::Mutex* mutex);

View file

@ -22,7 +22,7 @@
namespace { namespace {
class ThreadInfoStore : public ::emugl::ThreadStore { class ThreadInfoStore : public ::emugl::ThreadStore {
public: public:
ThreadInfoStore() : ::emugl::ThreadStore(NULL) {} ThreadInfoStore() : ::emugl::ThreadStore(NULL) {}
}; };
@ -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,23 +14,23 @@
#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
#if DEBUG #if DEBUG
# define D(...) my_debug(__PRETTY_FUNCTION__, __LINE__, __VA_ARGS__) #define D(...) my_debug(__PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
#else #else
# define D(...) ((void)0) #define D(...) ((void)0)
#endif #endif
namespace { namespace {
@ -129,8 +129,7 @@ struct RenderWindowMessage {
result = true; result = true;
break; break;
default: default:;
;
} }
return result; return result;
} }
@ -159,7 +158,7 @@ struct RenderWindowMessage {
// canWriteCmd.signal() // canWriteCmd.signal()
// //
class RenderWindowChannel { class RenderWindowChannel {
public: public:
RenderWindowChannel() : mIn(), mOut() {} RenderWindowChannel() : mIn(), mOut() {}
~RenderWindowChannel() {} ~RenderWindowChannel() {}
@ -193,7 +192,7 @@ public:
D("result sent\n"); D("result sent\n");
} }
private: private:
emugl::MessageChannel<RenderWindowMessage, 16U> mIn; emugl::MessageChannel<RenderWindowMessage, 16U> mIn;
emugl::MessageChannel<bool, 16U> mOut; emugl::MessageChannel<bool, 16U> mOut;
}; };
@ -207,7 +206,7 @@ namespace {
// The thread ends with a CMD_FINALIZE. // The thread ends with a CMD_FINALIZE.
// //
class RenderWindowThread : public emugl::Thread { class RenderWindowThread : public emugl::Thread {
public: public:
RenderWindowThread(RenderWindowChannel* channel) : mChannel(channel) {} RenderWindowThread(RenderWindowChannel* channel) : mChannel(channel) {}
virtual intptr_t main() { virtual intptr_t main() {
@ -234,18 +233,14 @@ public:
return 0; return 0;
} }
private: private:
RenderWindowChannel* mChannel; RenderWindowChannel* mChannel;
}; };
} // 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);
@ -264,7 +259,7 @@ RenderWindow::~RenderWindow() {
D("Sending CMD_FINALIZE\n"); D("Sending CMD_FINALIZE\n");
RenderWindowMessage msg; RenderWindowMessage msg;
msg.cmd = CMD_FINALIZE; msg.cmd = CMD_FINALIZE;
(void) processMessage(msg); (void)processMessage(msg);
if (mThread) { if (mThread) {
mThread->wait(NULL); mThread->wait(NULL);
@ -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");
@ -337,7 +326,7 @@ void RenderWindow::setRotation(float zRot) {
RenderWindowMessage msg; RenderWindowMessage msg;
msg.cmd = CMD_SET_ROTATION; msg.cmd = CMD_SET_ROTATION;
msg.rotation = zRot; msg.rotation = zRot;
(void) processMessage(msg); (void)processMessage(msg);
D("Exiting\n"); D("Exiting\n");
} }
@ -347,7 +336,7 @@ void RenderWindow::setTranslation(float px, float py) {
msg.cmd = CMD_SET_TRANSLATION; msg.cmd = CMD_SET_TRANSLATION;
msg.trans.px = px; msg.trans.px = px;
msg.trans.py = py; msg.trans.py = py;
(void) processMessage(msg); (void)processMessage(msg);
D("Exiting\n"); D("Exiting\n");
} }
@ -355,7 +344,7 @@ void RenderWindow::repaint() {
D("Entering\n"); D("Entering\n");
RenderWindowMessage msg; RenderWindowMessage msg;
msg.cmd = CMD_REPAINT; msg.cmd = CMD_REPAINT;
(void) processMessage(msg); (void)processMessage(msg);
D("Exiting\n"); D("Exiting\n");
} }

View file

@ -47,7 +47,7 @@ struct RenderWindowMessage;
// 6) Call repaint() to force a repaint(). // 6) Call repaint() to force a repaint().
// //
class RenderWindow { class RenderWindow {
public: public:
// Create new instance. |width| and |height| are the dimensions of the // Create new instance. |width| and |height| are the dimensions of the
// emulated accelerated framebuffer. |use_thread| can be true to force // emulated accelerated framebuffer. |use_thread| can be true to force
// the use of a separate thread, which might be required on some platforms // the use of a separate thread, which might be required on some platforms
@ -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,
@ -118,7 +110,7 @@ public:
// Force a repaint of the whole content into the sub-window. // Force a repaint of the whole content into the sub-window.
void repaint(); void repaint();
private: private:
bool processMessage(const RenderWindowMessage& msg); bool processMessage(const RenderWindowMessage& msg);
bool mValid; bool mValid;

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, const std::uint32_t &buffer,
Renderable(const std::string &name,
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;
@ -46,7 +43,7 @@ public:
void set_screen_position(const anbox::graphics::Rect &screen_position); void set_screen_position(const anbox::graphics::Rect &screen_position);
private: private:
std::string name_; std::string name_;
std::uint32_t buffer_; std::uint32_t buffer_;
anbox::graphics::Rect screen_position_; anbox::graphics::Rect screen_position_;

View file

@ -30,17 +30,17 @@
#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 {
// Helper class to call the bind_locked() / unbind_locked() properly. // Helper class to call the bind_locked() / unbind_locked() properly.
class ScopedBind { class ScopedBind {
public: public:
// Constructor will call bind_locked() on |fb|. // Constructor will call bind_locked() on |fb|.
// Use isValid() to check for errors. // Use isValid() to check for errors.
ScopedBind(Renderer* fb) : mFb(fb) { ScopedBind(Renderer *fb) : mFb(fb) {
if (!mFb->bind_locked()) { if (!mFb->bind_locked()) {
mFb = NULL; mFb = NULL;
} }
@ -59,33 +59,26 @@ public:
} }
// Destructor will call release(). // Destructor will call release().
~ScopedBind() { ~ScopedBind() { release(); }
release();
}
private: private:
Renderer* mFb; Renderer *mFb;
}; };
// Implementation of a ColorBuffer::Helper instance that redirects calls // Implementation of a ColorBuffer::Helper instance that redirects calls
// to a FrameBuffer instance. // to a FrameBuffer instance.
class ColorBufferHelper : public ColorBuffer::Helper { 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 { virtual TextureDraw *getTextureDraw() const { return mFb->getTextureDraw(); }
return mFb->getTextureDraw();
} private:
private: Renderer *mFb;
Renderer* mFb;
}; };
} // namespace } // namespace
@ -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__);
@ -147,8 +129,8 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy)
} }
// the string pointer may become invalid when the context is destroyed // the string pointer may become invalid when the context is destroyed
const char* s = (const char*)s_gles1.glGetString(GL_EXTENSIONS); const char *s = (const char *)s_gles1.glGetString(GL_EXTENSIONS);
char* extString = strdup(s ? s : ""); char *extString = strdup(s ? s : "");
s_egl.eglMakeCurrent(p_dpy, NULL, NULL, NULL); s_egl.eglMakeCurrent(p_dpy, NULL, NULL, NULL);
s_egl.eglDestroyContext(p_dpy, ctx); s_egl.eglDestroyContext(p_dpy, ctx);
@ -157,7 +139,7 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy)
return extString; return extString;
} }
void Renderer::finalize(){ void Renderer::finalize() {
m_colorbuffers.clear(); m_colorbuffers.clear();
m_windows.clear(); m_windows.clear();
m_contexts.clear(); m_contexts.clear();
@ -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");
@ -211,7 +191,7 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// if GLES2 plugin has loaded - try to make GLES2 context and // if GLES2 plugin has loaded - try to make GLES2 context and
// get GLES2 extension string // get GLES2 extension string
// //
char* gles1Extensions = NULL; char *gles1Extensions = NULL;
gles1Extensions = getGLES1ExtensionString(fb->m_eglDisplay); gles1Extensions = getGLES1ExtensionString(fb->m_eglDisplay);
if (!gles1Extensions) { if (!gles1Extensions) {
// Could not create GLES2 context - drop GL2 capability // Could not create GLES2 context - drop GL2 capability
@ -223,35 +203,34 @@ 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,30 +287,30 @@ 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);
// printf("GLES2 [%s]\n", gles2Extensions); // printf("GLES2 [%s]\n", gles2Extensions);
has_gl_oes_image = true; has_gl_oes_image = true;
if (has_gl_oes_image) { if (has_gl_oes_image) {
has_gl_oes_image &= strstr(gles1Extensions, "GL_OES_EGL_image") != NULL; has_gl_oes_image &= strstr(gles1Extensions, "GL_OES_EGL_image") != NULL;
} }
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;
} }
@ -409,9 +381,9 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
// Cache the GL strings so we don't have to think about threading or // Cache the GL strings so we don't have to think about threading or
// current-context when asked for them. // current-context when asked for them.
// //
fb->m_glVendor = (const char*)s_gles2.glGetString(GL_VENDOR); fb->m_glVendor = (const char *)s_gles2.glGetString(GL_VENDOR);
fb->m_glRenderer = (const char*)s_gles2.glGetString(GL_RENDERER); fb->m_glRenderer = (const char *)s_gles2.glGetString(GL_RENDERER);
fb->m_glVersion = (const char*)s_gles2.glGetString(GL_VERSION); fb->m_glVersion = (const char *)s_gles2.glGetString(GL_VERSION);
fb->m_textureDraw = new TextureDraw(fb->m_eglDisplay); fb->m_textureDraw = new TextureDraw(fb->m_eglDisplay);
if (!fb->m_textureDraw) { if (!fb->m_textureDraw) {
@ -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,12 +532,11 @@ 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;
const RendererConfig* config = getConfigs()->get(p_config); const RendererConfig *config = getConfigs()->get(p_config);
if (!config) { if (!config) {
return ret; return ret;
} }
@ -603,13 +563,13 @@ 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;
const RendererConfig* config = getConfigs()->get(p_config); const RendererConfig *config = getConfigs()->get(p_config);
if (!config) { if (!config) {
return ret; return ret;
} }
@ -618,7 +578,7 @@ HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height
getDisplay(), config->getEglConfig(), p_width, p_height)); getDisplay(), config->getEglConfig(), p_width, p_height));
if (win.Ptr() != NULL) { if (win.Ptr() != NULL) {
ret = genHandle(); ret = genHandle();
m_windows[ret] = std::pair<WindowSurfacePtr, HandleType>(win,0); m_windows[ret] = std::pair<WindowSurfacePtr, HandleType>(win, 0);
RenderThreadInfo *tinfo = RenderThreadInfo::get(); RenderThreadInfo *tinfo = RenderThreadInfo::get();
tinfo->m_windowSet.insert(ret); tinfo->m_windowSet.insert(ret);
} }
@ -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,36 +666,35 @@ 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;
} }
WindowSurface* surface = (*w).second.first.Ptr(); WindowSurface *surface = (*w).second.first.Ptr();
surface->flushColorBuffer(); surface->flushColorBuffer();
return true; return true;
} }
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));
if (w == m_windows.end()) { if (w == m_windows.end()) {
// bad surface handle // bad surface handle
ERR("%s: bad window surface handle %#x\n", __FUNCTION__, p_surface); ERR("%s: bad window surface handle %#x\n", __FUNCTION__, p_surface);
return false; return false;
} }
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()) {
DBG("%s: bad color buffer handle %#x\n", __FUNCTION__, p_colorbuffer); DBG("%s: bad color buffer handle %#x\n", __FUNCTION__, p_colorbuffer);
// bad colorbuffer handle // bad colorbuffer handle
@ -751,13 +706,12 @@ 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));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
// bad colorbuffer handle // bad colorbuffer handle
return; return;
@ -766,13 +720,12 @@ 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));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
// bad colorbuffer handle // bad colorbuffer handle
return false; return false;
@ -783,11 +736,10 @@ 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));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
// bad colorbuffer handle // bad colorbuffer handle
return false; return false;
@ -796,11 +748,10 @@ 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));
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end()) {
// bad colorbuffer handle // bad colorbuffer handle
return false; return false;
@ -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);
@ -822,14 +771,14 @@ bool Renderer::bindContext(HandleType p_context,
// if this is not an unbind operation - make sure all handles are good // if this is not an unbind operation - make sure all handles are good
// //
if (p_context || p_drawSurface || p_readSurface) { if (p_context || p_drawSurface || p_readSurface) {
RenderContextMap::iterator r( m_contexts.find(p_context) ); RenderContextMap::iterator r(m_contexts.find(p_context));
if (r == m_contexts.end()) { if (r == m_contexts.end()) {
// bad context handle // bad context handle
return false; return false;
} }
ctx = (*r).second; ctx = (*r).second;
WindowSurfaceMap::iterator w( m_windows.find(p_drawSurface) ); WindowSurfaceMap::iterator w(m_windows.find(p_drawSurface));
if (w == m_windows.end()) { if (w == m_windows.end()) {
// bad surface handle // bad surface handle
return false; return false;
@ -837,14 +786,13 @@ bool Renderer::bindContext(HandleType p_context,
draw = (*w).second.first; draw = (*w).second.first;
if (p_readSurface != p_drawSurface) { if (p_readSurface != p_drawSurface) {
WindowSurfaceMap::iterator w( m_windows.find(p_readSurface) ); WindowSurfaceMap::iterator w(m_windows.find(p_readSurface));
if (w == m_windows.end()) { if (w == m_windows.end()) {
// bad surface handle // bad surface handle
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,22 +835,23 @@ 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) {
RenderContextMap::iterator r( m_contexts.find(context) ); RenderContextMap::iterator r(m_contexts.find(context));
if (r == m_contexts.end()) { if (r == m_contexts.end()) {
// bad context handle // bad context handle
return false; return false;
@ -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,21 +945,19 @@ 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.
"precision mediump float;\n" "precision mediump float;\n"
"uniform sampler2D tex;\n" "uniform sampler2D tex;\n"
"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,12 +1006,10 @@ 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}};
vertices[1] = {{left, bottom, 0.0f}, {0.0f, tex_bottom}}; vertices[1] = {{left, bottom, 0.0f}, {0.0f, tex_bottom}};
vertices[2] = {{right, top, 0.0f}, {tex_right, 0.0f}}; vertices[2] = {{right, top, 0.0f}, {tex_right, 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;
@ -1102,11 +1035,9 @@ 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
@ -73,7 +74,7 @@ struct RendererWindow;
// and which must be previously setup by calling initialize(). // and which must be previously setup by calling initialize().
// //
class Renderer { class Renderer {
public: public:
// Initialize the global instance. // Initialize the global instance.
// |width| and |height| are the dimensions of the emulator GPU display // |width| and |height| are the dimensions of the emulator GPU display
// in pixels. |useSubWindow| is true to indicate that the caller // in pixels. |useSubWindow| is true to indicate that the caller
@ -88,10 +89,10 @@ public:
// Return a pointer to the global instance. initialize() must be called // Return a pointer to the global instance. initialize() must be called
// previously, or this will return NULL. // previously, or this will return NULL.
static Renderer *get() { return s_renderer; } static Renderer* get() { return s_renderer; }
// Return the capabilities of the underlying display. // Return the capabilities of the underlying display.
const RendererCaps &getCaps() const { return m_caps; } const RendererCaps& getCaps() const { return m_caps; }
// Return the list of configs available from this display. // Return the list of configs available from this display.
const RendererConfigList* getConfigs() const { return m_configs; } const RendererConfigList* getConfigs() const { return m_configs; }
@ -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;
@ -113,7 +113,7 @@ public:
} }
RendererWindow* createNativeWindow(EGLNativeWindowType native_window); RendererWindow* createNativeWindow(EGLNativeWindowType native_window);
void destroyNativeWindow(RendererWindow *window); void destroyNativeWindow(RendererWindow* window);
void destroyNativeWindow(EGLNativeWindowType native_window); void destroyNativeWindow(EGLNativeWindowType native_window);
// Create a new RenderContext instance for this display instance. // Create a new RenderContext instance for this display instance.
@ -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,29 +240,31 @@ 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.
bool bind_locked(); bool bind_locked();
bool unbind_locked(); bool unbind_locked();
private: private:
Renderer(); Renderer();
~Renderer(); ~Renderer();
HandleType genHandle(); HandleType genHandle();
bool bindWindow_locked(RendererWindow *window); bool bindWindow_locked(RendererWindow* window);
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);
private: private:
static Renderer *s_renderer; static Renderer* s_renderer;
static HandleType s_nextHandle; static HandleType s_nextHandle;
emugl::Mutex m_lock; emugl::Mutex m_lock;
RendererConfigList* m_configs; RendererConfigList* m_configs;
@ -294,11 +295,10 @@ private:
const char* m_glRenderer; const char* m_glRenderer;
const char* m_glVersion; const char* m_glVersion;
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

@ -26,38 +26,20 @@ namespace {
const GLuint kConfigAttributes[] = { const GLuint kConfigAttributes[] = {
EGL_DEPTH_SIZE, // must be first - see getDepthSize() EGL_DEPTH_SIZE, // must be first - see getDepthSize()
EGL_STENCIL_SIZE, // must be second - see getStencilSize() EGL_STENCIL_SIZE, // must be second - see getStencilSize()
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;
} }
@ -140,18 +113,17 @@ RendererConfigList::RendererConfigList(EGLDisplay display) :
mCount++; mCount++;
} }
delete [] hostConfigs; delete[] hostConfigs;
} }
RendererConfigList::~RendererConfigList() { RendererConfigList::~RendererConfigList() {
for (int n = 0; n < mCount; ++n) { for (int n = 0; n < mCount; ++n) {
delete mConfigs[n]; delete mConfigs[n];
} }
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,15 +173,12 @@ 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;
} }
delete [] newAttribs; delete[] newAttribs;
int result = 0; int result = 0;
for (int n = 0; n < numHostConfigs; ++n) { for (int n = 0; n < numHostConfigs; ++n) {
@ -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) {
@ -233,18 +202,17 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
if (configs && result < configsSize) { if (configs && result < configsSize) {
configs[result] = (uint32_t)k; configs[result] = (uint32_t)k;
} }
result ++; result++;
break; break;
} }
} }
} }
delete [] matchedConfigs; delete[] matchedConfigs;
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

@ -33,7 +33,7 @@
// an FbConfigList from the host EGLDisplay, and use its size() and get() // an FbConfigList from the host EGLDisplay, and use its size() and get()
// methods to access it. // methods to access it.
class RendererConfig { class RendererConfig {
public: public:
// Destructor // Destructor
~RendererConfig(); ~RendererConfig();
@ -56,7 +56,7 @@ public:
// underlying host EGLConfig handle. // underlying host EGLConfig handle.
GLint getConfigId() const { return (GLint)getAttribValue(4); } GLint getConfigId() const { return (GLint)getAttribValue(4); }
private: private:
RendererConfig(); RendererConfig();
RendererConfig(RendererConfig& other); RendererConfig(RendererConfig& other);
@ -92,7 +92,7 @@ private:
// 5) Use getPackInfo() and packConfigs() to retrieve information about // 5) Use getPackInfo() and packConfigs() to retrieve information about
// available configs to the guest. // available configs to the guest.
class RendererConfigList { class RendererConfigList {
public: public:
// Create a new list of FbConfig instance, by querying all compatible // Create a new list of FbConfig instance, by querying all compatible
// host configs from |display|. A compatible config is one that supports // host configs from |display|. A compatible config is one that supports
// Pbuffers and RGB pixel values. // Pbuffers and RGB pixel values.
@ -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
@ -151,7 +150,7 @@ public:
// On success, this returns // On success, this returns
EGLint packConfigs(GLuint bufferByteSize, GLuint* buffer) const; EGLint packConfigs(GLuint bufferByteSize, GLuint* buffer) const;
private: private:
RendererConfigList(); RendererConfigList();
RendererConfigList(const RendererConfigList& other); RendererConfigList(const RendererConfigList& other);

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
@ -134,7 +113,7 @@ const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
int n; int n;
do { do {
n = this->recv(buf, *inout_len); n = this->recv(buf, *inout_len);
} while( n < 0 && errno == EINTR ); } while (n < 0 && errno == EINTR);
if (n > 0) { if (n > 0) {
*inout_len = n; *inout_len = n;
@ -144,11 +123,10 @@ 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) {
res = ::recv(m_sock, (char *)buf, len, 0); res = ::recv(m_sock, (char *)buf, len, 0);
if (res < 0) { if (res < 0) {
if (errno == EINTR) { if (errno == EINTR) {

View file

@ -20,7 +20,7 @@
#include "IOStream.h" #include "IOStream.h"
class SocketStream : public IOStream { class SocketStream : public IOStream {
public: public:
typedef enum { ERR_INVALID_SOCKET = -1000 } SocketStreamError; typedef enum { ERR_INVALID_SOCKET = -1000 } SocketStreamError;
static const size_t MAX_ADDRSTR_LEN = 256; static const size_t MAX_ADDRSTR_LEN = 256;
@ -29,7 +29,7 @@ public:
virtual int listen(char addrstr[MAX_ADDRSTR_LEN]) = 0; virtual int listen(char addrstr[MAX_ADDRSTR_LEN]) = 0;
virtual SocketStream *accept() = 0; virtual SocketStream *accept() = 0;
virtual int connect(const char* addr) = 0; virtual int connect(const char *addr) = 0;
virtual void *allocBuffer(size_t minSize); virtual void *allocBuffer(size_t minSize);
virtual int commitBuffer(size_t size); virtual int commitBuffer(size_t size);
@ -42,7 +42,7 @@ public:
virtual void forceStop(); virtual void forceStop();
protected: protected:
int m_sock; int m_sock;
size_t m_bufsize; size_t m_bufsize;
unsigned char *m_buf; unsigned char *m_buf;

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) {
@ -48,15 +46,14 @@ int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
} }
snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", port); snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", port);
addrstr[MAX_ADDRSTR_LEN-1] = '\0'; addrstr[MAX_ADDRSTR_LEN - 1] = '\0';
return 0; return 0;
} }
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

@ -19,13 +19,14 @@
#include "SocketStream.h" #include "SocketStream.h"
class TcpStream : public SocketStream { class TcpStream : public SocketStream {
public: public:
explicit TcpStream(size_t bufsize = 10000); explicit TcpStream(size_t bufsize = 10000);
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);
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

@ -85,19 +85,19 @@ struct Vertex {
}; };
const Vertex kVertices[] = { const Vertex kVertices[] = {
{{ +1, -1, +0 }, { +1, +1 }}, {{+1, -1, +0}, {+1, +1}},
{{ +1, +1, +0 }, { +1, +0 }}, {{+1, +1, +0}, {+1, +0}},
{{ -1, +1, +0 }, { +0, +0 }}, {{-1, +1, +0}, {+0, +0}},
{{ -1, -1, +0 }, { +0, +1 }}, {{-1, -1, +0}, {+0, +1}},
}; };
const GLubyte kIndices[] = { 0, 1, 2, 2, 3, 0 }; const GLubyte kIndices[] = {0, 1, 2, 2, 3, 0};
const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]); 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

@ -30,7 +30,7 @@
// framebuffer with texture content. // framebuffer with texture content.
// //
class TextureDraw { class TextureDraw {
public: public:
// Create a new instance. // Create a new instance.
TextureDraw(EGLDisplay display); TextureDraw(EGLDisplay display);
@ -41,7 +41,7 @@ public:
// be the name of a GLES 2.x texture object. // be the name of a GLES 2.x texture object.
bool draw(GLuint texture); bool draw(GLuint texture);
private: private:
EGLDisplay mDisplay; EGLDisplay mDisplay;
GLuint mVertexShader; GLuint mVertexShader;
GLuint mFragmentShader; GLuint mFragmentShader;

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

@ -19,7 +19,7 @@
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
class TextureResize { class TextureResize {
public: public:
TextureResize(GLuint width, GLuint height); TextureResize(GLuint width, GLuint height);
~TextureResize(); ~TextureResize();
@ -35,11 +35,11 @@ public:
GLuint uTexture; GLuint uTexture;
}; };
private: private:
void setupFramebuffers(unsigned int factor); void setupFramebuffers(unsigned int factor);
void resize(GLuint texture); void resize(GLuint texture);
private: private:
GLuint mWidth; GLuint mWidth;
GLuint mHeight; GLuint mHeight;
unsigned int mFactor; unsigned int mFactor;

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,26 +36,19 @@
#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 {
ret = unlink(bound_socket_path); ret = unlink(bound_socket_path);
} while (ret < 0 && errno == EINTR); } while (ret < 0 && errno == EINTR);
if(ret != 0) { if (ret != 0) {
ERR("Failed to unlink UNIX socket at \"%s\"\n", bound_socket_path); ERR("Failed to unlink UNIX socket at \"%s\"\n", bound_socket_path);
perror("UNIX socket could not be unlinked"); perror("UNIX socket could not be unlinked");
} }
@ -66,14 +59,12 @@ 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;
// First, create user-specific temp directory if needed // First, create user-specific temp directory if needed
const char* user = getenv("XDG_RUNTIME_DIR"); const char *user = getenv("XDG_RUNTIME_DIR");
if (user != NULL) { if (user != NULL) {
struct stat st; struct stat st;
snprintf(tmp, sizeof(tmp), "%s/anbox", user); snprintf(tmp, sizeof(tmp), "%s/anbox", user);
@ -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,20 +109,17 @@ 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) {
ERR("WARNING: UNIX socket at \"%s\" should be manually removed \n", ERR("WARNING: UNIX socket at \"%s\" should be manually removed \n",
addrstr); addrstr);
return -1; return -1;
@ -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

@ -19,13 +19,14 @@
#include "SocketStream.h" #include "SocketStream.h"
class UnixStream : public SocketStream { class UnixStream : public SocketStream {
public: public:
explicit UnixStream(size_t bufsize = 10000); explicit UnixStream(size_t bufsize = 10000);
~UnixStream(); ~UnixStream();
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);
} }
// //
@ -161,12 +152,10 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
// Create pbuffer surface. // Create pbuffer surface.
// //
const EGLint pbufAttribs[5] = { const EGLint pbufAttribs[5] = {
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

@ -27,15 +27,13 @@
// A class used to model a guest-side window surface. The implementation // A class used to model a guest-side window surface. The implementation
// uses a host Pbuffer to act as the EGL rendering surface instead. // uses a host Pbuffer to act as the EGL rendering surface instead.
class WindowSurface { class WindowSurface {
public: public:
// Create a new WindowSurface instance. // Create a new WindowSurface instance.
// |display| is the host EGLDisplay value. // |display| is the host EGLDisplay value.
// |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
@ -79,7 +73,7 @@ public:
// for BIND_READDRAW, it assigns it to both. // for BIND_READDRAW, it assigns it to both.
void bind(RenderContextPtr p_ctx, BindType p_bindType); void bind(RenderContextPtr p_ctx, BindType p_bindType);
private: private:
WindowSurface(); WindowSurface();
WindowSurface(const WindowSurface& other); WindowSurface(const WindowSurface& other);
@ -87,7 +81,7 @@ private:
bool resize(unsigned int p_width, unsigned int p_height); bool resize(unsigned int p_width, unsigned int p_height);
private: private:
EGLSurface mSurface; EGLSurface mSurface;
ColorBufferPtr mAttachedColorBuffer; ColorBufferPtr mAttachedColorBuffer;
RenderContextPtr mReadContext; RenderContextPtr mReadContext;

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];
@ -72,18 +78,20 @@ void GLRendererServer::start() {
log_funcs.coarse = logger_write; log_funcs.coarse = logger_write;
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

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