Reformat all code and use the Google cpp code style
This commit is contained in:
parent
09811d780c
commit
b10382d2d8
222 changed files with 8739 additions and 9281 deletions
8
.clang-format
Normal file
8
.clang-format
Normal 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
3
scripts/clean-format.sh
Executable 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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,5 +37,4 @@ std::ostream& operator<<(std::ostream &out, const Intent &intent);
|
||||||
} // namespace android
|
} // namespace android
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_APPLICATION_MANAGER_H_
|
#ifndef ANBOX_APPLICATION_MANAGER_H_
|
||||||
#define ANBOX_APPLICATION_MANAGER_H_
|
#define ANBOX_APPLICATION_MANAGER_H_
|
||||||
|
|
||||||
#include "anbox/do_not_copy_or_move.h"
|
|
||||||
#include "anbox/android/intent.h"
|
#include "anbox/android/intent.h"
|
||||||
|
#include "anbox/do_not_copy_or_move.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/bridge/android_api_stub.h"
|
#include "anbox/bridge/android_api_stub.h"
|
||||||
#include "anbox/rpc/channel.h"
|
|
||||||
#include "anbox/utils.h"
|
|
||||||
#include "anbox/config.h"
|
#include "anbox/config.h"
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/rpc/channel.h"
|
||||||
|
#include "anbox/utils.h"
|
||||||
|
|
||||||
#include "anbox_rpc.pb.h"
|
|
||||||
#include "anbox_bridge.pb.h"
|
#include "anbox_bridge.pb.h"
|
||||||
|
#include "anbox_rpc.pb.h"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
|
@ -30,23 +30,19 @@ namespace fs = boost::filesystem;
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace bridge {
|
namespace bridge {
|
||||||
AndroidApiStub::AndroidApiStub() {
|
AndroidApiStub::AndroidApiStub() {}
|
||||||
}
|
|
||||||
|
|
||||||
AndroidApiStub::~AndroidApiStub() {
|
AndroidApiStub::~AndroidApiStub() {}
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidApiStub::set_rpc_channel(const std::shared_ptr<rpc::Channel> &channel) {
|
void AndroidApiStub::set_rpc_channel(
|
||||||
|
const std::shared_ptr<rpc::Channel> &channel) {
|
||||||
channel_ = channel;
|
channel_ = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidApiStub::reset_rpc_channel() {
|
void AndroidApiStub::reset_rpc_channel() { channel_.reset(); }
|
||||||
channel_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidApiStub::ensure_rpc_channel() {
|
void AndroidApiStub::ensure_rpc_channel() {
|
||||||
if (!channel_)
|
if (!channel_) throw std::runtime_error("No remote client connected");
|
||||||
throw std::runtime_error("No remote client connected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidApiStub::launch(const android::Intent &intent) {
|
void AndroidApiStub::launch(const android::Intent &intent) {
|
||||||
|
|
@ -62,38 +58,33 @@ void AndroidApiStub::launch(const android::Intent &intent) {
|
||||||
|
|
||||||
auto launch_intent = message.mutable_intent();
|
auto launch_intent = message.mutable_intent();
|
||||||
|
|
||||||
if (!intent.action.empty())
|
if (!intent.action.empty()) launch_intent->set_action(intent.action);
|
||||||
launch_intent->set_action(intent.action);
|
|
||||||
|
|
||||||
if (!intent.uri.empty())
|
if (!intent.uri.empty()) launch_intent->set_uri(intent.uri);
|
||||||
launch_intent->set_uri(intent.uri);
|
|
||||||
|
|
||||||
if (!intent.type.empty())
|
if (!intent.type.empty()) launch_intent->set_type(intent.type);
|
||||||
launch_intent->set_type(intent.type);
|
|
||||||
|
|
||||||
if (!intent.package.empty())
|
if (!intent.package.empty()) launch_intent->set_package(intent.package);
|
||||||
launch_intent->set_package(intent.package);
|
|
||||||
|
|
||||||
if (!intent.component.empty())
|
if (!intent.component.empty()) launch_intent->set_component(intent.component);
|
||||||
launch_intent->set_component(intent.component);
|
|
||||||
|
|
||||||
for (const auto &category : intent.categories) {
|
for (const auto &category : intent.categories) {
|
||||||
auto c = launch_intent->add_categories();
|
auto c = launch_intent->add_categories();
|
||||||
*c = category;
|
*c = category;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_->call_method("launch_application",
|
channel_->call_method(
|
||||||
&message,
|
"launch_application", &message, c->response.get(),
|
||||||
c->response.get(),
|
google::protobuf::NewCallback(this, &AndroidApiStub::application_launched,
|
||||||
google::protobuf::NewCallback(this, &AndroidApiStub::application_launched, c.get()));
|
c.get()));
|
||||||
|
|
||||||
launch_wait_handle_.wait_for_all();
|
launch_wait_handle_.wait_for_all();
|
||||||
|
|
||||||
if (c->response->has_error())
|
if (c->response->has_error()) throw std::runtime_error(c->response->error());
|
||||||
throw std::runtime_error(c->response->error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidApiStub::application_launched(Request<protobuf::rpc::Void> *request) {
|
void AndroidApiStub::application_launched(
|
||||||
|
Request<protobuf::rpc::Void> *request) {
|
||||||
(void)request;
|
(void)request;
|
||||||
launch_wait_handle_.result_received();
|
launch_wait_handle_.result_received();
|
||||||
}
|
}
|
||||||
|
|
@ -111,15 +102,13 @@ void AndroidApiStub::set_focused_task(const std::int32_t &id) {
|
||||||
set_focused_task_handle_.expect_result();
|
set_focused_task_handle_.expect_result();
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_->call_method("set_focused_task",
|
channel_->call_method("set_focused_task", &message, c->response.get(),
|
||||||
&message,
|
google::protobuf::NewCallback(
|
||||||
c->response.get(),
|
this, &AndroidApiStub::focused_task_set, c.get()));
|
||||||
google::protobuf::NewCallback(this, &AndroidApiStub::focused_task_set, c.get()));
|
|
||||||
|
|
||||||
set_focused_task_handle_.wait_for_all();
|
set_focused_task_handle_.wait_for_all();
|
||||||
|
|
||||||
if (c->response->has_error())
|
if (c->response->has_error()) throw std::runtime_error(c->response->error());
|
||||||
throw std::runtime_error(c->response->error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidApiStub::focused_task_set(Request<protobuf::rpc::Void> *request) {
|
void AndroidApiStub::focused_task_set(Request<protobuf::rpc::Void> *request) {
|
||||||
|
|
|
||||||
|
|
@ -17,40 +17,41 @@
|
||||||
|
|
||||||
#include "anbox/bridge/platform_api_skeleton.h"
|
#include "anbox/bridge/platform_api_skeleton.h"
|
||||||
#include "anbox/application/launcher_storage.h"
|
#include "anbox/application/launcher_storage.h"
|
||||||
|
#include "anbox/logger.h"
|
||||||
#include "anbox/wm/manager.h"
|
#include "anbox/wm/manager.h"
|
||||||
#include "anbox/wm/window_state.h"
|
#include "anbox/wm/window_state.h"
|
||||||
#include "anbox/logger.h"
|
|
||||||
|
|
||||||
#include "anbox_bridge.pb.h"
|
#include "anbox_bridge.pb.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace bridge {
|
namespace bridge {
|
||||||
PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
PlatformApiSkeleton::PlatformApiSkeleton(
|
||||||
|
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
||||||
const std::shared_ptr<wm::Manager> &window_manager,
|
const std::shared_ptr<wm::Manager> &window_manager,
|
||||||
const std::shared_ptr<application::LauncherStorage> &launcher_storage) :
|
const std::shared_ptr<application::LauncherStorage> &launcher_storage)
|
||||||
pending_calls_(pending_calls),
|
: pending_calls_(pending_calls),
|
||||||
window_manager_(window_manager),
|
window_manager_(window_manager),
|
||||||
launcher_storage_(launcher_storage) {
|
launcher_storage_(launcher_storage) {}
|
||||||
}
|
|
||||||
|
|
||||||
PlatformApiSkeleton::~PlatformApiSkeleton() {
|
PlatformApiSkeleton::~PlatformApiSkeleton() {}
|
||||||
}
|
|
||||||
|
|
||||||
void PlatformApiSkeleton::handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event) {
|
void PlatformApiSkeleton::handle_boot_finished_event(
|
||||||
|
const anbox::protobuf::bridge::BootFinishedEvent &event) {
|
||||||
(void)event;
|
(void)event;
|
||||||
|
|
||||||
if (boot_finished_handler_)
|
if (boot_finished_handler_) boot_finished_handler_();
|
||||||
boot_finished_handler_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event) {
|
void PlatformApiSkeleton::handle_window_state_update_event(
|
||||||
auto convert_window_state = [](const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState &window) {
|
const anbox::protobuf::bridge::WindowStateUpdateEvent &event) {
|
||||||
|
auto convert_window_state = [](
|
||||||
|
const ::anbox::protobuf::bridge::WindowStateUpdateEvent_WindowState
|
||||||
|
&window) {
|
||||||
return wm::WindowState(
|
return wm::WindowState(
|
||||||
wm::Display::Id(window.display_id()),
|
wm::Display::Id(window.display_id()), window.has_surface(),
|
||||||
window.has_surface(),
|
graphics::Rect(window.frame_left(), window.frame_top(),
|
||||||
graphics::Rect(window.frame_left(), window.frame_top(), window.frame_right(), window.frame_bottom()),
|
window.frame_right(), window.frame_bottom()),
|
||||||
window.package_name(),
|
window.package_name(), wm::Task::Id(window.task_id()),
|
||||||
wm::Task::Id(window.task_id()),
|
|
||||||
wm::Stack::Id(window.stack_id()));
|
wm::Stack::Id(window.stack_id()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -69,7 +70,8 @@ void PlatformApiSkeleton::handle_window_state_update_event(const anbox::protobuf
|
||||||
window_manager_->apply_window_state_update(updated, removed);
|
window_manager_->apply_window_state_update(updated, removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformApiSkeleton::handle_application_list_update_event(const anbox::protobuf::bridge::ApplicationListUpdateEvent &event) {
|
void PlatformApiSkeleton::handle_application_list_update_event(
|
||||||
|
const anbox::protobuf::bridge::ApplicationListUpdateEvent &event) {
|
||||||
for (int n = 0; n < event.applications_size(); n++) {
|
for (int n = 0; n < event.applications_size(); n++) {
|
||||||
application::LauncherStorage::Item item;
|
application::LauncherStorage::Item item;
|
||||||
|
|
||||||
|
|
@ -92,7 +94,8 @@ void PlatformApiSkeleton::handle_application_list_update_event(const anbox::prot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformApiSkeleton::register_boot_finished_handler(const std::function<void()> &action) {
|
void PlatformApiSkeleton::register_boot_finished_handler(
|
||||||
|
const std::function<void()> &action) {
|
||||||
boot_finished_handler_ = action;
|
boot_finished_handler_ = action;
|
||||||
}
|
}
|
||||||
} // namespace bridge
|
} // namespace bridge
|
||||||
|
|
|
||||||
|
|
@ -49,14 +49,18 @@ class LauncherStorage;
|
||||||
namespace bridge {
|
namespace bridge {
|
||||||
class PlatformApiSkeleton {
|
class PlatformApiSkeleton {
|
||||||
public:
|
public:
|
||||||
PlatformApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
PlatformApiSkeleton(
|
||||||
|
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
||||||
const std::shared_ptr<wm::Manager> &window_manager,
|
const std::shared_ptr<wm::Manager> &window_manager,
|
||||||
const std::shared_ptr<application::LauncherStorage> &launcher_storage);
|
const std::shared_ptr<application::LauncherStorage> &launcher_storage);
|
||||||
virtual ~PlatformApiSkeleton();
|
virtual ~PlatformApiSkeleton();
|
||||||
|
|
||||||
void handle_boot_finished_event(const anbox::protobuf::bridge::BootFinishedEvent &event);
|
void handle_boot_finished_event(
|
||||||
void handle_window_state_update_event(const anbox::protobuf::bridge::WindowStateUpdateEvent &event);
|
const anbox::protobuf::bridge::BootFinishedEvent &event);
|
||||||
void handle_application_list_update_event(const anbox::protobuf::bridge::ApplicationListUpdateEvent &event);
|
void handle_window_state_update_event(
|
||||||
|
const anbox::protobuf::bridge::WindowStateUpdateEvent &event);
|
||||||
|
void handle_application_list_update_event(
|
||||||
|
const anbox::protobuf::bridge::ApplicationListUpdateEvent &event);
|
||||||
|
|
||||||
void register_boot_finished_handler(const std::function<void()> &action);
|
void register_boot_finished_handler(const std::function<void()> &action);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ namespace bridge {
|
||||||
class PlatformApiSkeleton;
|
class PlatformApiSkeleton;
|
||||||
class PlatformMessageProcessor : public rpc::MessageProcessor {
|
class PlatformMessageProcessor : public rpc::MessageProcessor {
|
||||||
public:
|
public:
|
||||||
PlatformMessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
|
PlatformMessageProcessor(
|
||||||
|
const std::shared_ptr<network::MessageSender> &sender,
|
||||||
const std::shared_ptr<PlatformApiSkeleton> &server,
|
const std::shared_ptr<PlatformApiSkeleton> &server,
|
||||||
const std::shared_ptr<rpc::PendingCallCache> &pending_calls);
|
const std::shared_ptr<rpc::PendingCallCache> &pending_calls);
|
||||||
~PlatformMessageProcessor();
|
~PlatformMessageProcessor();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
169
src/anbox/cli.h
169
src/anbox/cli.h
|
|
@ -35,44 +35,36 @@ namespace anbox {
|
||||||
namespace cli {
|
namespace cli {
|
||||||
|
|
||||||
template <std::size_t max>
|
template <std::size_t max>
|
||||||
class SizeConstrainedString
|
class SizeConstrainedString {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
SizeConstrainedString(const std::string& s) : s{s}
|
SizeConstrainedString(const std::string& s) : s{s} {
|
||||||
{
|
|
||||||
if (s.size() > max)
|
if (s.size() > max)
|
||||||
throw std::logic_error{"Max size exceeded " + std::to_string(max)};
|
throw std::logic_error{"Max size exceeded " + std::to_string(max)};
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& as_string() const
|
const std::string& as_string() const { return s; }
|
||||||
{
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::string() const
|
operator std::string() const { return s; }
|
||||||
{
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string s;
|
std::string s;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t max>
|
template <std::size_t max>
|
||||||
bool operator<(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs)
|
bool operator<(const SizeConstrainedString<max>& lhs,
|
||||||
{
|
const SizeConstrainedString<max>& rhs) {
|
||||||
return lhs.as_string() < rhs.as_string();
|
return lhs.as_string() < rhs.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t max>
|
template <std::size_t max>
|
||||||
bool operator==(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs)
|
bool operator==(const SizeConstrainedString<max>& lhs,
|
||||||
{
|
const SizeConstrainedString<max>& rhs) {
|
||||||
return lhs.as_string() == rhs.as_string();
|
return lhs.as_string() == rhs.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t max>
|
template <std::size_t max>
|
||||||
std::ostream& operator<<(std::ostream& out, const SizeConstrainedString<max>& scs)
|
std::ostream& operator<<(std::ostream& out,
|
||||||
{
|
const SizeConstrainedString<max>& scs) {
|
||||||
return out << std::setw(max) << std::left << scs.as_string();
|
return out << std::setw(max) << std::left << scs.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,8 +74,7 @@ typedef SizeConstrainedString<60> Usage;
|
||||||
typedef SizeConstrainedString<60> Description;
|
typedef SizeConstrainedString<60> Description;
|
||||||
|
|
||||||
/// @brief Flag models an input parameter to a command.
|
/// @brief Flag models an input parameter to a command.
|
||||||
class Flag : public DoNotCopyOrMove
|
class Flag : public DoNotCopyOrMove {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// Safe us some typing.
|
// Safe us some typing.
|
||||||
typedef std::shared_ptr<Flag> Ptr;
|
typedef std::shared_ptr<Flag> Ptr;
|
||||||
|
|
@ -105,35 +96,30 @@ private:
|
||||||
Description description_;
|
Description description_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief TypedFlag implements Flag relying on operator<< and operator>> to read/write values to/from strings.
|
/// @brief TypedFlag implements Flag relying on operator<< and operator>> to
|
||||||
|
/// read/write values to/from strings.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedFlag : public Flag
|
class TypedFlag : public Flag {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<TypedFlag<T>> Ptr;
|
typedef std::shared_ptr<TypedFlag<T>> Ptr;
|
||||||
|
|
||||||
TypedFlag(const Name& name, const Description& description) : Flag{name, description}
|
TypedFlag(const Name& name, const Description& description)
|
||||||
{
|
: Flag{name, description} {}
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief value installs the given value in the flag.
|
/// @brief value installs the given value in the flag.
|
||||||
TypedFlag& value(const T& value)
|
TypedFlag& value(const T& value) {
|
||||||
{
|
|
||||||
value_ = value;
|
value_ = value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief value returns the optional value associated with the flag.
|
/// @brief value returns the optional value associated with the flag.
|
||||||
const Optional<T>& value() const
|
const Optional<T>& value() const { return value_; }
|
||||||
{
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief notify tries to unwrap a value of type T from value.
|
/// @brief notify tries to unwrap a value of type T from value.
|
||||||
void notify(const std::string& s) override
|
void notify(const std::string& s) override {
|
||||||
{
|
|
||||||
std::stringstream ss{s};
|
std::stringstream ss{s};
|
||||||
T value; ss >> value;
|
T value;
|
||||||
|
ss >> value;
|
||||||
value_ = value;
|
value_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,26 +127,23 @@ private:
|
||||||
Optional<T> value_;
|
Optional<T> value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to convert to/from string representations,
|
/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to
|
||||||
|
/// convert to/from string representations,
|
||||||
/// updating the given mutable reference to a value of type T.
|
/// updating the given mutable reference to a value of type T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedReferenceFlag : public Flag
|
class TypedReferenceFlag : public Flag {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// Safe us some typing.
|
// Safe us some typing.
|
||||||
typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
|
typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
|
||||||
|
|
||||||
/// @brief TypedReferenceFlag initializes a new instance with name, description and value.
|
/// @brief TypedReferenceFlag initializes a new instance with name,
|
||||||
|
/// description and value.
|
||||||
TypedReferenceFlag(const Name& name, const Description& description, T& value)
|
TypedReferenceFlag(const Name& name, const Description& description, T& value)
|
||||||
: Flag{name, description},
|
: Flag{name, description}, value_{value} {}
|
||||||
value_{value}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief notify tries to unwrap a value of type T from value,
|
/// @brief notify tries to unwrap a value of type T from value,
|
||||||
/// relying on operator>> to read from given string s.
|
/// relying on operator>> to read from given string s.
|
||||||
void notify(const std::string& s) override
|
void notify(const std::string& s) override {
|
||||||
{
|
|
||||||
std::stringstream ss{s};
|
std::stringstream ss{s};
|
||||||
ss >> value_.get();
|
ss >> value_.get();
|
||||||
}
|
}
|
||||||
|
|
@ -169,24 +152,24 @@ private:
|
||||||
std::reference_wrapper<T> value_;
|
std::reference_wrapper<T> value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making sure that
|
/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making
|
||||||
/// a value is always read on notify, even if the Optional<T> wasn't initialized previously.
|
/// sure that
|
||||||
|
/// a value is always read on notify, even if the Optional<T> wasn't initialized
|
||||||
|
/// previously.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class OptionalTypedReferenceFlag : public Flag
|
class OptionalTypedReferenceFlag : public Flag {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
|
typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
|
||||||
|
|
||||||
OptionalTypedReferenceFlag(const Name& name, const Description& description, Optional<T>& value)
|
OptionalTypedReferenceFlag(const Name& name, const Description& description,
|
||||||
: Flag{name, description},
|
Optional<T>& value)
|
||||||
value_{value}
|
: Flag{name, description}, value_{value} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief notify tries to unwrap a value of type T from value.
|
/// @brief notify tries to unwrap a value of type T from value.
|
||||||
void notify(const std::string& s) override
|
void notify(const std::string& s) override {
|
||||||
{
|
std::stringstream ss{s};
|
||||||
std::stringstream ss{s}; T value; ss >> value;
|
T value;
|
||||||
|
ss >> value;
|
||||||
value_.get() = value;
|
value_.get() = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,29 +178,26 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Command abstracts an individual command available from the daemon.
|
/// @brief Command abstracts an individual command available from the daemon.
|
||||||
class Command : public DoNotCopyOrMove
|
class Command : public DoNotCopyOrMove {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// Safe us some typing
|
// Safe us some typing
|
||||||
typedef std::shared_ptr<Command> Ptr;
|
typedef std::shared_ptr<Command> Ptr;
|
||||||
|
|
||||||
/// @brief FlagsMissing is thrown if at least one required flag is missing.
|
/// @brief FlagsMissing is thrown if at least one required flag is missing.
|
||||||
struct FlagsMissing : public std::runtime_error
|
struct FlagsMissing : public std::runtime_error {
|
||||||
{
|
|
||||||
/// @brief FlagsMissing initializes a new instance.
|
/// @brief FlagsMissing initializes a new instance.
|
||||||
FlagsMissing();
|
FlagsMissing();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief FlagsWithWrongValue is thrown if a value passed on the command line is invalid.
|
/// @brief FlagsWithWrongValue is thrown if a value passed on the command line
|
||||||
struct FlagsWithInvalidValue : public std::runtime_error
|
/// is invalid.
|
||||||
{
|
struct FlagsWithInvalidValue : public std::runtime_error {
|
||||||
/// @brief FlagsWithInvalidValue initializes a new instance.
|
/// @brief FlagsWithInvalidValue initializes a new instance.
|
||||||
FlagsWithInvalidValue();
|
FlagsWithInvalidValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Context bundles information passed to Command::run invocations.
|
/// @brief Context bundles information passed to Command::run invocations.
|
||||||
struct Context
|
struct Context {
|
||||||
{
|
|
||||||
std::istream& cin; ///< The std::istream that should be used for reading.
|
std::istream& cin; ///< The std::istream that should be used for reading.
|
||||||
std::ostream& cout; ///< The std::ostream that should be used for writing.
|
std::ostream& cout; ///< The std::ostream that should be used for writing.
|
||||||
std::vector<std::string> args; ///< The command line args.
|
std::vector<std::string> args; ///< The command line args.
|
||||||
|
|
@ -239,7 +219,8 @@ public:
|
||||||
virtual void help(std::ostream& out) = 0;
|
virtual void help(std::ostream& out) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @brief Command initializes a new instance with the given name, usage and description.
|
/// @brief Command initializes a new instance with the given name, usage and
|
||||||
|
/// description.
|
||||||
Command(const Name& name, const Usage& usage, const Description& description);
|
Command(const Name& name, const Usage& usage, const Description& description);
|
||||||
|
|
||||||
/// @brief name adjusts the name of the command to n.
|
/// @brief name adjusts the name of the command to n.
|
||||||
|
|
@ -255,15 +236,17 @@ private:
|
||||||
Description description_;
|
Description description_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief CommandWithSubcommands implements Command, selecting one of a set of actions.
|
/// @brief CommandWithSubcommands implements Command, selecting one of a set of
|
||||||
class CommandWithSubcommands : public Command
|
/// actions.
|
||||||
{
|
class CommandWithSubcommands : public Command {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<CommandWithSubcommands> Ptr;
|
typedef std::shared_ptr<CommandWithSubcommands> Ptr;
|
||||||
typedef std::function<int(const Context&)> Action;
|
typedef std::function<int(const Context&)> Action;
|
||||||
|
|
||||||
/// @brief CommandWithSubcommands initializes a new instance with the given name, usage and description
|
/// @brief CommandWithSubcommands initializes a new instance with the given
|
||||||
CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description);
|
/// name, usage and description
|
||||||
|
CommandWithSubcommands(const Name& name, const Usage& usage,
|
||||||
|
const Description& description);
|
||||||
|
|
||||||
/// @brief command adds the given command to the set of known commands.
|
/// @brief command adds the given command to the set of known commands.
|
||||||
CommandWithSubcommands& command(const Command::Ptr& command);
|
CommandWithSubcommands& command(const Command::Ptr& command);
|
||||||
|
|
@ -280,15 +263,17 @@ private:
|
||||||
std::set<Flag::Ptr> flags_;
|
std::set<Flag::Ptr> flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief CommandWithFlagsAction implements Command, executing an Action after handling
|
/// @brief CommandWithFlagsAction implements Command, executing an Action after
|
||||||
class CommandWithFlagsAndAction : public Command
|
/// handling
|
||||||
{
|
class CommandWithFlagsAndAction : public Command {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
|
typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
|
||||||
typedef std::function<int(const Context&)> Action;
|
typedef std::function<int(const Context&)> Action;
|
||||||
|
|
||||||
/// @brief CommandWithFlagsAndAction initializes a new instance with the given name, usage and description
|
/// @brief CommandWithFlagsAndAction initializes a new instance with the given
|
||||||
CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description);
|
/// name, usage and description
|
||||||
|
CommandWithFlagsAndAction(const Name& name, const Usage& usage,
|
||||||
|
const Description& description);
|
||||||
|
|
||||||
/// @brief flag adds the given flag to the set of known flags.
|
/// @brief flag adds the given flag to the set of known flags.
|
||||||
CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
|
CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
|
||||||
|
|
@ -305,13 +290,12 @@ private:
|
||||||
Action action_;
|
Action action_;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace cmd
|
namespace cmd {
|
||||||
{
|
|
||||||
/// @brief HelpFor prints a help message for the given command on execution.
|
/// @brief HelpFor prints a help message for the given command on execution.
|
||||||
class Help : public Command
|
class Help : public Command {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/// @brief HelpFor initializes a new instance with the given reference to a cmd.
|
/// @brief HelpFor initializes a new instance with the given reference to a
|
||||||
|
/// cmd.
|
||||||
explicit Help(Command& cmd);
|
explicit Help(Command& cmd);
|
||||||
|
|
||||||
// From Command
|
// From Command
|
||||||
|
|
@ -330,27 +314,30 @@ std::vector<std::string> args(int argc, char** argv);
|
||||||
|
|
||||||
/// @brief make_flag returns a flag with the given name and description.
|
/// @brief make_flag returns a flag with the given name and description.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypedFlag<T>::Ptr make_flag(const Name& name, const Description& description)
|
typename TypedFlag<T>::Ptr make_flag(const Name& name,
|
||||||
{
|
const Description& description) {
|
||||||
return std::make_shared<TypedFlag<T>>(name, description);
|
return std::make_shared<TypedFlag<T>>(name, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief make_flag returns a flag with the given name and description, notifying updates to value.
|
/// @brief make_flag returns a flag with the given name and description,
|
||||||
|
/// notifying updates to value.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, T& value)
|
typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name,
|
||||||
{
|
const Description& desc,
|
||||||
|
T& value) {
|
||||||
return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
|
return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief make_flag returns a flag with the given name and description, updating the given optional value.
|
/// @brief make_flag returns a flag with the given name and description,
|
||||||
|
/// updating the given optional value.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, Optional<T>& value)
|
typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name,
|
||||||
{
|
const Description& desc,
|
||||||
|
Optional<T>& value) {
|
||||||
return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
|
return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cli
|
} // namespace cli
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,18 @@
|
||||||
|
|
||||||
#include "anbox/cmds/container_manager.h"
|
#include "anbox/cmds/container_manager.h"
|
||||||
#include "anbox/container/service.h"
|
#include "anbox/container/service.h"
|
||||||
#include "anbox/runtime.h"
|
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
#include "core/posix/signal.h"
|
#include "core/posix/signal.h"
|
||||||
|
|
||||||
anbox::cmds::ContainerManager::ContainerManager()
|
anbox::cmds::ContainerManager::ContainerManager()
|
||||||
: CommandWithFlagsAndAction{cli::Name{"container-manager"}, cli::Usage{"container-manager"}, cli::Description{"Start the container manager service"}}
|
: CommandWithFlagsAndAction{
|
||||||
{
|
cli::Name{"container-manager"}, cli::Usage{"container-manager"},
|
||||||
|
cli::Description{"Start the container manager service"}} {
|
||||||
action([](const cli::Command::Context& ctxt) {
|
action([](const cli::Command::Context& ctxt) {
|
||||||
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term,
|
auto trap = core::posix::trap_signals_for_process(
|
||||||
core::posix::Signal::sig_int});
|
{core::posix::Signal::sig_term, core::posix::Signal::sig_int});
|
||||||
trap->signal_raised().connect([trap](const core::posix::Signal& signal) {
|
trap->signal_raised().connect([trap](const core::posix::Signal& signal) {
|
||||||
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
||||||
trap->stop();
|
trap->stop();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "anbox/cli.h"
|
|
||||||
#include "anbox/android/intent.h"
|
#include "anbox/android/intent.h"
|
||||||
|
#include "anbox/cli.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace cmds {
|
namespace cmds {
|
||||||
|
|
|
||||||
|
|
@ -19,40 +19,42 @@
|
||||||
|
|
||||||
#include "core/posix/signal.h"
|
#include "core/posix/signal.h"
|
||||||
|
|
||||||
#include "anbox/logger.h"
|
#include "anbox/application/launcher_storage.h"
|
||||||
#include "anbox/runtime.h"
|
|
||||||
#include "anbox/config.h"
|
|
||||||
#include "anbox/common/dispatcher.h"
|
|
||||||
#include "anbox/cmds/run.h"
|
|
||||||
#include "anbox/network/published_socket_connector.h"
|
|
||||||
#include "anbox/qemu/pipe_connection_creator.h"
|
|
||||||
#include "anbox/graphics/gl_renderer_server.h"
|
|
||||||
#include "anbox/input/manager.h"
|
|
||||||
#include "anbox/rpc/connection_creator.h"
|
|
||||||
#include "anbox/rpc/channel.h"
|
|
||||||
#include "anbox/bridge/platform_message_processor.h"
|
|
||||||
#include "anbox/bridge/android_api_stub.h"
|
#include "anbox/bridge/android_api_stub.h"
|
||||||
#include "anbox/bridge/platform_api_skeleton.h"
|
#include "anbox/bridge/platform_api_skeleton.h"
|
||||||
#include "anbox/dbus/skeleton/service.h"
|
#include "anbox/bridge/platform_message_processor.h"
|
||||||
|
#include "anbox/cmds/run.h"
|
||||||
|
#include "anbox/common/dispatcher.h"
|
||||||
|
#include "anbox/config.h"
|
||||||
#include "anbox/container/client.h"
|
#include "anbox/container/client.h"
|
||||||
#include "anbox/wm/manager.h"
|
#include "anbox/dbus/skeleton/service.h"
|
||||||
|
#include "anbox/graphics/gl_renderer_server.h"
|
||||||
|
#include "anbox/input/manager.h"
|
||||||
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/network/published_socket_connector.h"
|
||||||
|
#include "anbox/qemu/pipe_connection_creator.h"
|
||||||
|
#include "anbox/rpc/channel.h"
|
||||||
|
#include "anbox/rpc/connection_creator.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
#include "anbox/ubuntu/platform_policy.h"
|
#include "anbox/ubuntu/platform_policy.h"
|
||||||
#include "anbox/application/launcher_storage.h"
|
#include "anbox/wm/manager.h"
|
||||||
|
|
||||||
#include "external/xdg/xdg.h"
|
#include "external/xdg/xdg.h"
|
||||||
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include <core/dbus/bus.h>
|
|
||||||
#include <core/dbus/asio/executor.h>
|
#include <core/dbus/asio/executor.h>
|
||||||
|
#include <core/dbus/bus.h>
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class NullConnectionCreator : public anbox::network::ConnectionCreator<boost::asio::local::stream_protocol> {
|
class NullConnectionCreator : public anbox::network::ConnectionCreator<
|
||||||
|
boost::asio::local::stream_protocol> {
|
||||||
public:
|
public:
|
||||||
void create_connection_for(
|
void create_connection_for(
|
||||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override {
|
std::shared_ptr<boost::asio::local::stream_protocol::socket> const
|
||||||
|
&socket) override {
|
||||||
WARNING("Not implemented");
|
WARNING("Not implemented");
|
||||||
socket->close();
|
socket->close();
|
||||||
}
|
}
|
||||||
|
|
@ -66,25 +68,29 @@ anbox::cmds::Run::BusFactory anbox::cmds::Run::session_bus_factory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
anbox::cmds::Run::Run(const BusFactory &bus_factory)
|
anbox::cmds::Run::Run(const BusFactory &bus_factory)
|
||||||
: CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"Run the the anbox system"}},
|
: CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"},
|
||||||
bus_factory_(bus_factory)
|
cli::Description{"Run the the anbox system"}},
|
||||||
{
|
bus_factory_(bus_factory) {
|
||||||
// Just for the purpose to allow QtMir (or unity8) to find this on our /proc/*/cmdline
|
// Just for the purpose to allow QtMir (or unity8) to find this on our
|
||||||
|
// /proc/*/cmdline
|
||||||
// for proper confinement etc.
|
// for proper confinement etc.
|
||||||
flag(cli::make_flag(cli::Name{"desktop_file_hint"}, cli::Description{"Desktop file hint for QtMir/Unity8"}, desktop_file_hint_));
|
flag(cli::make_flag(cli::Name{"desktop_file_hint"},
|
||||||
flag(cli::make_flag(cli::Name{"icon"}, cli::Description{"Icon of the application to run"}, icon_));
|
cli::Description{"Desktop file hint for QtMir/Unity8"},
|
||||||
|
desktop_file_hint_));
|
||||||
|
flag(cli::make_flag(cli::Name{"icon"},
|
||||||
|
cli::Description{"Icon of the application to run"},
|
||||||
|
icon_));
|
||||||
|
|
||||||
action([this](const cli::Command::Context &ctx) {
|
action([this](const cli::Command::Context &ctx) {
|
||||||
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term,
|
auto trap = core::posix::trap_signals_for_process(
|
||||||
core::posix::Signal::sig_int});
|
{core::posix::Signal::sig_term, core::posix::Signal::sig_int});
|
||||||
trap->signal_raised().connect([trap](const core::posix::Signal &signal) {
|
trap->signal_raised().connect([trap](const core::posix::Signal &signal) {
|
||||||
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
||||||
trap->stop();
|
trap->stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
utils::ensure_paths({
|
utils::ensure_paths({
|
||||||
config::socket_path(),
|
config::socket_path(), config::host_input_device_path(),
|
||||||
config::host_input_device_path(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto rt = Runtime::create();
|
auto rt = Runtime::create();
|
||||||
|
|
@ -94,7 +100,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
|
||||||
|
|
||||||
auto android_api_stub = std::make_shared<bridge::AndroidApiStub>();
|
auto android_api_stub = std::make_shared<bridge::AndroidApiStub>();
|
||||||
|
|
||||||
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager, android_api_stub);
|
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager,
|
||||||
|
android_api_stub);
|
||||||
// FIXME this needs to be removed and solved differently behind the scenes
|
// FIXME this needs to be removed and solved differently behind the scenes
|
||||||
registerDisplayManager(policy);
|
registerDisplayManager(policy);
|
||||||
|
|
||||||
|
|
@ -103,7 +110,8 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
|
||||||
auto launcher_storage = std::make_shared<application::LauncherStorage>(
|
auto launcher_storage = std::make_shared<application::LauncherStorage>(
|
||||||
xdg::data().home() / "applications");
|
xdg::data().home() / "applications");
|
||||||
|
|
||||||
auto renderer = std::make_shared<graphics::GLRendererServer>(window_manager);
|
auto renderer =
|
||||||
|
std::make_shared<graphics::GLRendererServer>(window_manager);
|
||||||
renderer->start();
|
renderer->start();
|
||||||
|
|
||||||
// Socket which will be used by the qemud service inside the Android
|
// Socket which will be used by the qemud service inside the Android
|
||||||
|
|
@ -117,32 +125,31 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
|
||||||
|
|
||||||
// The qemu pipe is used as a very fast communication channel between guest
|
// The qemu pipe is used as a very fast communication channel between guest
|
||||||
// and host for things like the GLES emulation/translation, the RIL or ADB.
|
// and host for things like the GLES emulation/translation, the RIL or ADB.
|
||||||
auto qemu_pipe_connector = std::make_shared<network::PublishedSocketConnector>(
|
auto qemu_pipe_connector =
|
||||||
utils::string_format("%s/qemu_pipe", config::socket_path()),
|
std::make_shared<network::PublishedSocketConnector>(
|
||||||
rt,
|
utils::string_format("%s/qemu_pipe", config::socket_path()), rt,
|
||||||
std::make_shared<qemu::PipeConnectionCreator>(rt,
|
std::make_shared<qemu::PipeConnectionCreator>(
|
||||||
renderer->socket_path(),
|
rt, renderer->socket_path(), icon_));
|
||||||
icon_));
|
|
||||||
|
|
||||||
|
|
||||||
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
|
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
|
||||||
utils::string_format("%s/anbox_bridge", config::socket_path()),
|
utils::string_format("%s/anbox_bridge", config::socket_path()), rt,
|
||||||
rt,
|
std::make_shared<rpc::ConnectionCreator>(
|
||||||
std::make_shared<rpc::ConnectionCreator>(rt,
|
rt, [&](const std::shared_ptr<network::MessageSender> &sender) {
|
||||||
[&](const std::shared_ptr<network::MessageSender> &sender) {
|
|
||||||
auto pending_calls = std::make_shared<rpc::PendingCallCache>();
|
auto pending_calls = std::make_shared<rpc::PendingCallCache>();
|
||||||
auto rpc_channel = std::make_shared<rpc::Channel>(pending_calls, sender);
|
auto rpc_channel =
|
||||||
// This is safe as long as we only support a single client. If we support
|
std::make_shared<rpc::Channel>(pending_calls, sender);
|
||||||
// more than one one day we need proper dispatching to the right one.
|
// This is safe as long as we only support a single client. If we
|
||||||
|
// support
|
||||||
|
// more than one one day we need proper dispatching to the right
|
||||||
|
// one.
|
||||||
android_api_stub->set_rpc_channel(rpc_channel);
|
android_api_stub->set_rpc_channel(rpc_channel);
|
||||||
|
|
||||||
auto server = std::make_shared<bridge::PlatformApiSkeleton>(pending_calls,
|
auto server = std::make_shared<bridge::PlatformApiSkeleton>(
|
||||||
window_manager,
|
pending_calls, window_manager, launcher_storage);
|
||||||
launcher_storage);
|
server->register_boot_finished_handler(
|
||||||
server->register_boot_finished_handler([&]() {
|
[&]() { DEBUG("Android successfully booted"); });
|
||||||
DEBUG("Android successfully booted");
|
return std::make_shared<bridge::PlatformMessageProcessor>(
|
||||||
});
|
sender, server, pending_calls);
|
||||||
return std::make_shared<bridge::PlatformMessageProcessor>(sender, server, pending_calls);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
container::Client container(rt);
|
container::Client container(rt);
|
||||||
|
|
@ -156,14 +163,14 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
|
||||||
{"/dev/ashmem", "/dev/ashmem"},
|
{"/dev/ashmem", "/dev/ashmem"},
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatcher->dispatch([&]() {
|
dispatcher->dispatch(
|
||||||
container.start_container(container_configuration);
|
[&]() { container.start_container(container_configuration); });
|
||||||
});
|
|
||||||
|
|
||||||
auto bus = bus_factory_();
|
auto bus = bus_factory_();
|
||||||
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
|
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
|
||||||
|
|
||||||
auto skeleton = anbox::dbus::skeleton::Service::create_for_bus(bus, android_api_stub);
|
auto skeleton =
|
||||||
|
anbox::dbus::skeleton::Service::create_for_bus(bus, android_api_stub);
|
||||||
|
|
||||||
rt->start();
|
rt->start();
|
||||||
trap->run();
|
trap->run();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,9 @@ namespace {
|
||||||
struct AsioStrandDispatcher : public anbox::common::Dispatcher {
|
struct AsioStrandDispatcher : public anbox::common::Dispatcher {
|
||||||
public:
|
public:
|
||||||
AsioStrandDispatcher(const std::shared_ptr<anbox::Runtime>& rt)
|
AsioStrandDispatcher(const std::shared_ptr<anbox::Runtime>& rt)
|
||||||
: rt{rt},
|
: rt{rt}, strand{rt->service()} {}
|
||||||
strand{rt->service()} {
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispatch(const Task &task) override {
|
void dispatch(const Task& task) override { strand.post(task); }
|
||||||
strand.post(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<anbox::Runtime> rt;
|
std::shared_ptr<anbox::Runtime> rt;
|
||||||
|
|
@ -37,7 +33,8 @@ private:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<anbox::common::Dispatcher> anbox::common::create_dispatcher_for_runtime(
|
std::shared_ptr<anbox::common::Dispatcher>
|
||||||
|
anbox::common::create_dispatcher_for_runtime(
|
||||||
const std::shared_ptr<anbox::Runtime>& rt) {
|
const std::shared_ptr<anbox::Runtime>& rt) {
|
||||||
return std::make_shared<AsioStrandDispatcher>(rt);
|
return std::make_shared<AsioStrandDispatcher>(rt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ protected:
|
||||||
Dispatcher() = default;
|
Dispatcher() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Dispatcher> create_dispatcher_for_runtime(const std::shared_ptr<Runtime>&);
|
std::shared_ptr<Dispatcher> create_dispatcher_for_runtime(
|
||||||
|
const std::shared_ptr<Runtime>&);
|
||||||
} // namespace common
|
} // namespace common
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,13 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
struct IntOwnedFd
|
struct IntOwnedFd {
|
||||||
{
|
|
||||||
int int_owned_fd;
|
int int_owned_fd;
|
||||||
};
|
};
|
||||||
class Fd
|
class Fd {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
//transfer ownership of the POD-int to the object. The int no longer needs close()ing,
|
// transfer ownership of the POD-int to the object. The int no longer needs
|
||||||
|
// close()ing,
|
||||||
// and has the lifetime of the Fd object.
|
// and has the lifetime of the Fd object.
|
||||||
explicit Fd(int fd);
|
explicit Fd(int fd);
|
||||||
explicit Fd(IntOwnedFd);
|
explicit Fd(IntOwnedFd);
|
||||||
|
|
@ -39,7 +38,8 @@ public:
|
||||||
Fd(Fd const&) = default;
|
Fd(Fd const&) = default;
|
||||||
Fd& operator=(Fd);
|
Fd& operator=(Fd);
|
||||||
|
|
||||||
//bit of a convenient kludge. take care not to close or otherwise destroy the FD.
|
// bit of a convenient kludge. take care not to close or otherwise destroy the
|
||||||
|
// FD.
|
||||||
operator int() const;
|
operator int() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -21,27 +21,18 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace common {
|
namespace common {
|
||||||
WaitHandle::WaitHandle() :
|
WaitHandle::WaitHandle()
|
||||||
guard(),
|
: guard(), wait_condition(), expecting(0), received(0) {}
|
||||||
wait_condition(),
|
|
||||||
expecting(0),
|
|
||||||
received(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitHandle::~WaitHandle()
|
WaitHandle::~WaitHandle() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitHandle::expect_result()
|
void WaitHandle::expect_result() {
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(guard);
|
std::lock_guard<std::mutex> lock(guard);
|
||||||
|
|
||||||
expecting++;
|
expecting++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitHandle::result_received()
|
void WaitHandle::result_received() {
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(guard);
|
std::lock_guard<std::mutex> lock(guard);
|
||||||
|
|
||||||
received++;
|
received++;
|
||||||
|
|
@ -58,14 +49,12 @@ void WaitHandle::wait_for_all() // wait for all results you expect
|
||||||
expecting = 0;
|
expecting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaitHandle::wait_for_pending(std::chrono::milliseconds limit)
|
void WaitHandle::wait_for_pending(std::chrono::milliseconds limit) {
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(guard);
|
std::unique_lock<std::mutex> lock(guard);
|
||||||
|
|
||||||
wait_condition.wait_for(lock, limit, [&] { return received == expecting; });
|
wait_condition.wait_for(lock, limit, [&] { return received == expecting; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WaitHandle::wait_for_one() // wait for any single result
|
void WaitHandle::wait_for_one() // wait for any single result
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(guard);
|
std::unique_lock<std::mutex> lock(guard);
|
||||||
|
|
@ -76,15 +65,13 @@ void WaitHandle::wait_for_one() // wait for any single result
|
||||||
--expecting;
|
--expecting;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WaitHandle::has_result()
|
bool WaitHandle::has_result() {
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(guard);
|
std::lock_guard<std::mutex> lock(guard);
|
||||||
|
|
||||||
return received > 0;
|
return received > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WaitHandle::is_pending()
|
bool WaitHandle::is_pending() {
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(guard);
|
std::unique_lock<std::mutex> lock(guard);
|
||||||
return expecting > 0 && received != expecting;
|
return expecting > 0 && received != expecting;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,7 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace common {
|
namespace common {
|
||||||
struct WaitHandle
|
struct WaitHandle {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
WaitHandle();
|
WaitHandle();
|
||||||
~WaitHandle();
|
~WaitHandle();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_CONTAINER_CLIENT_H_
|
#ifndef ANBOX_CONTAINER_CLIENT_H_
|
||||||
#define ANBOX_CONTAINER_CLIENT_H_
|
#define ANBOX_CONTAINER_CLIENT_H_
|
||||||
|
|
||||||
#include "anbox/runtime.h"
|
|
||||||
#include "anbox/container/configuration.h"
|
#include "anbox/container/configuration.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
@ -41,7 +41,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void read_next_message();
|
void read_next_message();
|
||||||
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read);
|
void on_read_size(const boost::system::error_code &ec,
|
||||||
|
std::size_t bytes_read);
|
||||||
|
|
||||||
std::shared_ptr<network::LocalSocketMessenger> messenger_;
|
std::shared_ptr<network::LocalSocketMessenger> messenger_;
|
||||||
std::shared_ptr<rpc::PendingCallCache> pending_calls_;
|
std::shared_ptr<rpc::PendingCallCache> pending_calls_;
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_CONTAINER_CONFIGURATION_H_
|
#ifndef ANBOX_CONTAINER_CONFIGURATION_H_
|
||||||
#define ANBOX_CONTAINER_CONFIGURATION_H_
|
#define ANBOX_CONTAINER_CONFIGURATION_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace container {
|
namespace container {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace container {
|
namespace container {
|
||||||
Container::~Container() {
|
Container::~Container() {}
|
||||||
}
|
|
||||||
} // namespace container
|
} // namespace container
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@
|
||||||
|
|
||||||
#include "anbox/container/configuration.h"
|
#include "anbox/container/configuration.h"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace container {
|
namespace container {
|
||||||
|
|
|
||||||
|
|
@ -16,31 +16,28 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/container/lxc_container.h"
|
#include "anbox/container/lxc_container.h"
|
||||||
#include "anbox/utils.h"
|
|
||||||
#include "anbox/config.h"
|
#include "anbox/config.h"
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/utils.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/capability.h>
|
#include <sys/capability.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace container {
|
namespace container {
|
||||||
LxcContainer::LxcContainer() :
|
LxcContainer::LxcContainer() : state_(State::inactive), container_(nullptr) {
|
||||||
state_(State::inactive),
|
|
||||||
container_(nullptr) {
|
|
||||||
utils::ensure_paths({
|
utils::ensure_paths({
|
||||||
config::container_config_path(),
|
config::container_config_path(), config::log_path(),
|
||||||
config::log_path(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,16 +46,17 @@ LxcContainer::~LxcContainer() {
|
||||||
|
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
if (container_)
|
if (container_) lxc_container_put(container_);
|
||||||
lxc_container_put(container_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LxcContainer::start(const Configuration &configuration) {
|
void LxcContainer::start(const Configuration &configuration) {
|
||||||
if (getuid() != 0)
|
if (getuid() != 0)
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("You have to start the container as root"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("You have to start the container as root"));
|
||||||
|
|
||||||
if (container_ && container_->is_running(container_)) {
|
if (container_ && container_->is_running(container_)) {
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Container already started, stopping it now"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Container already started, stopping it now"));
|
||||||
container_->stop(container_);
|
container_->stop(container_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,22 +64,28 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
DEBUG("Containers are stored in %s", config::container_config_path());
|
DEBUG("Containers are stored in %s", config::container_config_path());
|
||||||
|
|
||||||
// Remove container config to be be able to rewrite it
|
// Remove container config to be be able to rewrite it
|
||||||
::unlink(utils::string_format("%s/default/config", config::container_config_path()).c_str());
|
::unlink(utils::string_format("%s/default/config",
|
||||||
|
config::container_config_path())
|
||||||
|
.c_str());
|
||||||
|
|
||||||
container_ = lxc_container_new("default", config::container_config_path().c_str());
|
container_ =
|
||||||
|
lxc_container_new("default", config::container_config_path().c_str());
|
||||||
if (!container_)
|
if (!container_)
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create LXC container instance"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Failed to create LXC container instance"));
|
||||||
|
|
||||||
// If container is still running (for example after a crash) we stop it here to ensure
|
// If container is still running (for example after a crash) we stop it here
|
||||||
|
// to ensure
|
||||||
// its configuration is synchronized.
|
// its configuration is synchronized.
|
||||||
if (container_->is_running(container_))
|
if (container_->is_running(container_)) container_->stop(container_);
|
||||||
container_->stop(container_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We drop all not needed capabilities
|
// We drop all not needed capabilities
|
||||||
set_config_item("lxc.cap.drop", "mac_admin mac_override sys_time sys_module sys_rawio");
|
set_config_item("lxc.cap.drop",
|
||||||
|
"mac_admin mac_override sys_time sys_module sys_rawio");
|
||||||
|
|
||||||
// We can mount proc/sys as rw here as we will run the container unprivileged in the end
|
// We can mount proc/sys as rw here as we will run the container unprivileged
|
||||||
|
// in the end
|
||||||
set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed");
|
set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed");
|
||||||
|
|
||||||
set_config_item("lxc.autodev", "1");
|
set_config_item("lxc.autodev", "1");
|
||||||
|
|
@ -95,7 +99,8 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
// We can't move bind-mounts, so don't use /dev/lxc/
|
// We can't move bind-mounts, so don't use /dev/lxc/
|
||||||
set_config_item("lxc.devttydir", "");
|
set_config_item("lxc.devttydir", "");
|
||||||
|
|
||||||
set_config_item("lxc.environment", "PATH=/system/bin:/system/sbin:/system/xbin");
|
set_config_item("lxc.environment",
|
||||||
|
"PATH=/system/bin:/system/sbin:/system/xbin");
|
||||||
|
|
||||||
set_config_item("lxc.init_cmd", "/anbox-init.sh");
|
set_config_item("lxc.init_cmd", "/anbox-init.sh");
|
||||||
set_config_item("lxc.rootfs.backend", "dir");
|
set_config_item("lxc.rootfs.backend", "dir");
|
||||||
|
|
@ -104,7 +109,9 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
set_config_item("lxc.rootfs", config::rootfs_path());
|
set_config_item("lxc.rootfs", config::rootfs_path());
|
||||||
|
|
||||||
set_config_item("lxc.loglevel", "0");
|
set_config_item("lxc.loglevel", "0");
|
||||||
set_config_item("lxc.logfile", utils::string_format("%s/container.log", config::log_path()).c_str());
|
set_config_item(
|
||||||
|
"lxc.logfile",
|
||||||
|
utils::string_format("%s/container.log", config::log_path()).c_str());
|
||||||
|
|
||||||
set_config_item("lxc.network.type", "veth");
|
set_config_item("lxc.network.type", "veth");
|
||||||
set_config_item("lxc.network.flags", "up");
|
set_config_item("lxc.network.flags", "up");
|
||||||
|
|
@ -115,8 +122,10 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
// which are otherwise forbidden by AppArmor.
|
// which are otherwise forbidden by AppArmor.
|
||||||
set_config_item("lxc.aa_profile", "lxc-container-default-with-nesting");
|
set_config_item("lxc.aa_profile", "lxc-container-default-with-nesting");
|
||||||
#else
|
#else
|
||||||
// FIXME: when using the nested profile we still get various denials from things
|
// FIXME: when using the nested profile we still get various denials from
|
||||||
// Android tries to do but isn't allowed to. We need to look into those and see
|
// things
|
||||||
|
// Android tries to do but isn't allowed to. We need to look into those and
|
||||||
|
// see
|
||||||
// how we can switch back to a confined way of running the container.
|
// how we can switch back to a confined way of running the container.
|
||||||
set_config_item("lxc.aa_profile", "unconfined");
|
set_config_item("lxc.aa_profile", "unconfined");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -124,22 +133,22 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
for (const auto &bind_mount : configuration.bind_mounts) {
|
for (const auto &bind_mount : configuration.bind_mounts) {
|
||||||
std::string create_type = "file";
|
std::string create_type = "file";
|
||||||
|
|
||||||
if (fs::is_directory(bind_mount.first))
|
if (fs::is_directory(bind_mount.first)) create_type = "dir";
|
||||||
create_type = "dir";
|
|
||||||
|
|
||||||
auto target_path = bind_mount.second;
|
auto target_path = bind_mount.second;
|
||||||
// LXC wants target paths relative to the container rootfs so
|
// LXC wants target paths relative to the container rootfs so
|
||||||
// prividing an absolute path doesn't work.
|
// prividing an absolute path doesn't work.
|
||||||
if (utils::string_starts_with(target_path, "/"))
|
if (utils::string_starts_with(target_path, "/")) target_path.erase(0, 1);
|
||||||
target_path.erase(0, 1);
|
|
||||||
|
|
||||||
set_config_item("lxc.mount.entry",
|
set_config_item(
|
||||||
|
"lxc.mount.entry",
|
||||||
utils::string_format("%s %s none bind,create=%s,optional 0 0",
|
utils::string_format("%s %s none bind,create=%s,optional 0 0",
|
||||||
bind_mount.first, target_path, create_type));
|
bind_mount.first, target_path, create_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!container_->save_config(container_, nullptr))
|
if (!container_->save_config(container_, nullptr))
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to save container configuration"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Failed to save container configuration"));
|
||||||
|
|
||||||
if (not container_->start(container_, 0, nullptr))
|
if (not container_->start(container_, 0, nullptr))
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start container"));
|
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start container"));
|
||||||
|
|
@ -151,7 +160,8 @@ void LxcContainer::start(const Configuration &configuration) {
|
||||||
|
|
||||||
void LxcContainer::stop() {
|
void LxcContainer::stop() {
|
||||||
if (not container_ || not container_->is_running(container_))
|
if (not container_ || not container_->is_running(container_))
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Cannot stop container as it is not running"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Cannot stop container as it is not running"));
|
||||||
|
|
||||||
if (not container_->stop(container_))
|
if (not container_->stop(container_))
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container"));
|
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container"));
|
||||||
|
|
@ -161,13 +171,13 @@ void LxcContainer::stop() {
|
||||||
DEBUG("Container successfully stopped");
|
DEBUG("Container successfully stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LxcContainer::set_config_item(const std::string &key, const std::string &value) {
|
void LxcContainer::set_config_item(const std::string &key,
|
||||||
|
const std::string &value) {
|
||||||
if (!container_->set_config_item(container_, key.c_str(), value.c_str()))
|
if (!container_->set_config_item(container_, key.c_str(), value.c_str()))
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to configure LXC container"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Failed to configure LXC container"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Container::State LxcContainer::state() {
|
Container::State LxcContainer::state() { return state_; }
|
||||||
return state_;
|
|
||||||
}
|
|
||||||
} // namespace container
|
} // namespace container
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ namespace container {
|
||||||
class ManagementApiSkeleton;
|
class ManagementApiSkeleton;
|
||||||
class ManagementApiMessageProcessor : public rpc::MessageProcessor {
|
class ManagementApiMessageProcessor : public rpc::MessageProcessor {
|
||||||
public:
|
public:
|
||||||
ManagementApiMessageProcessor(const std::shared_ptr<network::MessageSender> &sender,
|
ManagementApiMessageProcessor(
|
||||||
|
const std::shared_ptr<network::MessageSender> &sender,
|
||||||
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
||||||
const std::shared_ptr<ManagementApiSkeleton> &server);
|
const std::shared_ptr<ManagementApiSkeleton> &server);
|
||||||
~ManagementApiMessageProcessor();
|
~ManagementApiMessageProcessor();
|
||||||
|
|
|
||||||
|
|
@ -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("");
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,14 @@ namespace container {
|
||||||
class Container;
|
class Container;
|
||||||
class ManagementApiSkeleton {
|
class ManagementApiSkeleton {
|
||||||
public:
|
public:
|
||||||
ManagementApiSkeleton(const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
ManagementApiSkeleton(
|
||||||
|
const std::shared_ptr<rpc::PendingCallCache> &pending_calls,
|
||||||
const std::shared_ptr<Container> &container);
|
const std::shared_ptr<Container> &container);
|
||||||
~ManagementApiSkeleton();
|
~ManagementApiSkeleton();
|
||||||
|
|
||||||
void start_container(anbox::protobuf::container::StartContainer const *request,
|
void start_container(
|
||||||
anbox::protobuf::rpc::Void *response,
|
anbox::protobuf::container::StartContainer const *request,
|
||||||
google::protobuf::Closure *done);
|
anbox::protobuf::rpc::Void *response, google::protobuf::Closure *done);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<rpc::PendingCallCache> pending_calls_;
|
std::shared_ptr<rpc::PendingCallCache> pending_calls_;
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/container/management_api_stub.h"
|
#include "anbox/container/management_api_stub.h"
|
||||||
#include "anbox/rpc/channel.h"
|
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/rpc/channel.h"
|
||||||
|
|
||||||
#include "anbox_rpc.pb.h"
|
|
||||||
#include "anbox_container.pb.h"
|
#include "anbox_container.pb.h"
|
||||||
|
#include "anbox_rpc.pb.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace container {
|
namespace container {
|
||||||
ManagementApiStub::ManagementApiStub(const std::shared_ptr<rpc::Channel> &channel) :
|
ManagementApiStub::ManagementApiStub(
|
||||||
channel_(channel) {
|
const std::shared_ptr<rpc::Channel> &channel)
|
||||||
}
|
: channel_(channel) {}
|
||||||
|
|
||||||
ManagementApiStub::~ManagementApiStub() {
|
ManagementApiStub::~ManagementApiStub() {}
|
||||||
}
|
|
||||||
|
|
||||||
void ManagementApiStub::start_container(const Configuration &configuration) {
|
void ManagementApiStub::start_container(const Configuration &configuration) {
|
||||||
auto c = std::make_shared<Request<protobuf::rpc::Void>>();
|
auto c = std::make_shared<Request<protobuf::rpc::Void>>();
|
||||||
|
|
@ -50,18 +49,18 @@ void ManagementApiStub::start_container(const Configuration &configuration) {
|
||||||
start_wait_handle_.expect_result();
|
start_wait_handle_.expect_result();
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_->call_method("start_container",
|
channel_->call_method(
|
||||||
&message,
|
"start_container", &message, c->response.get(),
|
||||||
c->response.get(),
|
google::protobuf::NewCallback(this, &ManagementApiStub::container_started,
|
||||||
google::protobuf::NewCallback(this, &ManagementApiStub::container_started, c.get()));
|
c.get()));
|
||||||
|
|
||||||
start_wait_handle_.wait_for_all();
|
start_wait_handle_.wait_for_all();
|
||||||
|
|
||||||
if (c->response->has_error())
|
if (c->response->has_error()) throw std::runtime_error(c->response->error());
|
||||||
throw std::runtime_error(c->response->error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManagementApiStub::container_started(Request<protobuf::rpc::Void> *request) {
|
void ManagementApiStub::container_started(
|
||||||
|
Request<protobuf::rpc::Void> *request) {
|
||||||
(void)request;
|
(void)request;
|
||||||
DEBUG("");
|
DEBUG("");
|
||||||
start_wait_handle_.result_received();
|
start_wait_handle_.result_received();
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@
|
||||||
#ifndef ANBOX_CONTAINER_SERVICE_H_
|
#ifndef ANBOX_CONTAINER_SERVICE_H_
|
||||||
#define ANBOX_CONTAINER_SERVICE_H_
|
#define ANBOX_CONTAINER_SERVICE_H_
|
||||||
|
|
||||||
#include "anbox/network/published_socket_connector.h"
|
|
||||||
#include "anbox/network/connections.h"
|
|
||||||
#include "anbox/network/socket_connection.h"
|
|
||||||
#include "anbox/network/credentials.h"
|
|
||||||
#include "anbox/container/container.h"
|
|
||||||
#include "anbox/common/dispatcher.h"
|
#include "anbox/common/dispatcher.h"
|
||||||
|
#include "anbox/container/container.h"
|
||||||
|
#include "anbox/network/connections.h"
|
||||||
|
#include "anbox/network/credentials.h"
|
||||||
|
#include "anbox/network/published_socket_connector.h"
|
||||||
|
#include "anbox/network/socket_connection.h"
|
||||||
#include "anbox/runtime.h"
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
|
|
@ -37,7 +37,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int next_id();
|
int next_id();
|
||||||
void new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket);
|
void new_client(std::shared_ptr<
|
||||||
|
boost::asio::local::stream_protocol::socket> const &socket);
|
||||||
|
|
||||||
std::shared_ptr<common::Dispatcher> dispatcher_;
|
std::shared_ptr<common::Dispatcher> dispatcher_;
|
||||||
std::shared_ptr<network::PublishedSocketConnector> connector_;
|
std::shared_ptr<network::PublishedSocketConnector> connector_;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@
|
||||||
#ifndef ANBOX_DAEMON_H_
|
#ifndef ANBOX_DAEMON_H_
|
||||||
#define ANBOX_DAEMON_H_
|
#define ANBOX_DAEMON_H_
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "anbox/do_not_copy_or_move.h"
|
|
||||||
#include "anbox/cli.h"
|
#include "anbox/cli.h"
|
||||||
|
#include "anbox/do_not_copy_or_move.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
class Daemon : public DoNotCopyOrMove {
|
class Daemon : public DoNotCopyOrMove {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_DBUS_SKELETON_SERVICE_H_
|
#ifndef ANBOX_DBUS_SKELETON_SERVICE_H_
|
||||||
#define ANBOX_DBUS_SKELETON_SERVICE_H_
|
#define ANBOX_DBUS_SKELETON_SERVICE_H_
|
||||||
|
|
||||||
#include "anbox/do_not_copy_or_move.h"
|
|
||||||
#include "anbox/application_manager.h"
|
#include "anbox/application_manager.h"
|
||||||
|
#include "anbox/do_not_copy_or_move.h"
|
||||||
|
|
||||||
#include <core/dbus/bus.h>
|
#include <core/dbus/bus.h>
|
||||||
#include <core/dbus/object.h>
|
#include <core/dbus/object.h>
|
||||||
|
|
@ -31,11 +31,12 @@ namespace skeleton {
|
||||||
class ApplicationManager;
|
class ApplicationManager;
|
||||||
class Service : public DoNotCopyOrMove {
|
class Service : public DoNotCopyOrMove {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<Service> create_for_bus(const core::dbus::Bus::Ptr &bus,
|
static std::shared_ptr<Service> create_for_bus(
|
||||||
|
const core::dbus::Bus::Ptr &bus,
|
||||||
const std::shared_ptr<anbox::ApplicationManager> &application_manager);
|
const std::shared_ptr<anbox::ApplicationManager> &application_manager);
|
||||||
|
|
||||||
Service(const core::dbus::Bus::Ptr &bus,
|
Service(
|
||||||
const core::dbus::Service::Ptr& service,
|
const core::dbus::Bus::Ptr &bus, const core::dbus::Service::Ptr &service,
|
||||||
const core::dbus::Object::Ptr &object,
|
const core::dbus::Object::Ptr &object,
|
||||||
const std::shared_ptr<anbox::ApplicationManager> &application_manager);
|
const std::shared_ptr<anbox::ApplicationManager> &application_manager);
|
||||||
~Service();
|
~Service();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ namespace dbus {
|
||||||
namespace stub {
|
namespace stub {
|
||||||
class ApplicationManager : public anbox::ApplicationManager {
|
class ApplicationManager : public anbox::ApplicationManager {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<ApplicationManager> create_for_bus(const core::dbus::Bus::Ptr &bus);
|
static std::shared_ptr<ApplicationManager> create_for_bus(
|
||||||
|
const core::dbus::Bus::Ptr &bus);
|
||||||
|
|
||||||
ApplicationManager(const core::dbus::Bus::Ptr &bus,
|
ApplicationManager(const core::dbus::Bus::Ptr &bus,
|
||||||
const core::dbus::Service::Ptr &service,
|
const core::dbus::Service::Ptr &service,
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,10 @@ namespace anbox {
|
||||||
|
|
||||||
class DeferAction : public DoNotCopyOrMove {
|
class DeferAction : public DoNotCopyOrMove {
|
||||||
public:
|
public:
|
||||||
DeferAction(const std::function<void()> action) :
|
DeferAction(const std::function<void()> action) : action_(action) {}
|
||||||
action_(action) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~DeferAction() {
|
~DeferAction() {
|
||||||
if (action_)
|
if (action_) action_();
|
||||||
action_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
|
|
||||||
class DoNotCopyOrMove
|
class DoNotCopyOrMove {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
|
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
|
||||||
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
|
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
|
||||||
|
|
@ -32,7 +31,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
DoNotCopyOrMove() = default;
|
DoNotCopyOrMove() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,7 @@ bool bindFbo(GLuint* fbo, GLuint tex) {
|
||||||
|
|
||||||
s_gles2.glGenFramebuffers(1, fbo);
|
s_gles2.glGenFramebuffers(1, fbo);
|
||||||
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
|
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
|
||||||
s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER,
|
s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES,
|
||||||
GL_COLOR_ATTACHMENT0_OES,
|
|
||||||
GL_TEXTURE_2D, tex, 0);
|
GL_TEXTURE_2D, tex, 0);
|
||||||
GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = s_gles2.glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
|
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
|
||||||
|
|
@ -77,9 +76,7 @@ bool bindFbo(GLuint* fbo, GLuint tex) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unbindFbo() {
|
void unbindFbo() { s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0); }
|
||||||
s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper class to use a ColorBuffer::Helper context.
|
// Helper class to use a ColorBuffer::Helper context.
|
||||||
// Usage is pretty simple:
|
// Usage is pretty simple:
|
||||||
|
|
@ -102,9 +99,7 @@ public:
|
||||||
|
|
||||||
bool isOk() const { return mHelper != NULL; }
|
bool isOk() const { return mHelper != NULL; }
|
||||||
|
|
||||||
~ScopedHelperContext() {
|
~ScopedHelperContext() { release(); }
|
||||||
release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void release() {
|
void release() {
|
||||||
if (mHelper) {
|
if (mHelper) {
|
||||||
|
|
@ -112,6 +107,7 @@ public:
|
||||||
mHelper = NULL;
|
mHelper = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ColorBuffer::Helper* mHelper;
|
ColorBuffer::Helper* mHelper;
|
||||||
};
|
};
|
||||||
|
|
@ -119,12 +115,9 @@ private:
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
|
ColorBuffer* ColorBuffer::create(EGLDisplay p_display, int p_width,
|
||||||
int p_width,
|
int p_height, GLenum p_internalFormat,
|
||||||
int p_height,
|
bool has_eglimage_texture_2d, Helper* helper) {
|
||||||
GLenum p_internalFormat,
|
|
||||||
bool has_eglimage_texture_2d,
|
|
||||||
Helper* helper) {
|
|
||||||
GLenum texInternalFormat = 0;
|
GLenum texInternalFormat = 0;
|
||||||
|
|
||||||
switch (p_internalFormat) {
|
switch (p_internalFormat) {
|
||||||
|
|
@ -157,15 +150,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
|
||||||
int nComp = (texInternalFormat == GL_RGB ? 3 : 4);
|
int nComp = (texInternalFormat == GL_RGB ? 3 : 4);
|
||||||
|
|
||||||
char* zBuff = static_cast<char*>(::calloc(nComp * p_width * p_height, 1));
|
char* zBuff = static_cast<char*>(::calloc(nComp * p_width * p_height, 1));
|
||||||
s_gles2.glTexImage2D(GL_TEXTURE_2D,
|
s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, texInternalFormat, p_width, p_height,
|
||||||
0,
|
0, texInternalFormat, GL_UNSIGNED_BYTE, zBuff);
|
||||||
texInternalFormat,
|
|
||||||
p_width,
|
|
||||||
p_height,
|
|
||||||
0,
|
|
||||||
texInternalFormat,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
zBuff);
|
|
||||||
::free(zBuff);
|
::free(zBuff);
|
||||||
|
|
||||||
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
@ -178,15 +164,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
|
||||||
//
|
//
|
||||||
s_gles2.glGenTextures(1, &cb->m_blitTex);
|
s_gles2.glGenTextures(1, &cb->m_blitTex);
|
||||||
s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
|
s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_blitTex);
|
||||||
s_gles2.glTexImage2D(GL_TEXTURE_2D,
|
s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, texInternalFormat, p_width, p_height,
|
||||||
0,
|
0, texInternalFormat, GL_UNSIGNED_BYTE, NULL);
|
||||||
texInternalFormat,
|
|
||||||
p_width,
|
|
||||||
p_height,
|
|
||||||
0,
|
|
||||||
texInternalFormat,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
@ -199,18 +178,12 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
|
||||||
|
|
||||||
if (has_eglimage_texture_2d) {
|
if (has_eglimage_texture_2d) {
|
||||||
cb->m_eglImage = s_egl.eglCreateImageKHR(
|
cb->m_eglImage = s_egl.eglCreateImageKHR(
|
||||||
p_display,
|
p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
|
||||||
s_egl.eglGetCurrentContext(),
|
(EGLClientBuffer)SafePointerFromUInt(cb->m_tex), NULL);
|
||||||
EGL_GL_TEXTURE_2D_KHR,
|
|
||||||
(EGLClientBuffer)SafePointerFromUInt(cb->m_tex),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
|
cb->m_blitEGLImage = s_egl.eglCreateImageKHR(
|
||||||
p_display,
|
p_display, s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
|
||||||
s_egl.eglGetCurrentContext(),
|
(EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex), NULL);
|
||||||
EGL_GL_TEXTURE_2D_KHR,
|
|
||||||
(EGLClientBuffer)SafePointerFromUInt(cb->m_blitTex),
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cb->m_resizer = new TextureResize(p_width, p_height);
|
cb->m_resizer = new TextureResize(p_width, p_height);
|
||||||
|
|
@ -218,8 +191,8 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display,
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper) :
|
ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper)
|
||||||
m_tex(0),
|
: m_tex(0),
|
||||||
m_blitTex(0),
|
m_blitTex(0),
|
||||||
m_eglImage(NULL),
|
m_eglImage(NULL),
|
||||||
m_blitEGLImage(NULL),
|
m_blitEGLImage(NULL),
|
||||||
|
|
@ -248,13 +221,8 @@ ColorBuffer::~ColorBuffer() {
|
||||||
delete m_resizer;
|
delete m_resizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBuffer::readPixels(int x,
|
void ColorBuffer::readPixels(int x, int y, int width, int height,
|
||||||
int y,
|
GLenum p_format, GLenum p_type, void* pixels) {
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GLenum p_format,
|
|
||||||
GLenum p_type,
|
|
||||||
void* pixels) {
|
|
||||||
ScopedHelperContext context(m_helper);
|
ScopedHelperContext context(m_helper);
|
||||||
if (!context.isOk()) {
|
if (!context.isOk()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -266,13 +234,8 @@ void ColorBuffer::readPixels(int x,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBuffer::subUpdate(int x,
|
void ColorBuffer::subUpdate(int x, int y, int width, int height,
|
||||||
int y,
|
GLenum p_format, GLenum p_type, void* pixels) {
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GLenum p_format,
|
|
||||||
GLenum p_type,
|
|
||||||
void* pixels) {
|
|
||||||
ScopedHelperContext context(m_helper);
|
ScopedHelperContext context(m_helper);
|
||||||
if (!context.isOk()) {
|
if (!context.isOk()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -280,12 +243,11 @@ void ColorBuffer::subUpdate(int x,
|
||||||
|
|
||||||
s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
|
s_gles2.glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||||
s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
s_gles2.glTexSubImage2D(
|
s_gles2.glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, p_format,
|
||||||
GL_TEXTURE_2D, 0, x, y, width, height, p_format, p_type, pixels);
|
p_type, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ColorBuffer::blitFromCurrentReadBuffer()
|
bool ColorBuffer::blitFromCurrentReadBuffer() {
|
||||||
{
|
|
||||||
RenderThreadInfo* tInfo = RenderThreadInfo::get();
|
RenderThreadInfo* tInfo = RenderThreadInfo::get();
|
||||||
if (!tInfo->currContext.Ptr()) {
|
if (!tInfo->currContext.Ptr()) {
|
||||||
// no Current context
|
// no Current context
|
||||||
|
|
@ -302,18 +264,17 @@ bool ColorBuffer::blitFromCurrentReadBuffer()
|
||||||
s_gles2.glGenTextures(1, &tmpTex);
|
s_gles2.glGenTextures(1, &tmpTex);
|
||||||
s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
|
s_gles2.glBindTexture(GL_TEXTURE_2D, tmpTex);
|
||||||
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
|
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
|
||||||
s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
|
s_gles2.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
|
||||||
m_width, m_height);
|
m_height);
|
||||||
s_gles2.glDeleteTextures(1, &tmpTex);
|
s_gles2.glDeleteTextures(1, &tmpTex);
|
||||||
s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
|
s_gles2.glBindTexture(GL_TEXTURE_2D, currTexBind);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
|
s_gles1.glGetIntegerv(GL_TEXTURE_BINDING_2D, &currTexBind);
|
||||||
s_gles1.glGenTextures(1, &tmpTex);
|
s_gles1.glGenTextures(1, &tmpTex);
|
||||||
s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
|
s_gles1.glBindTexture(GL_TEXTURE_2D, tmpTex);
|
||||||
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
|
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_blitEGLImage);
|
||||||
s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
|
s_gles1.glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width,
|
||||||
m_width, m_height);
|
m_height);
|
||||||
s_gles1.glDeleteTextures(1, &tmpTex);
|
s_gles1.glDeleteTextures(1, &tmpTex);
|
||||||
s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
|
s_gles1.glBindTexture(GL_TEXTURE_2D, currTexBind);
|
||||||
}
|
}
|
||||||
|
|
@ -328,7 +289,9 @@ bool ColorBuffer::blitFromCurrentReadBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save current viewport and match it to the current colorbuffer size.
|
// Save current viewport and match it to the current colorbuffer size.
|
||||||
GLint vport[4] = { 0, };
|
GLint vport[4] = {
|
||||||
|
0,
|
||||||
|
};
|
||||||
s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
|
s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
|
||||||
s_gles2.glViewport(0, 0, m_width, m_height);
|
s_gles2.glViewport(0, 0, m_width, m_height);
|
||||||
|
|
||||||
|
|
@ -352,8 +315,7 @@ bool ColorBuffer::bindToTexture() {
|
||||||
}
|
}
|
||||||
if (tInfo->currContext->isGL2()) {
|
if (tInfo->currContext->isGL2()) {
|
||||||
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
|
s_gles2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
|
s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -368,10 +330,11 @@ bool ColorBuffer::bindToRenderbuffer() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (tInfo->currContext->isGL2()) {
|
if (tInfo->currContext->isGL2()) {
|
||||||
s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage);
|
s_gles2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
|
||||||
}
|
m_eglImage);
|
||||||
else {
|
} else {
|
||||||
s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage);
|
s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES,
|
||||||
|
m_eglImage);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -382,8 +345,8 @@ void ColorBuffer::readback(unsigned char* img) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bindFbo(&m_fbo, m_tex)) {
|
if (bindFbo(&m_fbo, m_tex)) {
|
||||||
s_gles2.glReadPixels(
|
s_gles2.glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, img);
|
img);
|
||||||
unbindFbo();
|
unbindFbo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,12 +76,9 @@ public:
|
||||||
// |has_eglimage_texture_2d| should be true iff the display supports
|
// |has_eglimage_texture_2d| should be true iff the display supports
|
||||||
// the EGL_KHR_gl_texture_2D_image extension.
|
// the EGL_KHR_gl_texture_2D_image extension.
|
||||||
// Returns NULL on failure.
|
// Returns NULL on failure.
|
||||||
static ColorBuffer* create(EGLDisplay p_display,
|
static ColorBuffer* create(EGLDisplay p_display, int p_width, int p_height,
|
||||||
int p_width,
|
|
||||||
int p_height,
|
|
||||||
GLenum p_internalFormat,
|
GLenum p_internalFormat,
|
||||||
bool has_eglimage_texture_2d,
|
bool has_eglimage_texture_2d, Helper* helper);
|
||||||
Helper* helper);
|
|
||||||
|
|
||||||
// Destructor.
|
// Destructor.
|
||||||
~ColorBuffer();
|
~ColorBuffer();
|
||||||
|
|
@ -91,22 +88,12 @@ public:
|
||||||
GLuint getHeight() const { return m_height; }
|
GLuint getHeight() const { return m_height; }
|
||||||
|
|
||||||
// Read the ColorBuffer instance's pixel values into host memory.
|
// Read the ColorBuffer instance's pixel values into host memory.
|
||||||
void readPixels(int x,
|
void readPixels(int x, int y, int width, int height, GLenum p_format,
|
||||||
int y,
|
GLenum p_type, void* pixels);
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GLenum p_format,
|
|
||||||
GLenum p_type,
|
|
||||||
void *pixels);
|
|
||||||
|
|
||||||
// Update the ColorBuffer instance's pixel values from host memory.
|
// Update the ColorBuffer instance's pixel values from host memory.
|
||||||
void subUpdate(int x,
|
void subUpdate(int x, int y, int width, int height, GLenum p_format,
|
||||||
int y,
|
GLenum p_type, void* pixels);
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GLenum p_format,
|
|
||||||
GLenum p_type,
|
|
||||||
void *pixels);
|
|
||||||
|
|
||||||
// Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's
|
// Bind the current context's EGL_TEXTURE_2D texture to this ColorBuffer's
|
||||||
// EGLImage. This is intended to implement glEGLImageTargetTexture2DOES()
|
// EGLImage. This is intended to implement glEGLImageTargetTexture2DOES()
|
||||||
|
|
@ -128,6 +115,7 @@ public:
|
||||||
void readback(unsigned char* img);
|
void readback(unsigned char* img);
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ColorBuffer(); // no default constructor.
|
ColorBuffer(); // no default constructor.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,14 @@ std::shared_ptr<DisplayManager> display_mgr;
|
||||||
|
|
||||||
class NullDisplayManager : public DisplayManager {
|
class NullDisplayManager : public DisplayManager {
|
||||||
public:
|
public:
|
||||||
DisplayInfo display_info() const override {
|
DisplayInfo display_info() const override { return {1280, 720}; }
|
||||||
return {1280, 720};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayManager::~DisplayManager() {
|
DisplayManager::~DisplayManager() {}
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<DisplayManager> DisplayManager::get() {
|
std::shared_ptr<DisplayManager> DisplayManager::get() {
|
||||||
if (!display_mgr)
|
if (!display_mgr) display_mgr = std::make_shared<NullDisplayManager>();
|
||||||
display_mgr = std::make_shared<NullDisplayManager>();
|
|
||||||
return display_mgr;
|
return display_mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,22 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "ReadBuffer.h"
|
#include "ReadBuffer.h"
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
#include "ErrorLog.h"
|
#include "ErrorLog.h"
|
||||||
|
|
||||||
ReadBuffer::ReadBuffer(size_t bufsize)
|
ReadBuffer::ReadBuffer(size_t bufsize) {
|
||||||
{
|
|
||||||
m_size = bufsize;
|
m_size = bufsize;
|
||||||
m_buf = (unsigned char*)malloc(m_size * sizeof(unsigned char));
|
m_buf = (unsigned char*)malloc(m_size * sizeof(unsigned char));
|
||||||
m_validData = 0;
|
m_validData = 0;
|
||||||
m_readPtr = m_buf;
|
m_readPtr = m_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadBuffer::~ReadBuffer()
|
ReadBuffer::~ReadBuffer() { free(m_buf); }
|
||||||
{
|
|
||||||
free(m_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ReadBuffer::getData(IOStream *stream)
|
int ReadBuffer::getData(IOStream* stream) {
|
||||||
{
|
if (stream == NULL) return -1;
|
||||||
if(stream == NULL)
|
|
||||||
return -1;
|
|
||||||
if ((m_validData > 0) && (m_readPtr > m_buf)) {
|
if ((m_validData > 0) && (m_readPtr > m_buf)) {
|
||||||
memmove(m_buf, m_readPtr, m_validData);
|
memmove(m_buf, m_readPtr, m_validData);
|
||||||
}
|
}
|
||||||
|
|
@ -66,8 +60,7 @@ int ReadBuffer::getData(IOStream *stream)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBuffer::consume(size_t amount)
|
void ReadBuffer::consume(size_t amount) {
|
||||||
{
|
|
||||||
assert(amount <= m_validData);
|
assert(amount <= m_validData);
|
||||||
m_validData -= amount;
|
m_validData -= amount;
|
||||||
m_readPtr += amount;
|
m_readPtr += amount;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ public:
|
||||||
~ReadBuffer();
|
~ReadBuffer();
|
||||||
int getData(IOStream *stream); // get fresh data from the stream
|
int getData(IOStream *stream); // get fresh data from the stream
|
||||||
unsigned char *buf() { return m_readPtr; } // return the next read location
|
unsigned char *buf() { return m_readPtr; } // return the next read location
|
||||||
size_t validData() { return m_validData; } // return the amount of valid data in readptr
|
size_t validData() {
|
||||||
|
return m_validData;
|
||||||
|
} // return the amount of valid data in readptr
|
||||||
void consume(size_t amount); // notify that 'amount' data has been consumed;
|
void consume(size_t amount); // notify that 'amount' data has been consumed;
|
||||||
private:
|
private:
|
||||||
unsigned char *m_buf;
|
unsigned char *m_buf;
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,7 @@ static RenderWindow* s_renderWindow = NULL;
|
||||||
static IOStream* createRenderThread(int p_stream_buffer_size,
|
static IOStream* createRenderThread(int p_stream_buffer_size,
|
||||||
unsigned int clientFlags);
|
unsigned int clientFlags);
|
||||||
|
|
||||||
RENDER_APICALL int RENDER_APIENTRY initLibrary(void)
|
RENDER_APICALL int RENDER_APIENTRY initLibrary(void) {
|
||||||
{
|
|
||||||
//
|
//
|
||||||
// Load EGL Plugin
|
// Load EGL Plugin
|
||||||
//
|
//
|
||||||
|
|
@ -91,7 +90,8 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
|
||||||
// For now, this feature is disabled entirely for the following
|
// For now, this feature is disabled entirely for the following
|
||||||
// reasons:
|
// reasons:
|
||||||
//
|
//
|
||||||
// - It must be disabled on Windows at all times, otherwise the main window becomes
|
// - It must be disabled on Windows at all times, otherwise the main window
|
||||||
|
// becomes
|
||||||
// unresponsive after a few seconds of user interaction (e.g. trying to
|
// unresponsive after a few seconds of user interaction (e.g. trying to
|
||||||
// move it over the desktop). Probably due to the subtle issues around
|
// move it over the desktop). Probably due to the subtle issues around
|
||||||
// input on this platform (input-queue is global, message-queue is
|
// input on this platform (input-queue is global, message-queue is
|
||||||
|
|
@ -100,11 +100,13 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
|
||||||
//
|
//
|
||||||
// - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption
|
// - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption
|
||||||
// issues with the GL state of the main window when using the SDL UI.
|
// issues with the GL state of the main window when using the SDL UI.
|
||||||
// After the switch to Qt, this is no longer necessary and may actually cause
|
// After the switch to Qt, this is no longer necessary and may actually
|
||||||
|
// cause
|
||||||
// undesired interactions between the UI thread and the RenderWindow thread:
|
// undesired interactions between the UI thread and the RenderWindow thread:
|
||||||
// for example, in a multi-monitor setup the context might be recreated when
|
// for example, in a multi-monitor setup the context might be recreated when
|
||||||
// dragging the window between monitors, triggering a Qt-specific callback
|
// dragging the window between monitors, triggering a Qt-specific callback
|
||||||
// in the context of RenderWindow thread, which will become blocked on the UI
|
// in the context of RenderWindow thread, which will become blocked on the
|
||||||
|
// UI
|
||||||
// thread, which may in turn be blocked on something else.
|
// thread, which may in turn be blocked on something else.
|
||||||
bool kUseThread = false;
|
bool kUseThread = false;
|
||||||
|
|
||||||
|
|
@ -137,8 +139,7 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(
|
RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(const char** vendor,
|
||||||
const char** vendor,
|
|
||||||
const char** renderer,
|
const char** renderer,
|
||||||
const char** version) {
|
const char** version) {
|
||||||
if (s_renderWindow &&
|
if (s_renderWindow &&
|
||||||
|
|
@ -148,8 +149,7 @@ RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(
|
||||||
*vendor = *renderer = *version = NULL;
|
*vendor = *renderer = *version = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void)
|
RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void) {
|
||||||
{
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
// open a dummy connection to the renderer to make it
|
// open a dummy connection to the renderer to make it
|
||||||
|
|
@ -176,31 +176,22 @@ RENDER_APICALL int RENDER_APIENTRY stopOpenGLRenderer(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_APICALL bool RENDER_APIENTRY showOpenGLSubwindow(
|
RENDER_APICALL bool RENDER_APIENTRY
|
||||||
FBNativeWindowType window_id,
|
showOpenGLSubwindow(FBNativeWindowType window_id, int wx, int wy, int ww,
|
||||||
int wx,
|
int wh, int fbw, int fbh, float dpr, float zRot) {
|
||||||
int wy,
|
|
||||||
int ww,
|
|
||||||
int wh,
|
|
||||||
int fbw,
|
|
||||||
int fbh,
|
|
||||||
float dpr,
|
|
||||||
float zRot)
|
|
||||||
{
|
|
||||||
RenderWindow* window = s_renderWindow;
|
RenderWindow* window = s_renderWindow;
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
return window->setupSubWindow(window_id,wx,wy,ww,wh,fbw,fbh,dpr,zRot);
|
return window->setupSubWindow(window_id, wx, wy, ww, wh, fbw, fbh, dpr,
|
||||||
|
zRot);
|
||||||
}
|
}
|
||||||
// XXX: should be implemented by sending the renderer process
|
// XXX: should be implemented by sending the renderer process
|
||||||
// a request
|
// a request
|
||||||
ERR("%s not implemented for separate renderer process !!!\n",
|
ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__);
|
||||||
__FUNCTION__);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
|
RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void) {
|
||||||
{
|
|
||||||
RenderWindow* window = s_renderWindow;
|
RenderWindow* window = s_renderWindow;
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
|
|
@ -209,8 +200,7 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
|
||||||
|
|
||||||
// XXX: should be implemented by sending the renderer process
|
// XXX: should be implemented by sending the renderer process
|
||||||
// a request
|
// a request
|
||||||
ERR("%s not implemented for separate renderer process !!!\n",
|
ERR("%s not implemented for separate renderer process !!!\n", __FUNCTION__);
|
||||||
__FUNCTION__);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,8 +208,8 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
|
||||||
|
|
||||||
int gRendererStreamMode = DEFAULT_STREAM_MODE;
|
int gRendererStreamMode = DEFAULT_STREAM_MODE;
|
||||||
|
|
||||||
IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
|
IOStream* createRenderThread(int p_stream_buffer_size,
|
||||||
{
|
unsigned int clientFlags) {
|
||||||
SocketStream* stream = NULL;
|
SocketStream* stream = NULL;
|
||||||
|
|
||||||
if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) {
|
if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@
|
||||||
#ifndef _LIBRENDER_RENDER_CONTEXT_H
|
#ifndef _LIBRENDER_RENDER_CONTEXT_H
|
||||||
#define _LIBRENDER_RENDER_CONTEXT_H
|
#define _LIBRENDER_RENDER_CONTEXT_H
|
||||||
|
|
||||||
#include "emugl/common/smart_ptr.h"
|
|
||||||
#include "GLDecoderContextData.h"
|
#include "GLDecoderContextData.h"
|
||||||
|
#include "emugl/common/smart_ptr.h"
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
|
|
@ -32,10 +32,8 @@ public:
|
||||||
// |sharedContext| is either EGL_NO_CONTEXT of a host EGLContext handle.
|
// |sharedContext| is either EGL_NO_CONTEXT of a host EGLContext handle.
|
||||||
// |isGl2| is true iff the new context will be used with GLESv2, or
|
// |isGl2| is true iff the new context will be used with GLESv2, or
|
||||||
// GLESv1 otherwise.
|
// GLESv1 otherwise.
|
||||||
static RenderContext *create(EGLDisplay display,
|
static RenderContext* create(EGLDisplay display, EGLConfig config,
|
||||||
EGLConfig config,
|
EGLContext sharedContext, bool isGL2 = false);
|
||||||
EGLContext sharedContext,
|
|
||||||
bool isGL2 = false);
|
|
||||||
|
|
||||||
// Destructor.
|
// Destructor.
|
||||||
~RenderContext();
|
~RenderContext();
|
||||||
|
|
@ -53,9 +51,7 @@ public:
|
||||||
private:
|
private:
|
||||||
RenderContext();
|
RenderContext();
|
||||||
|
|
||||||
RenderContext(EGLDisplay display,
|
RenderContext(EGLDisplay display, EGLContext context, bool isGl2);
|
||||||
EGLContext context,
|
|
||||||
bool isGl2);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EGLDisplay mDisplay;
|
EGLDisplay mDisplay;
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
#include "RenderControl.h"
|
#include "RenderControl.h"
|
||||||
|
|
||||||
#include "DispatchTables.h"
|
|
||||||
#include "RendererConfig.h"
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "RenderThreadInfo.h"
|
|
||||||
#include "ChecksumCalculatorThreadInfo.h"
|
#include "ChecksumCalculatorThreadInfo.h"
|
||||||
|
#include "DispatchTables.h"
|
||||||
#include "DisplayManager.h"
|
#include "DisplayManager.h"
|
||||||
|
#include "RenderThreadInfo.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "RendererConfig.h"
|
||||||
|
|
||||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||||
|
|
||||||
|
|
@ -33,18 +33,14 @@
|
||||||
static const GLint rendererVersion = 1;
|
static const GLint rendererVersion = 1;
|
||||||
static std::shared_ptr<anbox::graphics::LayerComposer> composer;
|
static std::shared_ptr<anbox::graphics::LayerComposer> composer;
|
||||||
|
|
||||||
void registerLayerComposer(const std::shared_ptr<anbox::graphics::LayerComposer> &c)
|
void registerLayerComposer(
|
||||||
{
|
const std::shared_ptr<anbox::graphics::LayerComposer> &c) {
|
||||||
composer = c;
|
composer = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLint rcGetRendererVersion()
|
static GLint rcGetRendererVersion() { return rendererVersion; }
|
||||||
{
|
|
||||||
return rendererVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor)
|
static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return EGL_FALSE;
|
return EGL_FALSE;
|
||||||
|
|
@ -55,8 +51,7 @@ static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor)
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
static EGLint rcQueryEGLString(EGLenum name, void *buffer, EGLint bufferSize) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -76,8 +71,7 @@ static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) {
|
||||||
{
|
|
||||||
RenderThreadInfo *tInfo = RenderThreadInfo::get();
|
RenderThreadInfo *tInfo = RenderThreadInfo::get();
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
|
|
@ -88,8 +82,7 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
||||||
else
|
else
|
||||||
str = reinterpret_cast<const char *>(s_gles1.glGetString(name));
|
str = reinterpret_cast<const char *>(s_gles1.glGetString(name));
|
||||||
|
|
||||||
if (str)
|
if (str) result += str;
|
||||||
result += str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're forcing version 2.0 no matter what the host provides as
|
// We're forcing version 2.0 no matter what the host provides as
|
||||||
|
|
@ -110,8 +103,7 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
||||||
|
|
||||||
for (const auto &extension : unsupported_extensions) {
|
for (const auto &extension : unsupported_extensions) {
|
||||||
size_t start_pos = approved_extensions.find(extension);
|
size_t start_pos = approved_extensions.find(extension);
|
||||||
if(start_pos == std::string::npos)
|
if (start_pos == std::string::npos) continue;
|
||||||
continue;
|
|
||||||
approved_extensions.replace(start_pos, extension.length(), "");
|
approved_extensions.replace(start_pos, extension.length(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,15 +112,13 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize)
|
||||||
|
|
||||||
int nextBufferSize = result.size() + 1;
|
int nextBufferSize = result.size() + 1;
|
||||||
|
|
||||||
if (!buffer || nextBufferSize > bufferSize)
|
if (!buffer || nextBufferSize > bufferSize) return -nextBufferSize;
|
||||||
return -nextBufferSize;
|
|
||||||
|
|
||||||
snprintf(static_cast<char *>(buffer), nextBufferSize, "%s", result.c_str());
|
snprintf(static_cast<char *>(buffer), nextBufferSize, "%s", result.c_str());
|
||||||
return nextBufferSize;
|
return nextBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcGetNumConfigs(uint32_t* p_numAttribs)
|
static EGLint rcGetNumConfigs(uint32_t *p_numAttribs) {
|
||||||
{
|
|
||||||
int numConfigs = 0, numAttribs = 0;
|
int numConfigs = 0, numAttribs = 0;
|
||||||
|
|
||||||
Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
|
Renderer::get()->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
|
||||||
|
|
@ -138,28 +128,23 @@ static EGLint rcGetNumConfigs(uint32_t* p_numAttribs)
|
||||||
return numConfigs;
|
return numConfigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer)
|
static EGLint rcGetConfigs(uint32_t bufSize, GLuint *buffer) {
|
||||||
{
|
|
||||||
GLuint bufferSize = (GLuint)bufSize;
|
GLuint bufferSize = (GLuint)bufSize;
|
||||||
return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer);
|
return Renderer::get()->getConfigs()->packConfigs(bufferSize, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcChooseConfig(EGLint *attribs,
|
static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size,
|
||||||
uint32_t attribs_size,
|
uint32_t *configs, uint32_t configs_size) {
|
||||||
uint32_t *configs,
|
|
||||||
uint32_t configs_size)
|
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb || attribs_size == 0) {
|
if (!fb || attribs_size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fb->getConfigs()->chooseConfig(
|
return fb->getConfigs()->chooseConfig(attribs, (EGLint *)configs,
|
||||||
attribs, (EGLint*)configs, (EGLint)configs_size);
|
(EGLint)configs_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcGetFBParam(EGLint param)
|
static EGLint rcGetFBParam(EGLint param) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -196,9 +181,8 @@ static EGLint rcGetFBParam(EGLint param)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rcCreateContext(uint32_t config,
|
static uint32_t rcCreateContext(uint32_t config, uint32_t share,
|
||||||
uint32_t share, uint32_t glVersion)
|
uint32_t glVersion) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -206,12 +190,12 @@ static uint32_t rcCreateContext(uint32_t config,
|
||||||
|
|
||||||
// To make it consistent with the guest, create GLES2 context when GL
|
// To make it consistent with the guest, create GLES2 context when GL
|
||||||
// version==2 or 3
|
// version==2 or 3
|
||||||
HandleType ret = fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3);
|
HandleType ret =
|
||||||
|
fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcDestroyContext(uint32_t context)
|
static void rcDestroyContext(uint32_t context) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -220,9 +204,8 @@ static void rcDestroyContext(uint32_t context)
|
||||||
fb->DestroyRenderContext(context);
|
fb->DestroyRenderContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rcCreateWindowSurface(uint32_t config,
|
static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width,
|
||||||
uint32_t width, uint32_t height)
|
uint32_t height) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -231,8 +214,7 @@ static uint32_t rcCreateWindowSurface(uint32_t config,
|
||||||
return fb->createWindowSurface(config, width, height);
|
return fb->createWindowSurface(config, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcDestroyWindowSurface(uint32_t windowSurface)
|
static void rcDestroyWindowSurface(uint32_t windowSurface) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -241,9 +223,8 @@ static void rcDestroyWindowSurface(uint32_t windowSurface)
|
||||||
fb->DestroyWindowSurface(windowSurface);
|
fb->DestroyWindowSurface(windowSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rcCreateColorBuffer(uint32_t width,
|
static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height,
|
||||||
uint32_t height, GLenum internalFormat)
|
GLenum internalFormat) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -252,8 +233,7 @@ static uint32_t rcCreateColorBuffer(uint32_t width,
|
||||||
return fb->createColorBuffer(width, height, internalFormat);
|
return fb->createColorBuffer(width, height, internalFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcOpenColorBuffer2(uint32_t colorbuffer)
|
static int rcOpenColorBuffer2(uint32_t colorbuffer) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -263,13 +243,11 @@ static int rcOpenColorBuffer2(uint32_t colorbuffer)
|
||||||
|
|
||||||
// Deprecated, kept for compatibility with old system images only.
|
// Deprecated, kept for compatibility with old system images only.
|
||||||
// Use rcOpenColorBuffer2 instead.
|
// Use rcOpenColorBuffer2 instead.
|
||||||
static void rcOpenColorBuffer(uint32_t colorbuffer)
|
static void rcOpenColorBuffer(uint32_t colorbuffer) {
|
||||||
{
|
|
||||||
(void)rcOpenColorBuffer2(colorbuffer);
|
(void)rcOpenColorBuffer2(colorbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcCloseColorBuffer(uint32_t colorbuffer)
|
static void rcCloseColorBuffer(uint32_t colorbuffer) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -277,8 +255,7 @@ static void rcCloseColorBuffer(uint32_t colorbuffer)
|
||||||
fb->closeColorBuffer(colorbuffer);
|
fb->closeColorBuffer(colorbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcFlushWindowColorBuffer(uint32_t windowSurface)
|
static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -290,8 +267,7 @@ static int rcFlushWindowColorBuffer(uint32_t windowSurface)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcSetWindowColorBuffer(uint32_t windowSurface,
|
static void rcSetWindowColorBuffer(uint32_t windowSurface,
|
||||||
uint32_t colorBuffer)
|
uint32_t colorBuffer) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -299,9 +275,8 @@ static void rcSetWindowColorBuffer(uint32_t windowSurface,
|
||||||
fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer);
|
fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcMakeCurrent(uint32_t context,
|
static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf,
|
||||||
uint32_t drawSurf, uint32_t readSurf)
|
uint32_t readSurf) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return EGL_FALSE;
|
return EGL_FALSE;
|
||||||
|
|
@ -312,18 +287,13 @@ static EGLint rcMakeCurrent(uint32_t context,
|
||||||
return (ret ? EGL_TRUE : EGL_FALSE);
|
return (ret ? EGL_TRUE : EGL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcFBPost(uint32_t colorBuffer)
|
static void rcFBPost(uint32_t colorBuffer) { WARNING("Not implemented"); }
|
||||||
{
|
|
||||||
WARNING("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rcFBSetSwapInterval(EGLint interval)
|
static void rcFBSetSwapInterval(EGLint interval) {
|
||||||
{
|
|
||||||
// XXX: TBD - should be implemented
|
// XXX: TBD - should be implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcBindTexture(uint32_t colorBuffer)
|
static void rcBindTexture(uint32_t colorBuffer) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -332,8 +302,7 @@ static void rcBindTexture(uint32_t colorBuffer)
|
||||||
fb->bindColorBufferToTexture(colorBuffer);
|
fb->bindColorBufferToTexture(colorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcBindRenderbuffer(uint32_t colorBuffer)
|
static void rcBindRenderbuffer(uint32_t colorBuffer) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -342,18 +311,15 @@ static void rcBindRenderbuffer(uint32_t colorBuffer)
|
||||||
fb->bindColorBufferToRenderbuffer(colorBuffer);
|
fb->bindColorBufferToRenderbuffer(colorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer,
|
static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount,
|
||||||
EGLint postCount, int forRead)
|
int forRead) {
|
||||||
{
|
|
||||||
// XXX: TBD - should be implemented
|
// XXX: TBD - should be implemented
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcReadColorBuffer(uint32_t colorBuffer,
|
static void rcReadColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
|
||||||
GLint x, GLint y,
|
GLint width, GLint height, GLenum format,
|
||||||
GLint width, GLint height,
|
GLenum type, void *pixels) {
|
||||||
GLenum format, GLenum type, void* pixels)
|
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -362,11 +328,9 @@ static void rcReadColorBuffer(uint32_t colorBuffer,
|
||||||
fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
|
fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcUpdateColorBuffer(uint32_t colorBuffer,
|
static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
|
||||||
GLint x, GLint y,
|
GLint width, GLint height, GLenum format,
|
||||||
GLint width, GLint height,
|
GLenum type, void *pixels) {
|
||||||
GLenum format, GLenum type, void* pixels)
|
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -376,8 +340,8 @@ static int rcUpdateColorBuffer(uint32_t colorBuffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer)
|
static uint32_t rcCreateClientImage(uint32_t context, EGLenum target,
|
||||||
{
|
GLuint buffer) {
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -386,8 +350,7 @@ static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buf
|
||||||
return fb->createClientImage(context, target, buffer);
|
return fb->createClientImage(context, target, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcDestroyClientImage(uint32_t image)
|
static int rcDestroyClientImage(uint32_t image) {
|
||||||
{
|
|
||||||
Renderer *fb = Renderer::get();
|
Renderer *fb = Renderer::get();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -400,9 +363,7 @@ static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) {
|
||||||
ChecksumCalculatorThreadInfo::setVersion(protocol);
|
ChecksumCalculatorThreadInfo::setVersion(protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rcGetNumDisplays() {
|
int rcGetNumDisplays() { return 1; }
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rcGetDisplayWidth(uint32_t display_id) {
|
int rcGetDisplayWidth(uint32_t display_id) {
|
||||||
printf("%s: display_id=%d\n", __func__, display_id);
|
printf("%s: display_id=%d\n", __func__, display_id);
|
||||||
|
|
@ -442,27 +403,23 @@ void rcPostLayer(const char *name, uint32_t color_buffer,
|
||||||
int32_t sourceCropLeft, int32_t sourceCropTop,
|
int32_t sourceCropLeft, int32_t sourceCropTop,
|
||||||
int32_t sourceCropRight, int32_t sourceCropBottom,
|
int32_t sourceCropRight, int32_t sourceCropBottom,
|
||||||
int32_t displayFrameLeft, int32_t displayFrameTop,
|
int32_t displayFrameLeft, int32_t displayFrameTop,
|
||||||
int32_t displayFrameRight, int32_t displayFrameBottom)
|
int32_t displayFrameRight, int32_t displayFrameBottom) {
|
||||||
{
|
|
||||||
Renderable r{
|
Renderable r{
|
||||||
name,
|
name,
|
||||||
color_buffer,
|
color_buffer,
|
||||||
{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom},
|
{displayFrameLeft, displayFrameTop, displayFrameRight,
|
||||||
{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}
|
displayFrameBottom},
|
||||||
};
|
{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}};
|
||||||
frame_layers.push_back(r);
|
frame_layers.push_back(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rcPostAllLayersDone()
|
void rcPostAllLayersDone() {
|
||||||
{
|
if (composer) composer->submit_layers(frame_layers);
|
||||||
if (composer)
|
|
||||||
composer->submit_layers(frame_layers);
|
|
||||||
|
|
||||||
frame_layers.clear();
|
frame_layers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initRenderControlContext(renderControl_decoder_context_t *dec)
|
void initRenderControlContext(renderControl_decoder_context_t *dec) {
|
||||||
{
|
|
||||||
dec->rcGetRendererVersion = rcGetRendererVersion;
|
dec->rcGetRendererVersion = rcGetRendererVersion;
|
||||||
dec->rcGetEGLVersion = rcGetEGLVersion;
|
dec->rcGetEGLVersion = rcGetEGLVersion;
|
||||||
dec->rcQueryEGLString = rcQueryEGLString;
|
dec->rcQueryEGLString = rcQueryEGLString;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@
|
||||||
*/
|
*/
|
||||||
#include "RenderServer.h"
|
#include "RenderServer.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
#include "RenderThread.h"
|
#include "RenderThread.h"
|
||||||
#include "TcpStream.h"
|
#include "TcpStream.h"
|
||||||
#include "UnixStream.h"
|
#include "UnixStream.h"
|
||||||
#include <signal.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "OpenglRender/render_api.h"
|
#include "OpenglRender/render_api.h"
|
||||||
|
|
||||||
|
|
@ -29,23 +29,13 @@
|
||||||
|
|
||||||
typedef std::set<RenderThread *> RenderThreadsSet;
|
typedef std::set<RenderThread *> RenderThreadsSet;
|
||||||
|
|
||||||
RenderServer::RenderServer() :
|
RenderServer::RenderServer() : m_lock(), m_listenSock(NULL), m_exiting(false) {}
|
||||||
m_lock(),
|
|
||||||
m_listenSock(NULL),
|
|
||||||
m_exiting(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderServer::~RenderServer()
|
|
||||||
{
|
|
||||||
delete m_listenSock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
RenderServer::~RenderServer() { delete m_listenSock; }
|
||||||
|
|
||||||
extern "C" int gRendererStreamMode;
|
extern "C" int gRendererStreamMode;
|
||||||
|
|
||||||
RenderServer *RenderServer::create(char* addr, size_t addrLen)
|
RenderServer *RenderServer::create(char *addr, size_t addrLen) {
|
||||||
{
|
|
||||||
RenderServer *server = new RenderServer();
|
RenderServer *server = new RenderServer();
|
||||||
if (!server) {
|
if (!server) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -76,8 +66,7 @@ RenderServer *RenderServer::create(char* addr, size_t addrLen)
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t RenderServer::main()
|
intptr_t RenderServer::main() {
|
||||||
{
|
|
||||||
RenderThreadsSet threads;
|
RenderThreadsSet threads;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
@ -115,8 +104,7 @@ intptr_t RenderServer::main()
|
||||||
// remove from the threads list threads which are
|
// remove from the threads list threads which are
|
||||||
// no longer running
|
// no longer running
|
||||||
//
|
//
|
||||||
for (RenderThreadsSet::iterator n,t = threads.begin();
|
for (RenderThreadsSet::iterator n, t = threads.begin(); t != threads.end();
|
||||||
t != threads.end();
|
|
||||||
t = n) {
|
t = n) {
|
||||||
// first find next iterator
|
// first find next iterator
|
||||||
n = t;
|
n = t;
|
||||||
|
|
@ -131,15 +119,13 @@ intptr_t RenderServer::main()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the thread has been created and started, insert it to the list
|
// if the thread has been created and started, insert it to the list
|
||||||
if (rt)
|
if (rt) threads.insert(rt);
|
||||||
threads.insert(rt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Wait for all threads to finish
|
// Wait for all threads to finish
|
||||||
//
|
//
|
||||||
for (RenderThreadsSet::iterator t = threads.begin();
|
for (RenderThreadsSet::iterator t = threads.begin(); t != threads.end();
|
||||||
t != threads.end();
|
|
||||||
t++) {
|
t++) {
|
||||||
(*t)->forceStop();
|
(*t)->forceStop();
|
||||||
(*t)->wait(NULL);
|
(*t)->wait(NULL);
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@
|
||||||
#include "emugl/common/mutex.h"
|
#include "emugl/common/mutex.h"
|
||||||
#include "emugl/common/thread.h"
|
#include "emugl/common/thread.h"
|
||||||
|
|
||||||
class RenderServer : public emugl::Thread
|
class RenderServer : public emugl::Thread {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
static RenderServer *create(char *addr, size_t addrLen);
|
static RenderServer *create(char *addr, size_t addrLen);
|
||||||
virtual ~RenderServer();
|
virtual ~RenderServer();
|
||||||
|
|
|
||||||
|
|
@ -15,36 +15,30 @@
|
||||||
*/
|
*/
|
||||||
#include "RenderThread.h"
|
#include "RenderThread.h"
|
||||||
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "ReadBuffer.h"
|
#include "ReadBuffer.h"
|
||||||
#include "RenderControl.h"
|
#include "RenderControl.h"
|
||||||
#include "RenderThreadInfo.h"
|
#include "RenderThreadInfo.h"
|
||||||
|
#include "Renderer.h"
|
||||||
#include "TimeUtils.h"
|
#include "TimeUtils.h"
|
||||||
|
|
||||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
|
||||||
#include "OpenGLESDispatch/GLESv2Dispatch.h"
|
|
||||||
#include "OpenGLESDispatch/GLESv1Dispatch.h"
|
|
||||||
#include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
|
#include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
|
||||||
|
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||||
|
#include "OpenGLESDispatch/GLESv1Dispatch.h"
|
||||||
|
#include "OpenGLESDispatch/GLESv2Dispatch.h"
|
||||||
|
|
||||||
#define STREAM_BUFFER_SIZE 4 * 1024 * 1024
|
#define STREAM_BUFFER_SIZE 4 * 1024 * 1024
|
||||||
|
|
||||||
RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) :
|
RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock)
|
||||||
emugl::Thread(),
|
: emugl::Thread(), m_lock(lock), m_stream(stream) {}
|
||||||
m_lock(lock),
|
|
||||||
m_stream(stream) {}
|
|
||||||
|
|
||||||
RenderThread::~RenderThread() {
|
RenderThread::~RenderThread() { delete m_stream; }
|
||||||
delete m_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
RenderThread *RenderThread::create(IOStream *stream, emugl::Mutex *lock) {
|
RenderThread *RenderThread::create(IOStream *stream, emugl::Mutex *lock) {
|
||||||
return new RenderThread(stream, lock);
|
return new RenderThread(stream, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::forceStop() {
|
void RenderThread::forceStop() { m_stream->forceStop(); }
|
||||||
m_stream->forceStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t RenderThread::main() {
|
intptr_t RenderThread::main() {
|
||||||
RenderThreadInfo tInfo;
|
RenderThreadInfo tInfo;
|
||||||
|
|
@ -60,7 +54,6 @@ intptr_t RenderThread::main() {
|
||||||
ReadBuffer readBuf(STREAM_BUFFER_SIZE);
|
ReadBuffer readBuf(STREAM_BUFFER_SIZE);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
int stat = readBuf.getData(m_stream);
|
int stat = readBuf.getData(m_stream);
|
||||||
if (stat <= 0) {
|
if (stat <= 0) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -74,7 +67,8 @@ intptr_t RenderThread::main() {
|
||||||
//
|
//
|
||||||
// try to process some of the command buffer using the GLESv1 decoder
|
// try to process some of the command buffer using the GLESv1 decoder
|
||||||
//
|
//
|
||||||
size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
|
size_t last =
|
||||||
|
tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
|
||||||
if (last > 0) {
|
if (last > 0) {
|
||||||
progress = true;
|
progress = true;
|
||||||
readBuf.consume(last);
|
readBuf.consume(last);
|
||||||
|
|
@ -83,7 +77,8 @@ intptr_t RenderThread::main() {
|
||||||
//
|
//
|
||||||
// try to process some of the command buffer using the GLESv2 decoder
|
// try to process some of the command buffer using the GLESv2 decoder
|
||||||
//
|
//
|
||||||
last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
|
last =
|
||||||
|
tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream);
|
||||||
if (last > 0) {
|
if (last > 0) {
|
||||||
progress = true;
|
progress = true;
|
||||||
readBuf.consume(last);
|
readBuf.consume(last);
|
||||||
|
|
@ -102,7 +97,6 @@ intptr_t RenderThread::main() {
|
||||||
m_lock->unlock();
|
m_lock->unlock();
|
||||||
|
|
||||||
} while (progress);
|
} while (progress);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -110,7 +104,8 @@ intptr_t RenderThread::main() {
|
||||||
//
|
//
|
||||||
Renderer::get()->bindContext(0, 0, 0);
|
Renderer::get()->bindContext(0, 0, 0);
|
||||||
if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
|
if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) {
|
||||||
fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n");
|
fprintf(stderr,
|
||||||
|
"ERROR: RenderThread exiting with current context/surfaces\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::get()->drainWindowSurface();
|
Renderer::get()->drainWindowSurface();
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,16 @@
|
||||||
|
|
||||||
#include "RenderWindow.h"
|
#include "RenderWindow.h"
|
||||||
|
|
||||||
|
#include "Renderer.h"
|
||||||
#include "emugl/common/logging.h"
|
#include "emugl/common/logging.h"
|
||||||
#include "emugl/common/message_channel.h"
|
#include "emugl/common/message_channel.h"
|
||||||
#include "emugl/common/mutex.h"
|
#include "emugl/common/mutex.h"
|
||||||
#include "emugl/common/thread.h"
|
#include "emugl/common/thread.h"
|
||||||
#include "Renderer.h"
|
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
|
|
@ -129,8 +129,7 @@ struct RenderWindowMessage {
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -240,12 +239,8 @@ private:
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RenderWindow::RenderWindow(EGLNativeDisplayType native_display,
|
RenderWindow::RenderWindow(EGLNativeDisplayType native_display, bool use_thread)
|
||||||
bool use_thread) :
|
: mValid(false), mHasSubWindow(false), mThread(NULL), mChannel(NULL) {
|
||||||
mValid(false),
|
|
||||||
mHasSubWindow(false),
|
|
||||||
mThread(NULL),
|
|
||||||
mChannel(NULL) {
|
|
||||||
if (use_thread) {
|
if (use_thread) {
|
||||||
mChannel = new RenderWindowChannel();
|
mChannel = new RenderWindowChannel();
|
||||||
mThread = new RenderWindowThread(mChannel);
|
mThread = new RenderWindowThread(mChannel);
|
||||||
|
|
@ -284,20 +279,14 @@ bool RenderWindow::getHardwareStrings(const char** vendor,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fb->getGLStrings(vendor, renderer, version);
|
fb->getGLStrings(vendor, renderer, version);
|
||||||
D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n",
|
D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n", *vendor, *renderer,
|
||||||
*vendor, *renderer, *version);
|
*version);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderWindow::setupSubWindow(FBNativeWindowType window,
|
bool RenderWindow::setupSubWindow(FBNativeWindowType window, int wx, int wy,
|
||||||
int wx,
|
int ww, int wh, int fbw, int fbh, float dpr,
|
||||||
int wy,
|
|
||||||
int ww,
|
|
||||||
int wh,
|
|
||||||
int fbw,
|
|
||||||
int fbh,
|
|
||||||
float dpr,
|
|
||||||
float zRot) {
|
float zRot) {
|
||||||
D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");
|
D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,12 @@
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class Renderable
|
class Renderable {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Renderable(const std::string &name,
|
Renderable(const std::string &name, const std::uint32_t &buffer,
|
||||||
const std::uint32_t &buffer,
|
|
||||||
const anbox::graphics::Rect &screen_position,
|
const anbox::graphics::Rect &screen_position,
|
||||||
const anbox::graphics::Rect &crop = {},
|
const anbox::graphics::Rect &crop = {},
|
||||||
const glm::mat4 &transformation = {},
|
const glm::mat4 &transformation = {}, const float &alpha = 1.0f);
|
||||||
const float &alpha = 1.0f);
|
|
||||||
~Renderable();
|
~Renderable();
|
||||||
|
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtx/transform.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
@ -59,9 +59,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor will call release().
|
// Destructor will call release().
|
||||||
~ScopedBind() {
|
~ScopedBind() { release(); }
|
||||||
release();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer *mFb;
|
Renderer *mFb;
|
||||||
|
|
@ -73,17 +71,12 @@ class ColorBufferHelper : public ColorBuffer::Helper {
|
||||||
public:
|
public:
|
||||||
ColorBufferHelper(Renderer *fb) : mFb(fb) {}
|
ColorBufferHelper(Renderer *fb) : mFb(fb) {}
|
||||||
|
|
||||||
virtual bool setupContext() {
|
virtual bool setupContext() { return mFb->bind_locked(); }
|
||||||
return mFb->bind_locked();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void teardownContext() {
|
virtual void teardownContext() { mFb->unbind_locked(); }
|
||||||
mFb->unbind_locked();
|
|
||||||
}
|
virtual TextureDraw *getTextureDraw() const { return mFb->getTextureDraw(); }
|
||||||
|
|
||||||
virtual TextureDraw* getTextureDraw() const {
|
|
||||||
return mFb->getTextureDraw();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
Renderer *mFb;
|
Renderer *mFb;
|
||||||
};
|
};
|
||||||
|
|
@ -93,31 +86,23 @@ private:
|
||||||
Renderer *Renderer::s_renderer = NULL;
|
Renderer *Renderer::s_renderer = NULL;
|
||||||
HandleType Renderer::s_nextHandle = 0;
|
HandleType Renderer::s_nextHandle = 0;
|
||||||
|
|
||||||
static char* getGLES1ExtensionString(EGLDisplay p_dpy)
|
static char *getGLES1ExtensionString(EGLDisplay p_dpy) {
|
||||||
{
|
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLSurface surface;
|
EGLSurface surface;
|
||||||
|
|
||||||
static const GLint configAttribs[] = {
|
static const GLint configAttribs[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
||||||
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
||||||
EGL_NONE
|
EGL_NONE};
|
||||||
};
|
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
if (!s_egl.eglChooseConfig(p_dpy, configAttribs,
|
if (!s_egl.eglChooseConfig(p_dpy, configAttribs, &config, 1, &n) || n == 0) {
|
||||||
&config, 1, &n) || n == 0) {
|
|
||||||
ERR("%s: Could not find GLES 1.x config!\n", __FUNCTION__);
|
ERR("%s: Could not find GLES 1.x config!\n", __FUNCTION__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG("%s: Found config %p\n", __FUNCTION__, (void *)config);
|
DBG("%s: Found config %p\n", __FUNCTION__, (void *)config);
|
||||||
|
|
||||||
static const EGLint pbufAttribs[] = {
|
static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||||
EGL_WIDTH, 1,
|
|
||||||
EGL_HEIGHT, 1,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
surface = s_egl.eglCreatePbufferSurface(p_dpy, config, pbufAttribs);
|
surface = s_egl.eglCreatePbufferSurface(p_dpy, config, pbufAttribs);
|
||||||
if (surface == EGL_NO_SURFACE) {
|
if (surface == EGL_NO_SURFACE) {
|
||||||
|
|
@ -125,13 +110,10 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GLint gles1ContextAttribs[] = {
|
static const GLint gles1ContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 1,
|
||||||
EGL_CONTEXT_CLIENT_VERSION, 1,
|
EGL_NONE};
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
EGLContext ctx = s_egl.eglCreateContext(p_dpy, config,
|
EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, EGL_NO_CONTEXT,
|
||||||
EGL_NO_CONTEXT,
|
|
||||||
gles1ContextAttribs);
|
gles1ContextAttribs);
|
||||||
if (ctx == EGL_NO_CONTEXT) {
|
if (ctx == EGL_NO_CONTEXT) {
|
||||||
ERR("%s: Could not create GLES 1.x Context!\n", __FUNCTION__);
|
ERR("%s: Could not create GLES 1.x Context!\n", __FUNCTION__);
|
||||||
|
|
@ -167,8 +149,7 @@ void Renderer::finalize(){
|
||||||
s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface);
|
s_egl.eglDestroySurface(m_eglDisplay, m_pbufSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) {
|
||||||
{
|
|
||||||
GL_LOG("FrameBuffer::initialize");
|
GL_LOG("FrameBuffer::initialize");
|
||||||
if (s_renderer != NULL) {
|
if (s_renderer != NULL) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -194,8 +175,7 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_LOG("call eglInitialize");
|
GL_LOG("call eglInitialize");
|
||||||
if (!s_egl.eglInitialize(fb->m_eglDisplay,
|
if (!s_egl.eglInitialize(fb->m_eglDisplay, &fb->m_caps.eglMajor,
|
||||||
&fb->m_caps.eglMajor,
|
|
||||||
&fb->m_caps.eglMinor)) {
|
&fb->m_caps.eglMinor)) {
|
||||||
ERR("Failed to eglInitialize\n");
|
ERR("Failed to eglInitialize\n");
|
||||||
GL_LOG("Failed to eglInitialize");
|
GL_LOG("Failed to eglInitialize");
|
||||||
|
|
@ -224,34 +204,33 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
// Create EGL context for framebuffer post rendering.
|
// Create EGL context for framebuffer post rendering.
|
||||||
//
|
//
|
||||||
GLint surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
|
GLint surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
|
||||||
const GLint configAttribs[] = {
|
const GLint configAttribs[] = {EGL_RED_SIZE,
|
||||||
EGL_RED_SIZE, 1,
|
1,
|
||||||
EGL_GREEN_SIZE, 1,
|
EGL_GREEN_SIZE,
|
||||||
EGL_BLUE_SIZE, 1,
|
1,
|
||||||
EGL_SURFACE_TYPE, surfaceType,
|
EGL_BLUE_SIZE,
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
1,
|
||||||
EGL_NONE
|
EGL_SURFACE_TYPE,
|
||||||
};
|
surfaceType,
|
||||||
|
EGL_RENDERABLE_TYPE,
|
||||||
|
EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs,
|
if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, &fb->m_eglConfig,
|
||||||
&fb->m_eglConfig, 1, &n)) {
|
1, &n)) {
|
||||||
ERR("Failed on eglChooseConfig\n");
|
ERR("Failed on eglChooseConfig\n");
|
||||||
free(gles1Extensions);
|
free(gles1Extensions);
|
||||||
delete fb;
|
delete fb;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GLint glContextAttribs[] = {
|
static const GLint glContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
EGL_NONE};
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
GL_LOG("attempting to create egl context");
|
GL_LOG("attempting to create egl context");
|
||||||
fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay,
|
fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig,
|
||||||
fb->m_eglConfig,
|
EGL_NO_CONTEXT, glContextAttribs);
|
||||||
EGL_NO_CONTEXT,
|
|
||||||
glContextAttribs);
|
|
||||||
if (fb->m_eglContext == EGL_NO_CONTEXT) {
|
if (fb->m_eglContext == EGL_NO_CONTEXT) {
|
||||||
ERR("Failed to create context 0x%x\n", s_egl.eglGetError());
|
ERR("Failed to create context 0x%x\n", s_egl.eglGetError());
|
||||||
free(gles1Extensions);
|
free(gles1Extensions);
|
||||||
|
|
@ -268,10 +247,8 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
// on Mac platform when switching binded drawable for a context however
|
// on Mac platform when switching binded drawable for a context however
|
||||||
// it is more efficient on other platforms as well.
|
// it is more efficient on other platforms as well.
|
||||||
//
|
//
|
||||||
fb->m_pbufContext = s_egl.eglCreateContext(fb->m_eglDisplay,
|
fb->m_pbufContext = s_egl.eglCreateContext(
|
||||||
fb->m_eglConfig,
|
fb->m_eglDisplay, fb->m_eglConfig, fb->m_eglContext, glContextAttribs);
|
||||||
fb->m_eglContext,
|
|
||||||
glContextAttribs);
|
|
||||||
if (fb->m_pbufContext == EGL_NO_CONTEXT) {
|
if (fb->m_pbufContext == EGL_NO_CONTEXT) {
|
||||||
ERR("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError());
|
ERR("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError());
|
||||||
free(gles1Extensions);
|
free(gles1Extensions);
|
||||||
|
|
@ -285,15 +262,10 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
// the FB context.
|
// the FB context.
|
||||||
// The FB output will go to a subwindow, if one exist.
|
// The FB output will go to a subwindow, if one exist.
|
||||||
//
|
//
|
||||||
static const EGLint pbufAttribs[] = {
|
static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||||
EGL_WIDTH, 1,
|
|
||||||
EGL_HEIGHT, 1,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(fb->m_eglDisplay,
|
fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(
|
||||||
fb->m_eglConfig,
|
fb->m_eglDisplay, fb->m_eglConfig, pbufAttribs);
|
||||||
pbufAttribs);
|
|
||||||
if (fb->m_pbufSurface == EGL_NO_SURFACE) {
|
if (fb->m_pbufSurface == EGL_NO_SURFACE) {
|
||||||
ERR("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError());
|
ERR("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError());
|
||||||
free(gles1Extensions);
|
free(gles1Extensions);
|
||||||
|
|
@ -315,7 +287,8 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
//
|
//
|
||||||
// Initilize framebuffer capabilities
|
// Initilize framebuffer capabilities
|
||||||
//
|
//
|
||||||
//const char* gles2Extensions = (const char *)s_gles2.glGetString(GL_EXTENSIONS);
|
// const char* gles2Extensions = (const char
|
||||||
|
// *)s_gles2.glGetString(GL_EXTENSIONS);
|
||||||
bool has_gl_oes_image = false;
|
bool has_gl_oes_image = false;
|
||||||
|
|
||||||
// printf("GLES1 [%s]\n", gles1Extensions);
|
// printf("GLES1 [%s]\n", gles1Extensions);
|
||||||
|
|
@ -329,16 +302,15 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
free((void *)gles1Extensions);
|
free((void *)gles1Extensions);
|
||||||
gles1Extensions = NULL;
|
gles1Extensions = NULL;
|
||||||
|
|
||||||
const char *eglExtensions = s_egl.eglQueryString(fb->m_eglDisplay,
|
const char *eglExtensions =
|
||||||
EGL_EXTENSIONS);
|
s_egl.eglQueryString(fb->m_eglDisplay, EGL_EXTENSIONS);
|
||||||
|
|
||||||
if (eglExtensions && has_gl_oes_image) {
|
if (eglExtensions && has_gl_oes_image) {
|
||||||
fb->m_caps.has_eglimage_texture_2d =
|
fb->m_caps.has_eglimage_texture_2d =
|
||||||
strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL;
|
strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL;
|
||||||
fb->m_caps.has_eglimage_renderbuffer =
|
fb->m_caps.has_eglimage_renderbuffer =
|
||||||
strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL;
|
strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fb->m_caps.has_eglimage_texture_2d = false;
|
fb->m_caps.has_eglimage_texture_2d = false;
|
||||||
fb->m_caps.has_eglimage_renderbuffer = false;
|
fb->m_caps.has_eglimage_renderbuffer = false;
|
||||||
}
|
}
|
||||||
|
|
@ -435,21 +407,22 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Program::Program(GLuint program_id)
|
Renderer::Program::Program(GLuint program_id) {
|
||||||
{
|
|
||||||
id = program_id;
|
id = program_id;
|
||||||
position_attr = s_gles2.glGetAttribLocation(id, "position");
|
position_attr = s_gles2.glGetAttribLocation(id, "position");
|
||||||
texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord");
|
texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord");
|
||||||
tex_uniform = s_gles2.glGetUniformLocation(id, "tex");
|
tex_uniform = s_gles2.glGetUniformLocation(id, "tex");
|
||||||
center_uniform = s_gles2.glGetUniformLocation(id, "centre");
|
center_uniform = s_gles2.glGetUniformLocation(id, "centre");
|
||||||
display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform");
|
display_transform_uniform =
|
||||||
|
s_gles2.glGetUniformLocation(id, "display_transform");
|
||||||
transform_uniform = s_gles2.glGetUniformLocation(id, "transform");
|
transform_uniform = s_gles2.glGetUniformLocation(id, "transform");
|
||||||
screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords");
|
screen_to_gl_coords_uniform =
|
||||||
|
s_gles2.glGetUniformLocation(id, "screen_to_gl_coords");
|
||||||
alpha_uniform = s_gles2.glGetUniformLocation(id, "alpha");
|
alpha_uniform = s_gles2.glGetUniformLocation(id, "alpha");
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Renderer() :
|
Renderer::Renderer()
|
||||||
m_configs(NULL),
|
: m_configs(NULL),
|
||||||
m_eglDisplay(EGL_NO_DISPLAY),
|
m_eglDisplay(EGL_NO_DISPLAY),
|
||||||
m_colorBufferHelper(new ColorBufferHelper(this)),
|
m_colorBufferHelper(new ColorBufferHelper(this)),
|
||||||
m_eglContext(EGL_NO_CONTEXT),
|
m_eglContext(EGL_NO_CONTEXT),
|
||||||
|
|
@ -463,8 +436,7 @@ Renderer::Renderer() :
|
||||||
m_statsStartTime(0LL),
|
m_statsStartTime(0LL),
|
||||||
m_glVendor(NULL),
|
m_glVendor(NULL),
|
||||||
m_glRenderer(NULL),
|
m_glRenderer(NULL),
|
||||||
m_glVersion(NULL)
|
m_glVersion(NULL) {
|
||||||
{
|
|
||||||
m_fpsStats = getenv("SHOW_FPS_STATS") != NULL;
|
m_fpsStats = getenv("SHOW_FPS_STATS") != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,31 +454,28 @@ struct RendererWindow {
|
||||||
glm::mat4 display_transform;
|
glm::mat4 display_transform;
|
||||||
};
|
};
|
||||||
|
|
||||||
RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window)
|
RendererWindow *Renderer::createNativeWindow(
|
||||||
{
|
EGLNativeWindowType native_window) {
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
|
|
||||||
auto window = new RendererWindow;
|
auto window = new RendererWindow;
|
||||||
window->native_window = native_window;
|
window->native_window = native_window;
|
||||||
window->surface = s_egl.eglCreateWindowSurface(
|
window->surface = s_egl.eglCreateWindowSurface(
|
||||||
m_eglDisplay, m_eglConfig, window->native_window, nullptr);
|
m_eglDisplay, m_eglConfig, window->native_window, nullptr);
|
||||||
if (window->surface == EGL_NO_SURFACE)
|
if (window->surface == EGL_NO_SURFACE) {
|
||||||
{
|
|
||||||
delete window;
|
delete window;
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bindWindow_locked(window))
|
if (!bindWindow_locked(window)) {
|
||||||
{
|
|
||||||
s_egl.eglDestroySurface(m_eglDisplay, window->surface);
|
s_egl.eglDestroySurface(m_eglDisplay, window->surface);
|
||||||
delete window;
|
delete window;
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_gles2.glClear(GL_COLOR_BUFFER_BIT |
|
s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
|
||||||
GL_DEPTH_BUFFER_BIT |
|
|
||||||
GL_STENCIL_BUFFER_BIT);
|
GL_STENCIL_BUFFER_BIT);
|
||||||
s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
|
s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
|
||||||
|
|
||||||
|
|
@ -521,8 +490,7 @@ RendererWindow* Renderer::createNativeWindow(EGLNativeWindowType native_window)
|
||||||
|
|
||||||
void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) {
|
void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) {
|
||||||
auto w = m_nativeWindows.find(native_window);
|
auto w = m_nativeWindows.find(native_window);
|
||||||
if (w == m_nativeWindows.end())
|
if (w == m_nativeWindows.end()) return;
|
||||||
return;
|
|
||||||
|
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
|
|
||||||
|
|
@ -537,31 +505,24 @@ void Renderer::destroyNativeWindow(EGLNativeWindowType native_window) {
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleType Renderer::genHandle()
|
HandleType Renderer::genHandle() {
|
||||||
{
|
|
||||||
HandleType id;
|
HandleType id;
|
||||||
do {
|
do {
|
||||||
id = ++s_nextHandle;
|
id = ++s_nextHandle;
|
||||||
} while( id == 0 ||
|
} while (id == 0 || m_contexts.find(id) != m_contexts.end() ||
|
||||||
m_contexts.find(id) != m_contexts.end() ||
|
|
||||||
m_windows.find(id) != m_windows.end());
|
m_windows.find(id) != m_windows.end());
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleType Renderer::createColorBuffer(int p_width, int p_height,
|
HandleType Renderer::createColorBuffer(int p_width, int p_height,
|
||||||
GLenum p_internalFormat)
|
GLenum p_internalFormat) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
HandleType ret = 0;
|
HandleType ret = 0;
|
||||||
|
|
||||||
ColorBufferPtr cb(ColorBuffer::create(
|
ColorBufferPtr cb(ColorBuffer::create(
|
||||||
getDisplay(),
|
getDisplay(), p_width, p_height, p_internalFormat,
|
||||||
p_width,
|
getCaps().has_eglimage_texture_2d, m_colorBufferHelper));
|
||||||
p_height,
|
|
||||||
p_internalFormat,
|
|
||||||
getCaps().has_eglimage_texture_2d,
|
|
||||||
m_colorBufferHelper));
|
|
||||||
if (cb.Ptr() != NULL) {
|
if (cb.Ptr() != NULL) {
|
||||||
ret = genHandle();
|
ret = genHandle();
|
||||||
m_colorbuffers[ret].cb = cb;
|
m_colorbuffers[ret].cb = cb;
|
||||||
|
|
@ -571,8 +532,7 @@ HandleType Renderer::createColorBuffer(int p_width, int p_height,
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
||||||
bool p_isGL2)
|
bool p_isGL2) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
HandleType ret = 0;
|
HandleType ret = 0;
|
||||||
|
|
||||||
|
|
@ -603,8 +563,8 @@ HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height)
|
HandleType Renderer::createWindowSurface(int p_config, int p_width,
|
||||||
{
|
int p_height) {
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
HandleType ret = 0;
|
HandleType ret = 0;
|
||||||
|
|
@ -626,8 +586,7 @@ HandleType Renderer::createWindowSurface(int p_config, int p_width, int p_height
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::drainRenderContext()
|
void Renderer::drainRenderContext() {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||||
if (tinfo->m_contextSet.empty()) return;
|
if (tinfo->m_contextSet.empty()) return;
|
||||||
|
|
@ -639,8 +598,7 @@ void Renderer::drainRenderContext()
|
||||||
tinfo->m_contextSet.clear();
|
tinfo->m_contextSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::drainWindowSurface()
|
void Renderer::drainWindowSurface() {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||||
if (tinfo->m_windowSet.empty()) return;
|
if (tinfo->m_windowSet.empty()) return;
|
||||||
|
|
@ -652,7 +610,9 @@ void Renderer::drainWindowSurface()
|
||||||
if (oldColorBufferHandle) {
|
if (oldColorBufferHandle) {
|
||||||
ColorBufferMap::iterator cit(m_colorbuffers.find(oldColorBufferHandle));
|
ColorBufferMap::iterator cit(m_colorbuffers.find(oldColorBufferHandle));
|
||||||
if (cit != m_colorbuffers.end()) {
|
if (cit != m_colorbuffers.end()) {
|
||||||
if (--(*cit).second.refcount == 0) { m_colorbuffers.erase(cit); }
|
if (--(*cit).second.refcount == 0) {
|
||||||
|
m_colorbuffers.erase(cit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_windows.erase(windowHandle);
|
m_windows.erase(windowHandle);
|
||||||
|
|
@ -661,8 +621,7 @@ void Renderer::drainWindowSurface()
|
||||||
tinfo->m_windowSet.clear();
|
tinfo->m_windowSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DestroyRenderContext(HandleType p_context)
|
void Renderer::DestroyRenderContext(HandleType p_context) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
m_contexts.erase(p_context);
|
m_contexts.erase(p_context);
|
||||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||||
|
|
@ -670,8 +629,7 @@ void Renderer::DestroyRenderContext(HandleType p_context)
|
||||||
tinfo->m_contextSet.erase(p_context);
|
tinfo->m_contextSet.erase(p_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DestroyWindowSurface(HandleType p_surface)
|
void Renderer::DestroyWindowSurface(HandleType p_surface) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
if (m_windows.find(p_surface) != m_windows.end()) {
|
if (m_windows.find(p_surface) != m_windows.end()) {
|
||||||
m_windows.erase(p_surface);
|
m_windows.erase(p_surface);
|
||||||
|
|
@ -681,8 +639,7 @@ void Renderer::DestroyWindowSurface(HandleType p_surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Renderer::openColorBuffer(HandleType p_colorbuffer)
|
int Renderer::openColorBuffer(HandleType p_colorbuffer) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
if (c == m_colorbuffers.end()) {
|
if (c == m_colorbuffers.end()) {
|
||||||
|
|
@ -694,8 +651,7 @@ int Renderer::openColorBuffer(HandleType p_colorbuffer)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::closeColorBuffer(HandleType p_colorbuffer)
|
void Renderer::closeColorBuffer(HandleType p_colorbuffer) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
if (c == m_colorbuffers.end()) {
|
if (c == m_colorbuffers.end()) {
|
||||||
|
|
@ -710,13 +666,13 @@ void Renderer::closeColorBuffer(HandleType p_colorbuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface)
|
bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
||||||
if (w == m_windows.end()) {
|
if (w == m_windows.end()) {
|
||||||
ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n", p_surface);
|
ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n",
|
||||||
|
p_surface);
|
||||||
// bad surface handle
|
// bad surface handle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -728,8 +684,7 @@ bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
||||||
HandleType p_colorbuffer)
|
HandleType p_colorbuffer) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
||||||
|
|
@ -751,10 +706,9 @@ bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::readColorBuffer(HandleType p_colorbuffer,
|
void Renderer::readColorBuffer(HandleType p_colorbuffer, int x, int y,
|
||||||
int x, int y, int width, int height,
|
int width, int height, GLenum format,
|
||||||
GLenum format, GLenum type, void *pixels)
|
GLenum type, void *pixels) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
|
|
@ -766,10 +720,9 @@ void Renderer::readColorBuffer(HandleType p_colorbuffer,
|
||||||
(*c).second.cb->readPixels(x, y, width, height, format, type, pixels);
|
(*c).second.cb->readPixels(x, y, width, height, format, type, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::updateColorBuffer(HandleType p_colorbuffer,
|
bool Renderer::updateColorBuffer(HandleType p_colorbuffer, int x, int y,
|
||||||
int x, int y, int width, int height,
|
int width, int height, GLenum format,
|
||||||
GLenum format, GLenum type, void *pixels)
|
GLenum type, void *pixels) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
|
|
@ -783,8 +736,7 @@ bool Renderer::updateColorBuffer(HandleType p_colorbuffer,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer)
|
bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
|
|
@ -796,8 +748,7 @@ bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer)
|
||||||
return (*c).second.cb->bindToTexture();
|
return (*c).second.cb->bindToTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
|
bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||||
|
|
@ -809,10 +760,8 @@ bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
|
||||||
return (*c).second.cb->bindToRenderbuffer();
|
return (*c).second.cb->bindToRenderbuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::bindContext(HandleType p_context,
|
bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface,
|
||||||
HandleType p_drawSurface,
|
HandleType p_readSurface) {
|
||||||
HandleType p_readSurface)
|
|
||||||
{
|
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
emugl::Mutex::AutoLock mutex(m_lock);
|
||||||
|
|
||||||
WindowSurfacePtr draw(NULL), read(NULL);
|
WindowSurfacePtr draw(NULL), read(NULL);
|
||||||
|
|
@ -843,8 +792,7 @@ bool Renderer::bindContext(HandleType p_context,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
read = (*w).second.first;
|
read = (*w).second.first;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
read = draw;
|
read = draw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -875,8 +823,7 @@ bool Renderer::bindContext(HandleType p_context,
|
||||||
if (bindDraw.Ptr() != bindRead.Ptr()) {
|
if (bindDraw.Ptr() != bindRead.Ptr()) {
|
||||||
bindDraw->bind(ctx, WindowSurface::BIND_DRAW);
|
bindDraw->bind(ctx, WindowSurface::BIND_DRAW);
|
||||||
bindRead->bind(ctx, WindowSurface::BIND_READ);
|
bindRead->bind(ctx, WindowSurface::BIND_READ);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
bindDraw->bind(ctx, WindowSurface::BIND_READDRAW);
|
bindDraw->bind(ctx, WindowSurface::BIND_READDRAW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -888,18 +835,19 @@ bool Renderer::bindContext(HandleType p_context,
|
||||||
tinfo->currDrawSurf = draw;
|
tinfo->currDrawSurf = draw;
|
||||||
tinfo->currReadSurf = read;
|
tinfo->currReadSurf = read;
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
if (ctx->isGL2()) tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
|
if (ctx->isGL2())
|
||||||
else tinfo->m_glDec.setContextData(&ctx->decoderContextData());
|
tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
|
||||||
}
|
else
|
||||||
else {
|
tinfo->m_glDec.setContextData(&ctx->decoderContextData());
|
||||||
|
} else {
|
||||||
tinfo->m_glDec.setContextData(NULL);
|
tinfo->m_glDec.setContextData(NULL);
|
||||||
tinfo->m_gl2Dec.setContextData(NULL);
|
tinfo->m_gl2Dec.setContextData(NULL);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleType Renderer::createClientImage(HandleType context, EGLenum target, GLuint buffer)
|
HandleType Renderer::createClientImage(HandleType context, EGLenum target,
|
||||||
{
|
GLuint buffer) {
|
||||||
RenderContextPtr ctx(NULL);
|
RenderContextPtr ctx(NULL);
|
||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
|
|
@ -913,15 +861,14 @@ HandleType Renderer::createClientImage(HandleType context, EGLenum target, GLuin
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLContext eglContext = ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT;
|
EGLContext eglContext = ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT;
|
||||||
EGLImageKHR image = s_egl.eglCreateImageKHR(
|
EGLImageKHR image =
|
||||||
m_eglDisplay, eglContext, target,
|
s_egl.eglCreateImageKHR(m_eglDisplay, eglContext, target,
|
||||||
reinterpret_cast<EGLClientBuffer>(buffer), NULL);
|
reinterpret_cast<EGLClientBuffer>(buffer), NULL);
|
||||||
|
|
||||||
return (HandleType) reinterpret_cast<uintptr_t>(image);
|
return (HandleType) reinterpret_cast<uintptr_t>(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLBoolean Renderer::destroyClientImage(HandleType image)
|
EGLBoolean Renderer::destroyClientImage(HandleType image) {
|
||||||
{
|
|
||||||
return s_egl.eglDestroyImageKHR(m_eglDisplay,
|
return s_egl.eglDestroyImageKHR(m_eglDisplay,
|
||||||
reinterpret_cast<EGLImageKHR>(image));
|
reinterpret_cast<EGLImageKHR>(image));
|
||||||
}
|
}
|
||||||
|
|
@ -929,14 +876,13 @@ EGLBoolean Renderer::destroyClientImage(HandleType image)
|
||||||
//
|
//
|
||||||
// The framebuffer lock should be held when calling this function !
|
// The framebuffer lock should be held when calling this function !
|
||||||
//
|
//
|
||||||
bool Renderer::bind_locked()
|
bool Renderer::bind_locked() {
|
||||||
{
|
|
||||||
EGLContext prevContext = s_egl.eglGetCurrentContext();
|
EGLContext prevContext = s_egl.eglGetCurrentContext();
|
||||||
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
||||||
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
||||||
|
|
||||||
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface,
|
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, m_pbufSurface,
|
||||||
m_pbufSurface, m_pbufContext)) {
|
m_pbufContext)) {
|
||||||
ERR("eglMakeCurrent failed\n");
|
ERR("eglMakeCurrent failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -947,14 +893,13 @@ bool Renderer::bind_locked()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::bindWindow_locked(RendererWindow *window)
|
bool Renderer::bindWindow_locked(RendererWindow *window) {
|
||||||
{
|
|
||||||
EGLContext prevContext = s_egl.eglGetCurrentContext();
|
EGLContext prevContext = s_egl.eglGetCurrentContext();
|
||||||
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
||||||
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
||||||
|
|
||||||
if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface,
|
if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface, window->surface,
|
||||||
window->surface, m_eglContext)) {
|
m_eglContext)) {
|
||||||
ERR("eglMakeCurrent failed\n");
|
ERR("eglMakeCurrent failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -965,10 +910,9 @@ bool Renderer::bindWindow_locked(RendererWindow *window)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::unbind_locked()
|
bool Renderer::unbind_locked() {
|
||||||
{
|
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, m_prevReadSurf,
|
||||||
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf,
|
m_prevContext)) {
|
||||||
m_prevReadSurf, m_prevContext)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -978,8 +922,7 @@ bool Renderer::unbind_locked()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLchar* const Renderer::vshader =
|
const GLchar *const Renderer::vshader = {
|
||||||
{
|
|
||||||
"attribute vec3 position;\n"
|
"attribute vec3 position;\n"
|
||||||
"attribute vec2 texcoord;\n"
|
"attribute vec2 texcoord;\n"
|
||||||
"uniform mat4 screen_to_gl_coords;\n"
|
"uniform mat4 screen_to_gl_coords;\n"
|
||||||
|
|
@ -992,11 +935,9 @@ const GLchar* const Renderer::vshader =
|
||||||
" vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n"
|
" vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n"
|
||||||
" gl_Position = display_transform * screen_to_gl_coords * transformed;\n"
|
" gl_Position = display_transform * screen_to_gl_coords * transformed;\n"
|
||||||
" v_texcoord = texcoord;\n"
|
" v_texcoord = texcoord;\n"
|
||||||
"}\n"
|
"}\n"};
|
||||||
};
|
|
||||||
|
|
||||||
const GLchar* const Renderer::alphaFShader =
|
const GLchar *const Renderer::alphaFShader = {
|
||||||
{
|
|
||||||
"precision mediump float;\n"
|
"precision mediump float;\n"
|
||||||
"uniform sampler2D tex;\n"
|
"uniform sampler2D tex;\n"
|
||||||
"uniform float alpha;\n"
|
"uniform float alpha;\n"
|
||||||
|
|
@ -1004,8 +945,7 @@ const GLchar* const Renderer::alphaFShader =
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" vec4 frag = texture2D(tex, v_texcoord);\n"
|
" vec4 frag = texture2D(tex, v_texcoord);\n"
|
||||||
" gl_FragColor = alpha*frag;\n"
|
" gl_FragColor = alpha*frag;\n"
|
||||||
"}\n"
|
"}\n"};
|
||||||
};
|
|
||||||
|
|
||||||
const GLchar *const Renderer::defaultFShader =
|
const GLchar *const Renderer::defaultFShader =
|
||||||
{ // This is the fastest fragment shader. Use it when you can.
|
{ // This is the fastest fragment shader. Use it when you can.
|
||||||
|
|
@ -1014,11 +954,10 @@ const GLchar* const Renderer::defaultFShader =
|
||||||
"varying vec2 v_texcoord;\n"
|
"varying vec2 v_texcoord;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" gl_FragColor = texture2D(tex, v_texcoord);\n"
|
" gl_FragColor = texture2D(tex, v_texcoord);\n"
|
||||||
"}\n"
|
"}\n"};
|
||||||
};
|
|
||||||
|
|
||||||
void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect &rect)
|
void Renderer::setupViewport(RendererWindow *window,
|
||||||
{
|
const anbox::graphics::Rect &rect) {
|
||||||
/*
|
/*
|
||||||
* Here we provide a 3D perspective projection with a default 30 degrees
|
* Here we provide a 3D perspective projection with a default 30 degrees
|
||||||
* vertical field of view. This projection matrix is carefully designed
|
* vertical field of view. This projection matrix is carefully designed
|
||||||
|
|
@ -1028,7 +967,8 @@ void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect
|
||||||
* a different depth and it will appear to come out of or go into the
|
* a different depth and it will appear to come out of or go into the
|
||||||
* screen.
|
* screen.
|
||||||
*/
|
*/
|
||||||
window->screen_to_gl_coords = glm::translate(glm::mat4(1.0f), glm::vec3{-1.0f, 1.0f, 0.0f});
|
window->screen_to_gl_coords =
|
||||||
|
glm::translate(glm::mat4(1.0f), glm::vec3{-1.0f, 1.0f, 0.0f});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perspective division is one thing that can't be done in a matrix
|
* Perspective division is one thing that can't be done in a matrix
|
||||||
|
|
@ -1039,27 +979,23 @@ void Renderer::setupViewport(RendererWindow *window, const anbox::graphics::Rect
|
||||||
window->screen_to_gl_coords[2][3] = -1.0f;
|
window->screen_to_gl_coords[2][3] = -1.0f;
|
||||||
|
|
||||||
float const vertical_fov_degrees = 30.0f;
|
float const vertical_fov_degrees = 30.0f;
|
||||||
float const near =
|
float const near = (rect.height() / 2.0f) /
|
||||||
(rect.height() / 2.0f) /
|
|
||||||
std::tan((vertical_fov_degrees * M_PI / 180.0f) / 2.0f);
|
std::tan((vertical_fov_degrees * M_PI / 180.0f) / 2.0f);
|
||||||
float const far = -near;
|
float const far = -near;
|
||||||
|
|
||||||
window->screen_to_gl_coords = glm::scale(window->screen_to_gl_coords,
|
window->screen_to_gl_coords =
|
||||||
glm::vec3{2.0f / rect.width(),
|
glm::scale(window->screen_to_gl_coords,
|
||||||
-2.0f / rect.height(),
|
glm::vec3{2.0f / rect.width(), -2.0f / rect.height(),
|
||||||
2.0f / (near - far)});
|
2.0f / (near - far)});
|
||||||
window->screen_to_gl_coords = glm::translate(window->screen_to_gl_coords,
|
window->screen_to_gl_coords = glm::translate(
|
||||||
glm::vec3{-rect.left(),
|
window->screen_to_gl_coords, glm::vec3{-rect.left(), -rect.top(), 0.0f});
|
||||||
-rect.top(),
|
|
||||||
0.0f});
|
|
||||||
|
|
||||||
window->viewport = rect;
|
window->viewport = rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::tessellate(std::vector<anbox::graphics::Primitive> &primitives,
|
void Renderer::tessellate(std::vector<anbox::graphics::Primitive> &primitives,
|
||||||
const anbox::graphics::Rect &buf_size,
|
const anbox::graphics::Rect &buf_size,
|
||||||
const Renderable &renderable)
|
const Renderable &renderable) {
|
||||||
{
|
|
||||||
auto rect = renderable.screen_position();
|
auto rect = renderable.screen_position();
|
||||||
GLfloat left = rect.left();
|
GLfloat left = rect.left();
|
||||||
GLfloat right = rect.right();
|
GLfloat right = rect.right();
|
||||||
|
|
@ -1070,10 +1006,8 @@ void Renderer::tessellate(std::vector<anbox::graphics::Primitive>& primitives,
|
||||||
rectangle.tex_id = 0;
|
rectangle.tex_id = 0;
|
||||||
rectangle.type = GL_TRIANGLE_STRIP;
|
rectangle.type = GL_TRIANGLE_STRIP;
|
||||||
|
|
||||||
GLfloat tex_right = static_cast<GLfloat>(rect.width()) /
|
GLfloat tex_right = static_cast<GLfloat>(rect.width()) / buf_size.width();
|
||||||
buf_size.width();
|
GLfloat tex_bottom = static_cast<GLfloat>(rect.height()) / buf_size.height();
|
||||||
GLfloat tex_bottom = static_cast<GLfloat>(rect.height()) /
|
|
||||||
buf_size.height();
|
|
||||||
|
|
||||||
auto &vertices = rectangle.vertices;
|
auto &vertices = rectangle.vertices;
|
||||||
vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}};
|
vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}};
|
||||||
|
|
@ -1085,11 +1019,10 @@ void Renderer::tessellate(std::vector<anbox::graphics::Primitive>& primitives,
|
||||||
primitives[0] = rectangle;
|
primitives[0] = rectangle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::draw(RendererWindow *window, const Renderable &renderable, const Program &prog)
|
void Renderer::draw(RendererWindow *window, const Renderable &renderable,
|
||||||
{
|
const Program &prog) {
|
||||||
const auto &color_buffer = m_colorbuffers.find(renderable.buffer());
|
const auto &color_buffer = m_colorbuffers.find(renderable.buffer());
|
||||||
if (color_buffer == m_colorbuffers.end())
|
if (color_buffer == m_colorbuffers.end()) return;
|
||||||
return;
|
|
||||||
|
|
||||||
const auto &cb = color_buffer->second.cb;
|
const auto &cb = color_buffer->second.cb;
|
||||||
|
|
||||||
|
|
@ -1103,10 +1036,8 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
|
||||||
s_gles2.glActiveTexture(GL_TEXTURE0);
|
s_gles2.glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
auto const &rect = renderable.screen_position();
|
auto const &rect = renderable.screen_position();
|
||||||
GLfloat centerx = rect.left() +
|
GLfloat centerx = rect.left() + rect.width() / 2.0f;
|
||||||
rect.width() / 2.0f;
|
GLfloat centery = rect.top() + rect.height() / 2.0f;
|
||||||
GLfloat centery = rect.top() +
|
|
||||||
rect.height() / 2.0f;
|
|
||||||
s_gles2.glUniform2f(prog.center_uniform, centerx, centery);
|
s_gles2.glUniform2f(prog.center_uniform, centerx, centery);
|
||||||
|
|
||||||
s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE,
|
s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE,
|
||||||
|
|
@ -1121,20 +1052,19 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
|
||||||
m_primitives.clear();
|
m_primitives.clear();
|
||||||
tessellate(m_primitives, {cb->getWidth(), cb->getHeight()}, renderable);
|
tessellate(m_primitives, {cb->getWidth(), cb->getHeight()}, renderable);
|
||||||
|
|
||||||
for (auto const& p : m_primitives)
|
for (auto const &p : m_primitives) {
|
||||||
{
|
|
||||||
cb->bind();
|
cb->bind();
|
||||||
|
|
||||||
s_gles2.glVertexAttribPointer(prog.position_attr, 3, GL_FLOAT,
|
s_gles2.glVertexAttribPointer(prog.position_attr, 3, GL_FLOAT, GL_FALSE,
|
||||||
GL_FALSE, sizeof(anbox::graphics::Vertex),
|
sizeof(anbox::graphics::Vertex),
|
||||||
&p.vertices[0].position);
|
&p.vertices[0].position);
|
||||||
s_gles2.glVertexAttribPointer(prog.texcoord_attr, 2, GL_FLOAT,
|
s_gles2.glVertexAttribPointer(prog.texcoord_attr, 2, GL_FLOAT, GL_FALSE,
|
||||||
GL_FALSE, sizeof(anbox::graphics::Vertex),
|
sizeof(anbox::graphics::Vertex),
|
||||||
&p.vertices[0].texcoord);
|
&p.vertices[0].texcoord);
|
||||||
|
|
||||||
s_gles2.glEnable(GL_BLEND);
|
s_gles2.glEnable(GL_BLEND);
|
||||||
s_gles2.glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA,
|
s_gles2.glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
|
||||||
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
s_gles2.glDrawArrays(p.type, 0, p.nvertices);
|
s_gles2.glDrawArrays(p.type, 0, p.nvertices);
|
||||||
}
|
}
|
||||||
|
|
@ -1143,14 +1073,13 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
|
||||||
s_gles2.glDisableVertexAttribArray(prog.position_attr);
|
s_gles2.glDisableVertexAttribArray(prog.position_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables)
|
bool Renderer::draw(EGLNativeWindowType native_window,
|
||||||
{
|
const anbox::graphics::Rect &window_frame,
|
||||||
|
const RenderableList &renderables) {
|
||||||
auto w = m_nativeWindows.find(native_window);
|
auto w = m_nativeWindows.find(native_window);
|
||||||
if (w == m_nativeWindows.end())
|
if (w == m_nativeWindows.end()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!bindWindow_locked(w->second))
|
if (!bindWindow_locked(w->second)) {
|
||||||
{
|
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,18 @@
|
||||||
#define _LIBRENDER_FRAMEBUFFER_H
|
#define _LIBRENDER_FRAMEBUFFER_H
|
||||||
|
|
||||||
#include "ColorBuffer.h"
|
#include "ColorBuffer.h"
|
||||||
#include "emugl/common/mutex.h"
|
|
||||||
#include "RendererConfig.h"
|
|
||||||
#include "RenderContext.h"
|
#include "RenderContext.h"
|
||||||
|
#include "RendererConfig.h"
|
||||||
#include "TextureDraw.h"
|
#include "TextureDraw.h"
|
||||||
#include "WindowSurface.h"
|
#include "WindowSurface.h"
|
||||||
|
#include "emugl/common/mutex.h"
|
||||||
|
|
||||||
#include "OpenglRender/render_api.h"
|
#include "OpenglRender/render_api.h"
|
||||||
|
|
||||||
#include "Renderable.h"
|
#include "Renderable.h"
|
||||||
|
|
||||||
#include "anbox/graphics/program_family.h"
|
|
||||||
#include "anbox/graphics/primitives.h"
|
#include "anbox/graphics/primitives.h"
|
||||||
|
#include "anbox/graphics/program_family.h"
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
|
|
@ -45,7 +45,8 @@ struct ColorBufferRef {
|
||||||
uint32_t refcount; // number of client-side references
|
uint32_t refcount; // number of client-side references
|
||||||
};
|
};
|
||||||
typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
|
typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
|
||||||
typedef std::map<HandleType, std::pair<WindowSurfacePtr, HandleType> > WindowSurfaceMap;
|
typedef std::map<HandleType, std::pair<WindowSurfacePtr, HandleType>>
|
||||||
|
WindowSurfaceMap;
|
||||||
typedef std::map<HandleType, ColorBufferRef> ColorBufferMap;
|
typedef std::map<HandleType, ColorBufferRef> ColorBufferMap;
|
||||||
|
|
||||||
// A structure used to list the capabilities of the underlying EGL
|
// A structure used to list the capabilities of the underlying EGL
|
||||||
|
|
@ -104,8 +105,7 @@ public:
|
||||||
// Retrieve the GL strings of the underlying EGL/GLES implementation.
|
// Retrieve the GL strings of the underlying EGL/GLES implementation.
|
||||||
// On return, |*vendor|, |*renderer| and |*version| will point to strings
|
// On return, |*vendor|, |*renderer| and |*version| will point to strings
|
||||||
// that are owned by the instance (and must not be freed by the caller).
|
// that are owned by the instance (and must not be freed by the caller).
|
||||||
void getGLStrings(const char** vendor,
|
void getGLStrings(const char** vendor, const char** renderer,
|
||||||
const char** renderer,
|
|
||||||
const char** version) const {
|
const char** version) const {
|
||||||
*vendor = m_glVendor;
|
*vendor = m_glVendor;
|
||||||
*renderer = m_glRenderer;
|
*renderer = m_glRenderer;
|
||||||
|
|
@ -122,8 +122,8 @@ public:
|
||||||
// |p_isGL2| is true to create a GLES 2.x context, or false for a GLES 1.x
|
// |p_isGL2| is true to create a GLES 2.x context, or false for a GLES 1.x
|
||||||
// one.
|
// one.
|
||||||
// Return a new handle value, which will be 0 in case of error.
|
// Return a new handle value, which will be 0 in case of error.
|
||||||
HandleType createRenderContext(
|
HandleType createRenderContext(int p_config, HandleType p_share,
|
||||||
int p_config, HandleType p_share, bool p_isGL2 = false);
|
bool p_isGL2 = false);
|
||||||
|
|
||||||
// Create a new WindowSurface instance from this display instance.
|
// Create a new WindowSurface instance from this display instance.
|
||||||
// |p_config| is the index of one of the configs returned by getConfigs().
|
// |p_config| is the index of one of the configs returned by getConfigs().
|
||||||
|
|
@ -137,8 +137,8 @@ public:
|
||||||
// list of valid values. Note that ColorBuffer instances are reference-
|
// list of valid values. Note that ColorBuffer instances are reference-
|
||||||
// counted. Use openColorBuffer / closeColorBuffer to operate on the
|
// counted. Use openColorBuffer / closeColorBuffer to operate on the
|
||||||
// internal count.
|
// internal count.
|
||||||
HandleType createColorBuffer(
|
HandleType createColorBuffer(int p_width, int p_height,
|
||||||
int p_width, int p_height, GLenum p_internalFormat);
|
GLenum p_internalFormat);
|
||||||
|
|
||||||
// Call this function when a render thread terminates to destroy all
|
// Call this function when a render thread terminates to destroy all
|
||||||
// the remaining contexts it created. Necessary to avoid leaking host
|
// the remaining contexts it created. Necessary to avoid leaking host
|
||||||
|
|
@ -174,8 +174,7 @@ public:
|
||||||
// of the context, the draw surface and the read surface, respectively.
|
// of the context, the draw surface and the read surface, respectively.
|
||||||
// Returns true on success, false on failure.
|
// Returns true on success, false on failure.
|
||||||
// Note: if all handle values are 0, this is an unbind operation.
|
// Note: if all handle values are 0, this is an unbind operation.
|
||||||
bool bindContext(HandleType p_context,
|
bool bindContext(HandleType p_context, HandleType p_drawSurface,
|
||||||
HandleType p_drawSurface,
|
|
||||||
HandleType p_readSurface);
|
HandleType p_readSurface);
|
||||||
|
|
||||||
// Attach a ColorBuffer to a WindowSurface instance.
|
// Attach a ColorBuffer to a WindowSurface instance.
|
||||||
|
|
@ -183,8 +182,8 @@ public:
|
||||||
// |p_surface| is the target WindowSurface's handle value.
|
// |p_surface| is the target WindowSurface's handle value.
|
||||||
// |p_colorbuffer| is the ColorBuffer handle value.
|
// |p_colorbuffer| is the ColorBuffer handle value.
|
||||||
// Returns true on success, false otherwise.
|
// Returns true on success, false otherwise.
|
||||||
bool setWindowSurfaceColorBuffer(
|
bool setWindowSurfaceColorBuffer(HandleType p_surface,
|
||||||
HandleType p_surface, HandleType p_colorbuffer);
|
HandleType p_colorbuffer);
|
||||||
|
|
||||||
// Copy the content of a WindowSurface's Pbuffer to its attached
|
// Copy the content of a WindowSurface's Pbuffer to its attached
|
||||||
// ColorBuffer. See the documentation for WindowSurface::flushColorBuffer()
|
// ColorBuffer. See the documentation for WindowSurface::flushColorBuffer()
|
||||||
|
|
@ -215,9 +214,8 @@ public:
|
||||||
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
|
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
|
||||||
// |pixels| is the address of a caller-provided buffer that will be filled
|
// |pixels| is the address of a caller-provided buffer that will be filled
|
||||||
// with the pixel data.
|
// with the pixel data.
|
||||||
void readColorBuffer(HandleType p_colorbuffer,
|
void readColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
|
||||||
int x, int y, int width, int height,
|
int height, GLenum format, GLenum type, void* pixels);
|
||||||
GLenum format, GLenum type, void *pixels);
|
|
||||||
|
|
||||||
// Update the content of a given ColorBuffer from client data.
|
// Update the content of a given ColorBuffer from client data.
|
||||||
// |p_colorbuffer| is the ColorBuffer's handle value. Similar
|
// |p_colorbuffer| is the ColorBuffer's handle value. Similar
|
||||||
|
|
@ -228,11 +226,12 @@ public:
|
||||||
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
|
// |type| is the type of pixel data, e.g. GL_UNSIGNED_BYTE.
|
||||||
// |pixels| is the address of a buffer containing the new pixel data.
|
// |pixels| is the address of a buffer containing the new pixel data.
|
||||||
// Returns true on success, false otherwise.
|
// Returns true on success, false otherwise.
|
||||||
bool updateColorBuffer(HandleType p_colorbuffer,
|
bool updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width,
|
||||||
int x, int y, int width, int height,
|
int height, GLenum format, GLenum type, void* pixels);
|
||||||
GLenum format, GLenum type, void *pixels);
|
|
||||||
|
|
||||||
bool draw(EGLNativeWindowType native_window, const anbox::graphics::Rect &window_frame, const RenderableList &renderables);
|
bool draw(EGLNativeWindowType native_window,
|
||||||
|
const anbox::graphics::Rect& window_frame,
|
||||||
|
const RenderableList& renderables);
|
||||||
|
|
||||||
// Return the host EGLDisplay used by this instance.
|
// Return the host EGLDisplay used by this instance.
|
||||||
EGLDisplay getDisplay() const { return m_eglDisplay; }
|
EGLDisplay getDisplay() const { return m_eglDisplay; }
|
||||||
|
|
@ -241,7 +240,8 @@ public:
|
||||||
// and windows created by this instance.
|
// and windows created by this instance.
|
||||||
TextureDraw* getTextureDraw() const { return m_textureDraw; }
|
TextureDraw* getTextureDraw() const { return m_textureDraw; }
|
||||||
|
|
||||||
HandleType createClientImage(HandleType context, EGLenum target, GLuint buffer);
|
HandleType createClientImage(HandleType context, EGLenum target,
|
||||||
|
GLuint buffer);
|
||||||
EGLBoolean destroyClientImage(HandleType image);
|
EGLBoolean destroyClientImage(HandleType image);
|
||||||
|
|
||||||
// Used internally.
|
// Used internally.
|
||||||
|
|
@ -257,7 +257,8 @@ private:
|
||||||
|
|
||||||
void setupViewport(RendererWindow* window, const anbox::graphics::Rect& rect);
|
void setupViewport(RendererWindow* window, const anbox::graphics::Rect& rect);
|
||||||
struct Program;
|
struct Program;
|
||||||
void draw(RendererWindow *window, const Renderable &renderable, const Program &prog);
|
void draw(RendererWindow* window, const Renderable& renderable,
|
||||||
|
const Program& prog);
|
||||||
void tessellate(std::vector<anbox::graphics::Primitive>& primitives,
|
void tessellate(std::vector<anbox::graphics::Primitive>& primitives,
|
||||||
const anbox::graphics::Rect& buf_size,
|
const anbox::graphics::Rect& buf_size,
|
||||||
const Renderable& renderable);
|
const Renderable& renderable);
|
||||||
|
|
@ -297,8 +298,7 @@ private:
|
||||||
std::map<EGLNativeWindowType, RendererWindow*> m_nativeWindows;
|
std::map<EGLNativeWindowType, RendererWindow*> m_nativeWindows;
|
||||||
|
|
||||||
anbox::graphics::ProgramFamily m_family;
|
anbox::graphics::ProgramFamily m_family;
|
||||||
struct Program
|
struct Program {
|
||||||
{
|
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
GLint tex_uniform = -1;
|
GLint tex_uniform = -1;
|
||||||
GLint position_attr = -1;
|
GLint position_attr = -1;
|
||||||
|
|
|
||||||
|
|
@ -29,35 +29,17 @@ const GLuint kConfigAttributes[] = {
|
||||||
EGL_RENDERABLE_TYPE, // must be third - see getRenderableType()
|
EGL_RENDERABLE_TYPE, // must be third - see getRenderableType()
|
||||||
EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType()
|
EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType()
|
||||||
EGL_CONFIG_ID, // must be fifth - see chooseConfig()
|
EGL_CONFIG_ID, // must be fifth - see chooseConfig()
|
||||||
EGL_BUFFER_SIZE,
|
EGL_BUFFER_SIZE, EGL_ALPHA_SIZE, EGL_BLUE_SIZE, EGL_GREEN_SIZE,
|
||||||
EGL_ALPHA_SIZE,
|
EGL_RED_SIZE, EGL_CONFIG_CAVEAT, EGL_LEVEL, EGL_MAX_PBUFFER_HEIGHT,
|
||||||
EGL_BLUE_SIZE,
|
EGL_MAX_PBUFFER_PIXELS, EGL_MAX_PBUFFER_WIDTH, EGL_NATIVE_RENDERABLE,
|
||||||
EGL_GREEN_SIZE,
|
EGL_NATIVE_VISUAL_ID, EGL_NATIVE_VISUAL_TYPE, EGL_SAMPLES,
|
||||||
EGL_RED_SIZE,
|
EGL_SAMPLE_BUFFERS, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_BLUE_VALUE,
|
||||||
EGL_CONFIG_CAVEAT,
|
EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_RED_VALUE,
|
||||||
EGL_LEVEL,
|
EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_MIN_SWAP_INTERVAL,
|
||||||
EGL_MAX_PBUFFER_HEIGHT,
|
EGL_MAX_SWAP_INTERVAL, EGL_LUMINANCE_SIZE, EGL_ALPHA_MASK_SIZE,
|
||||||
EGL_MAX_PBUFFER_PIXELS,
|
|
||||||
EGL_MAX_PBUFFER_WIDTH,
|
|
||||||
EGL_NATIVE_RENDERABLE,
|
|
||||||
EGL_NATIVE_VISUAL_ID,
|
|
||||||
EGL_NATIVE_VISUAL_TYPE,
|
|
||||||
EGL_SAMPLES,
|
|
||||||
EGL_SAMPLE_BUFFERS,
|
|
||||||
EGL_TRANSPARENT_TYPE,
|
|
||||||
EGL_TRANSPARENT_BLUE_VALUE,
|
|
||||||
EGL_TRANSPARENT_GREEN_VALUE,
|
|
||||||
EGL_TRANSPARENT_RED_VALUE,
|
|
||||||
EGL_BIND_TO_TEXTURE_RGB,
|
|
||||||
EGL_BIND_TO_TEXTURE_RGBA,
|
|
||||||
EGL_MIN_SWAP_INTERVAL,
|
|
||||||
EGL_MAX_SWAP_INTERVAL,
|
|
||||||
EGL_LUMINANCE_SIZE,
|
|
||||||
EGL_ALPHA_MASK_SIZE,
|
|
||||||
EGL_COLOR_BUFFER_TYPE,
|
EGL_COLOR_BUFFER_TYPE,
|
||||||
// EGL_MATCH_NATIVE_PIXMAP,
|
// EGL_MATCH_NATIVE_PIXMAP,
|
||||||
EGL_CONFORMANT
|
EGL_CONFORMANT};
|
||||||
};
|
|
||||||
|
|
||||||
const size_t kConfigAttributesLen =
|
const size_t kConfigAttributesLen =
|
||||||
sizeof(kConfigAttributes) / sizeof(kConfigAttributes[0]);
|
sizeof(kConfigAttributes) / sizeof(kConfigAttributes[0]);
|
||||||
|
|
@ -66,22 +48,17 @@ bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) {
|
||||||
// Filter out configs which do not support pbuffers, since they
|
// Filter out configs which do not support pbuffers, since they
|
||||||
// are used to implement window surfaces.
|
// are used to implement window surfaces.
|
||||||
EGLint surfaceType;
|
EGLint surfaceType;
|
||||||
s_egl.eglGetConfigAttrib(
|
s_egl.eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
|
||||||
display, config, EGL_SURFACE_TYPE, &surfaceType);
|
|
||||||
if (!(surfaceType & EGL_PBUFFER_BIT)) {
|
if (!(surfaceType & EGL_PBUFFER_BIT)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out configs that do not support RGB pixel values.
|
// Filter out configs that do not support RGB pixel values.
|
||||||
EGLint redSize = 0, greenSize = 0, blueSize = 0, alphaSize = 0;
|
EGLint redSize = 0, greenSize = 0, blueSize = 0, alphaSize = 0;
|
||||||
s_egl.eglGetConfigAttrib(
|
s_egl.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
|
||||||
display, config,EGL_RED_SIZE, &redSize);
|
s_egl.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
|
||||||
s_egl.eglGetConfigAttrib(
|
s_egl.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
|
||||||
display, config, EGL_GREEN_SIZE, &greenSize);
|
s_egl.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
|
||||||
s_egl.eglGetConfigAttrib(
|
|
||||||
display, config, EGL_BLUE_SIZE, &blueSize);
|
|
||||||
s_egl.eglGetConfigAttrib(
|
|
||||||
display, config, EGL_ALPHA_SIZE, &alphaSize);
|
|
||||||
|
|
||||||
if (!redSize || !greenSize || !blueSize || !alphaSize) {
|
if (!redSize || !greenSize || !blueSize || !alphaSize) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -92,18 +69,14 @@ bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RendererConfig::~RendererConfig() {
|
RendererConfig::~RendererConfig() { delete[] mAttribValues; }
|
||||||
delete [] mAttribValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) :
|
RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay)
|
||||||
mEglConfig(hostConfig), mAttribValues(NULL) {
|
: mEglConfig(hostConfig), mAttribValues(NULL) {
|
||||||
mAttribValues = new GLint[kConfigAttributesLen];
|
mAttribValues = new GLint[kConfigAttributesLen];
|
||||||
for (size_t i = 0; i < kConfigAttributesLen; ++i) {
|
for (size_t i = 0; i < kConfigAttributesLen; ++i) {
|
||||||
mAttribValues[i] = 0;
|
mAttribValues[i] = 0;
|
||||||
s_egl.eglGetConfigAttrib(hostDisplay,
|
s_egl.eglGetConfigAttrib(hostDisplay, hostConfig, kConfigAttributes[i],
|
||||||
hostConfig,
|
|
||||||
kConfigAttributes[i],
|
|
||||||
&mAttribValues[i]);
|
&mAttribValues[i]);
|
||||||
|
|
||||||
// This implementation supports guest window surfaces by wrapping
|
// This implementation supports guest window surfaces by wrapping
|
||||||
|
|
@ -114,11 +87,11 @@ RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererConfigList::RendererConfigList(EGLDisplay display) :
|
RendererConfigList::RendererConfigList(EGLDisplay display)
|
||||||
mCount(0), mConfigs(NULL), mDisplay(display) {
|
: mCount(0), mConfigs(NULL), mDisplay(display) {
|
||||||
if (display == EGL_NO_DISPLAY) {
|
if (display == EGL_NO_DISPLAY) {
|
||||||
E("%s: Invalid display value %p (EGL_NO_DISPLAY)\n",
|
E("%s: Invalid display value %p (EGL_NO_DISPLAY)\n", __FUNCTION__,
|
||||||
__FUNCTION__, (void*)display);
|
(void*)display);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,8 +123,7 @@ RendererConfigList::~RendererConfigList() {
|
||||||
delete[] mConfigs;
|
delete[] mConfigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RendererConfigList::chooseConfig(const EGLint* attribs,
|
int RendererConfigList::chooseConfig(const EGLint* attribs, EGLint* configs,
|
||||||
EGLint* configs,
|
|
||||||
EGLint configsSize) const {
|
EGLint configsSize) const {
|
||||||
EGLint numHostConfigs = 0;
|
EGLint numHostConfigs = 0;
|
||||||
if (!s_egl.eglGetConfigs(mDisplay, NULL, 0, &numHostConfigs)) {
|
if (!s_egl.eglGetConfigs(mDisplay, NULL, 0, &numHostConfigs)) {
|
||||||
|
|
@ -201,11 +173,8 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
|
||||||
newAttribs[numAttribs + 2] = EGL_NONE;
|
newAttribs[numAttribs + 2] = EGL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_egl.eglChooseConfig(mDisplay,
|
if (!s_egl.eglChooseConfig(mDisplay, newAttribs ? newAttribs : attribs,
|
||||||
newAttribs ? newAttribs : attribs,
|
matchedConfigs, numHostConfigs, &numHostConfigs)) {
|
||||||
matchedConfigs,
|
|
||||||
numHostConfigs,
|
|
||||||
&numHostConfigs)) {
|
|
||||||
numHostConfigs = 0;
|
numHostConfigs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,8 +193,8 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
|
||||||
}
|
}
|
||||||
// Find the FbConfig with the same EGL_CONFIG_ID
|
// Find the FbConfig with the same EGL_CONFIG_ID
|
||||||
EGLint hostConfigId;
|
EGLint hostConfigId;
|
||||||
s_egl.eglGetConfigAttrib(
|
s_egl.eglGetConfigAttrib(mDisplay, matchedConfigs[n], EGL_CONFIG_ID,
|
||||||
mDisplay, matchedConfigs[n], EGL_CONFIG_ID, &hostConfigId);
|
&hostConfigId);
|
||||||
for (int k = 0; k < mCount; ++k) {
|
for (int k = 0; k < mCount; ++k) {
|
||||||
int guestConfigId = mConfigs[k]->getConfigId();
|
int guestConfigId = mConfigs[k]->getConfigId();
|
||||||
if (guestConfigId == hostConfigId) {
|
if (guestConfigId == hostConfigId) {
|
||||||
|
|
@ -244,7 +213,6 @@ int RendererConfigList::chooseConfig(const EGLint* attribs,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RendererConfigList::getPackInfo(EGLint* numConfigs,
|
void RendererConfigList::getPackInfo(EGLint* numConfigs,
|
||||||
EGLint* numAttributes) const {
|
EGLint* numAttributes) const {
|
||||||
if (numConfigs) {
|
if (numConfigs) {
|
||||||
|
|
@ -255,7 +223,8 @@ void RendererConfigList::getPackInfo(EGLint* numConfigs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLint RendererConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) const {
|
EGLint RendererConfigList::packConfigs(GLuint bufferByteSize,
|
||||||
|
GLuint* buffer) const {
|
||||||
GLuint numAttribs = static_cast<GLuint>(kConfigAttributesLen);
|
GLuint numAttribs = static_cast<GLuint>(kConfigAttributesLen);
|
||||||
GLuint kGLuintSize = static_cast<GLuint>(sizeof(GLuint));
|
GLuint kGLuintSize = static_cast<GLuint>(sizeof(GLuint));
|
||||||
GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize;
|
GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize;
|
||||||
|
|
@ -267,8 +236,7 @@ EGLint RendererConfigList::packConfigs(GLuint bufferByteSize, GLuint* buffer) co
|
||||||
memcpy(buffer, kConfigAttributes, kConfigAttributesLen * kGLuintSize);
|
memcpy(buffer, kConfigAttributes, kConfigAttributesLen * kGLuintSize);
|
||||||
|
|
||||||
for (int i = 0; i < mCount; ++i) {
|
for (int i = 0; i < mCount; ++i) {
|
||||||
memcpy(buffer + (i + 1) * kConfigAttributesLen,
|
memcpy(buffer + (i + 1) * kConfigAttributesLen, mConfigs[i]->mAttribValues,
|
||||||
mConfigs[i]->mAttribValues,
|
|
||||||
kConfigAttributesLen * kGLuintSize);
|
kConfigAttributesLen * kGLuintSize);
|
||||||
}
|
}
|
||||||
return mCount;
|
return mCount;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -15,36 +15,24 @@
|
||||||
*/
|
*/
|
||||||
#include "SocketStream.h"
|
#include "SocketStream.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
SocketStream::SocketStream(size_t bufSize) :
|
SocketStream::SocketStream(size_t bufSize)
|
||||||
IOStream(bufSize),
|
: IOStream(bufSize), m_sock(-1), m_bufsize(bufSize), m_buf(NULL) {}
|
||||||
m_sock(-1),
|
|
||||||
m_bufsize(bufSize),
|
|
||||||
m_buf(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketStream::SocketStream(int sock, size_t bufSize) :
|
SocketStream::SocketStream(int sock, size_t bufSize)
|
||||||
IOStream(bufSize),
|
: IOStream(bufSize), m_sock(sock), m_bufsize(bufSize), m_buf(NULL) {}
|
||||||
m_sock(sock),
|
|
||||||
m_bufsize(bufSize),
|
|
||||||
m_buf(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketStream::~SocketStream()
|
SocketStream::~SocketStream() {
|
||||||
{
|
|
||||||
if (m_sock >= 0) {
|
if (m_sock >= 0) {
|
||||||
forceStop();
|
forceStop();
|
||||||
if(close(m_sock) < 0)
|
if (close(m_sock) < 0) perror("Closing SocketStream failed");
|
||||||
perror("Closing SocketStream failed");
|
|
||||||
// DBG("SocketStream::~close @ %d \n", m_sock);
|
// DBG("SocketStream::~close @ %d \n", m_sock);
|
||||||
m_sock = -1;
|
m_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
@ -54,14 +42,11 @@ SocketStream::~SocketStream()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *SocketStream::allocBuffer(size_t minSize) {
|
||||||
void *SocketStream::allocBuffer(size_t minSize)
|
|
||||||
{
|
|
||||||
size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize);
|
size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize);
|
||||||
if (!m_buf) {
|
if (!m_buf) {
|
||||||
m_buf = (unsigned char *)malloc(allocSize);
|
m_buf = (unsigned char *)malloc(allocSize);
|
||||||
}
|
} else if (m_bufsize < allocSize) {
|
||||||
else if (m_bufsize < allocSize) {
|
|
||||||
unsigned char *p = (unsigned char *)realloc(m_buf, allocSize);
|
unsigned char *p = (unsigned char *)realloc(m_buf, allocSize);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
m_buf = p;
|
m_buf = p;
|
||||||
|
|
@ -77,13 +62,9 @@ void *SocketStream::allocBuffer(size_t minSize)
|
||||||
return m_buf;
|
return m_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
int SocketStream::commitBuffer(size_t size)
|
int SocketStream::commitBuffer(size_t size) { return writeFully(m_buf, size); }
|
||||||
{
|
|
||||||
return writeFully(m_buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SocketStream::writeFully(const void* buffer, size_t size)
|
int SocketStream::writeFully(const void *buffer, size_t size) {
|
||||||
{
|
|
||||||
if (!valid()) return -1;
|
if (!valid()) return -1;
|
||||||
|
|
||||||
size_t res = size;
|
size_t res = size;
|
||||||
|
|
@ -104,8 +85,7 @@ int SocketStream::writeFully(const void* buffer, size_t size)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char *SocketStream::readFully(void *buf, size_t len)
|
const unsigned char *SocketStream::readFully(void *buf, size_t len) {
|
||||||
{
|
|
||||||
if (!valid()) return NULL;
|
if (!valid()) return NULL;
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return NULL; // do not allow NULL buf in that implementation
|
return NULL; // do not allow NULL buf in that implementation
|
||||||
|
|
@ -124,8 +104,7 @@ const unsigned char *SocketStream::readFully(void *buf, size_t len)
|
||||||
return (const unsigned char *)buf;
|
return (const unsigned char *)buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
|
const unsigned char *SocketStream::read(void *buf, size_t *inout_len) {
|
||||||
{
|
|
||||||
if (!valid()) return NULL;
|
if (!valid()) return NULL;
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return NULL; // do not allow NULL buf in that implementation
|
return NULL; // do not allow NULL buf in that implementation
|
||||||
|
|
@ -144,8 +123,7 @@ const unsigned char *SocketStream::read( void *buf, size_t *inout_len)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SocketStream::recv(void *buf, size_t len)
|
int SocketStream::recv(void *buf, size_t len) {
|
||||||
{
|
|
||||||
if (!valid()) return int(ERR_INVALID_SOCKET);
|
if (!valid()) return int(ERR_INVALID_SOCKET);
|
||||||
int res = 0;
|
int res = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
|
@ -29,8 +29,7 @@
|
||||||
|
|
||||||
TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {}
|
TcpStream::TcpStream(size_t bufSize) : SocketStream(bufSize) {}
|
||||||
|
|
||||||
TcpStream::TcpStream(int sock, size_t bufSize) :
|
TcpStream::TcpStream(int sock, size_t bufSize) : SocketStream(sock, bufSize) {
|
||||||
SocketStream(sock, bufSize) {
|
|
||||||
// disable Nagle algorithm to improve bandwidth of small
|
// disable Nagle algorithm to improve bandwidth of small
|
||||||
// packets which are quite common in our implementation.
|
// packets which are quite common in our implementation.
|
||||||
emugl::socketTcpDisableNagle(sock);
|
emugl::socketTcpDisableNagle(sock);
|
||||||
|
|
@ -38,8 +37,7 @@ TcpStream::TcpStream(int sock, size_t bufSize) :
|
||||||
|
|
||||||
int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
|
int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
|
||||||
m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM);
|
m_sock = emugl::socketTcpLoopbackServer(0, SOCK_STREAM);
|
||||||
if (!valid())
|
if (!valid()) return int(ERR_INVALID_SOCKET);
|
||||||
return int(ERR_INVALID_SOCKET);
|
|
||||||
|
|
||||||
int port = emugl::socketGetPort(m_sock);
|
int port = emugl::socketGetPort(m_sock);
|
||||||
if (port < 0) {
|
if (port < 0) {
|
||||||
|
|
@ -55,8 +53,7 @@ int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
|
||||||
|
|
||||||
SocketStream* TcpStream::accept() {
|
SocketStream* TcpStream::accept() {
|
||||||
int clientSock = emugl::socketAccept(m_sock);
|
int clientSock = emugl::socketAccept(m_sock);
|
||||||
if (clientSock < 0)
|
if (clientSock < 0) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return new TcpStream(clientSock, m_bufsize);
|
return new TcpStream(clientSock, m_bufsize);
|
||||||
}
|
}
|
||||||
|
|
@ -67,8 +64,7 @@ int TcpStream::connect(const char* addr) {
|
||||||
return valid() ? 0 : -1;
|
return valid() ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TcpStream::connect(const char* hostname, unsigned short port)
|
int TcpStream::connect(const char* hostname, unsigned short port) {
|
||||||
{
|
|
||||||
m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM);
|
m_sock = emugl::socketTcpClient(hostname, port, SOCK_STREAM);
|
||||||
return valid() ? 0 : -1;
|
return valid() ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ public:
|
||||||
virtual SocketStream* accept();
|
virtual SocketStream* accept();
|
||||||
virtual int connect(const char* addr);
|
virtual int connect(const char* addr);
|
||||||
int connect(const char* hostname, unsigned short port);
|
int connect(const char* hostname, unsigned short port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TcpStream(int sock, size_t bufSize);
|
TcpStream(int sock, size_t bufSize);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,8 @@ const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TextureDraw::TextureDraw(EGLDisplay display) :
|
TextureDraw::TextureDraw(EGLDisplay display)
|
||||||
mDisplay(display),
|
: mDisplay(display),
|
||||||
mVertexShader(0),
|
mVertexShader(0),
|
||||||
mFragmentShader(0),
|
mFragmentShader(0),
|
||||||
mProgram(0),
|
mProgram(0),
|
||||||
|
|
@ -119,8 +119,7 @@ TextureDraw::TextureDraw(EGLDisplay display) :
|
||||||
s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
|
s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
|
||||||
if (success == GL_FALSE) {
|
if (success == GL_FALSE) {
|
||||||
GLchar messages[256];
|
GLchar messages[256];
|
||||||
s_gles2.glGetProgramInfoLog(
|
s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
|
||||||
mProgram, sizeof(messages), 0, &messages[0]);
|
|
||||||
ERR("%s: Could not create/link program: %s\n", __FUNCTION__, messages);
|
ERR("%s: Could not create/link program: %s\n", __FUNCTION__, messages);
|
||||||
s_gles2.glDeleteProgram(mProgram);
|
s_gles2.glDeleteProgram(mProgram);
|
||||||
mProgram = 0;
|
mProgram = 0;
|
||||||
|
|
@ -141,14 +140,12 @@ TextureDraw::TextureDraw(EGLDisplay display) :
|
||||||
// Create vertex and index buffers.
|
// Create vertex and index buffers.
|
||||||
s_gles2.glGenBuffers(1, &mVertexBuffer);
|
s_gles2.glGenBuffers(1, &mVertexBuffer);
|
||||||
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
|
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
|
||||||
s_gles2.glBufferData(
|
s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices,
|
||||||
GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
s_gles2.glGenBuffers(1, &mIndexBuffer);
|
s_gles2.glGenBuffers(1, &mIndexBuffer);
|
||||||
s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
||||||
s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndices), kIndices,
|
||||||
sizeof(kIndices),
|
|
||||||
kIndices,
|
|
||||||
GL_STATIC_DRAW);
|
GL_STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,26 +162,19 @@ bool TextureDraw::draw(GLuint texture) {
|
||||||
s_gles2.glUseProgram(mProgram);
|
s_gles2.glUseProgram(mProgram);
|
||||||
err = s_gles2.glGetError();
|
err = s_gles2.glGetError();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
ERR("%s: Could not use program error=0x%x\n",
|
ERR("%s: Could not use program error=0x%x\n", __FUNCTION__, err);
|
||||||
__FUNCTION__, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Setup the |position| attribute values.
|
// Setup the |position| attribute values.
|
||||||
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
|
s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
|
||||||
err = s_gles2.glGetError();
|
err = s_gles2.glGetError();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n",
|
ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n", __FUNCTION__, err);
|
||||||
__FUNCTION__, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s_gles2.glEnableVertexAttribArray(mPositionSlot);
|
s_gles2.glEnableVertexAttribArray(mPositionSlot);
|
||||||
s_gles2.glVertexAttribPointer(mPositionSlot,
|
s_gles2.glVertexAttribPointer(mPositionSlot, 3, GL_FLOAT, GL_FALSE,
|
||||||
3,
|
sizeof(Vertex), 0);
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
sizeof(Vertex),
|
|
||||||
0);
|
|
||||||
err = s_gles2.glGetError();
|
err = s_gles2.glGetError();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n",
|
ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n",
|
||||||
|
|
@ -193,14 +183,9 @@ bool TextureDraw::draw(GLuint texture) {
|
||||||
|
|
||||||
// Setup the |inCoord| attribute values.
|
// Setup the |inCoord| attribute values.
|
||||||
s_gles2.glEnableVertexAttribArray(mInCoordSlot);
|
s_gles2.glEnableVertexAttribArray(mInCoordSlot);
|
||||||
s_gles2.glVertexAttribPointer(mInCoordSlot,
|
s_gles2.glVertexAttribPointer(
|
||||||
2,
|
mInCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||||
GL_FLOAT,
|
reinterpret_cast<GLvoid*>(static_cast<uintptr_t>(sizeof(float) * 3)));
|
||||||
GL_FALSE,
|
|
||||||
sizeof(Vertex),
|
|
||||||
reinterpret_cast<GLvoid*>(
|
|
||||||
static_cast<uintptr_t>(
|
|
||||||
sizeof(float) * 3)));
|
|
||||||
|
|
||||||
// setup the |texture| uniform value.
|
// setup the |texture| uniform value.
|
||||||
s_gles2.glActiveTexture(GL_TEXTURE0);
|
s_gles2.glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
@ -213,8 +198,7 @@ bool TextureDraw::draw(GLuint texture) {
|
||||||
s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState);
|
s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState);
|
||||||
if (validState == GL_FALSE) {
|
if (validState == GL_FALSE) {
|
||||||
GLchar messages[256];
|
GLchar messages[256];
|
||||||
s_gles2.glGetProgramInfoLog(
|
s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
|
||||||
mProgram, sizeof(messages), 0, &messages[0]);
|
|
||||||
ERR("%s: Could not run program: %s\n", __FUNCTION__, messages);
|
ERR("%s: Could not run program: %s\n", __FUNCTION__, messages);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -230,8 +214,7 @@ bool TextureDraw::draw(GLuint texture) {
|
||||||
s_gles2.glDrawElements(GL_TRIANGLES, kIndicesLen, GL_UNSIGNED_BYTE, 0);
|
s_gles2.glDrawElements(GL_TRIANGLES, kIndicesLen, GL_UNSIGNED_BYTE, 0);
|
||||||
err = s_gles2.glGetError();
|
err = s_gles2.glGetError();
|
||||||
if (err != GL_NO_ERROR) {
|
if (err != GL_NO_ERROR) {
|
||||||
ERR("%s: Could not glDrawElements() error=0x%x\n",
|
ERR("%s: Could not glDrawElements() error=0x%x\n", __FUNCTION__, err);
|
||||||
__FUNCTION__, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(digit): Restore previous program state.
|
// TODO(digit): Restore previous program state.
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,13 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
/* Not all systems define PATH_MAX, those who don't generally don't
|
/* Not all systems define PATH_MAX, those who don't generally don't
|
||||||
* have a limit on the maximum path size, so use a value that is
|
* have a limit on the maximum path size, so use a value that is
|
||||||
|
|
@ -36,20 +36,13 @@
|
||||||
#define PATH_MAX 128
|
#define PATH_MAX 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UnixStream::UnixStream(size_t bufSize) :
|
UnixStream::UnixStream(size_t bufSize)
|
||||||
SocketStream(bufSize),
|
: SocketStream(bufSize), bound_socket_path(NULL) {}
|
||||||
bound_socket_path(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UnixStream::UnixStream(int sock, size_t bufSize) :
|
UnixStream::UnixStream(int sock, size_t bufSize)
|
||||||
SocketStream(sock, bufSize),
|
: SocketStream(sock, bufSize), bound_socket_path(NULL) {}
|
||||||
bound_socket_path(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
UnixStream::~UnixStream()
|
UnixStream::~UnixStream() {
|
||||||
{
|
|
||||||
if (bound_socket_path != NULL) {
|
if (bound_socket_path != NULL) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
do {
|
do {
|
||||||
|
|
@ -66,9 +59,7 @@ UnixStream::~UnixStream()
|
||||||
/* Initialize a sockaddr_un with the appropriate values corresponding
|
/* Initialize a sockaddr_un with the appropriate values corresponding
|
||||||
* to a given 'virtual port'. Returns 0 on success, -1 on error.
|
* to a given 'virtual port'. Returns 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int make_unix_path(char *path, size_t pathlen, int port_number) {
|
||||||
make_unix_path(char *path, size_t pathlen, int port_number)
|
|
||||||
{
|
|
||||||
char tmp[PATH_MAX]; // temp directory
|
char tmp[PATH_MAX]; // temp directory
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
@ -89,8 +80,7 @@ make_unix_path(char *path, size_t pathlen, int port_number)
|
||||||
ERR("Could not create temp directory: %s", tmp);
|
ERR("Could not create temp directory: %s", tmp);
|
||||||
user = NULL; // will fall-back to /tmp
|
user = NULL; // will fall-back to /tmp
|
||||||
}
|
}
|
||||||
}
|
} else if (ret < 0) {
|
||||||
else if (ret < 0) {
|
|
||||||
user = NULL; // will fallback to /tmp
|
user = NULL; // will fallback to /tmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +99,8 @@ make_unix_path(char *path, size_t pathlen, int port_number)
|
||||||
if (::access(path, F_OK) == 0) {
|
if (::access(path, F_OK) == 0) {
|
||||||
ret = ::remove(path);
|
ret = ::remove(path);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ERR("Failed to remove stale socket file at %s: %s\n", path, strerror(errno));
|
ERR("Failed to remove stale socket file at %s: %s\n", path,
|
||||||
|
strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
DBG("Stale socket file at %s was removed.\n", path);
|
DBG("Stale socket file at %s was removed.\n", path);
|
||||||
}
|
}
|
||||||
|
|
@ -118,17 +109,14 @@ make_unix_path(char *path, size_t pathlen, int port_number)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN]) {
|
||||||
int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
|
|
||||||
{
|
|
||||||
if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) {
|
if (make_unix_path(addrstr, MAX_ADDRSTR_LEN, getpid()) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM);
|
m_sock = emugl::socketLocalServer(addrstr, SOCK_STREAM);
|
||||||
|
|
||||||
if (!valid())
|
if (!valid()) return int(ERR_INVALID_SOCKET);
|
||||||
return int(ERR_INVALID_SOCKET);
|
|
||||||
|
|
||||||
bound_socket_path = strdup(addrstr);
|
bound_socket_path = strdup(addrstr);
|
||||||
if (bound_socket_path == NULL) {
|
if (bound_socket_path == NULL) {
|
||||||
|
|
@ -140,8 +128,7 @@ int UnixStream::listen(char addrstr[MAX_ADDRSTR_LEN])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketStream * UnixStream::accept()
|
SocketStream *UnixStream::accept() {
|
||||||
{
|
|
||||||
int clientSock = -1;
|
int clientSock = -1;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -164,8 +151,7 @@ SocketStream * UnixStream::accept()
|
||||||
return clientStream;
|
return clientStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UnixStream::connect(const char* addr)
|
int UnixStream::connect(const char *addr) {
|
||||||
{
|
|
||||||
m_sock = emugl::socketLocalClient(addr, SOCK_STREAM);
|
m_sock = emugl::socketLocalClient(addr, SOCK_STREAM);
|
||||||
// DBG("UnixStream::connect @ %d \n", m_sock);
|
// DBG("UnixStream::connect @ %d \n", m_sock);
|
||||||
if (!valid()) return -1;
|
if (!valid()) return -1;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ public:
|
||||||
virtual int listen(char addrstr[MAX_ADDRSTR_LEN]);
|
virtual int listen(char addrstr[MAX_ADDRSTR_LEN]);
|
||||||
virtual SocketStream *accept();
|
virtual SocketStream *accept();
|
||||||
virtual int connect(const char *addr);
|
virtual int connect(const char *addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *bound_socket_path;
|
char *bound_socket_path;
|
||||||
UnixStream(int sock, size_t bufSize);
|
UnixStream(int sock, size_t bufSize);
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
WindowSurface::WindowSurface(EGLDisplay display, EGLConfig config)
|
||||||
WindowSurface::WindowSurface(EGLDisplay display,
|
: mSurface(NULL),
|
||||||
EGLConfig config) :
|
|
||||||
mSurface(NULL),
|
|
||||||
mAttachedColorBuffer(NULL),
|
mAttachedColorBuffer(NULL),
|
||||||
mReadContext(NULL),
|
mReadContext(NULL),
|
||||||
mDrawContext(NULL),
|
mDrawContext(NULL),
|
||||||
|
|
@ -43,10 +41,8 @@ WindowSurface::~WindowSurface() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowSurface *WindowSurface::create(EGLDisplay display,
|
WindowSurface *WindowSurface::create(EGLDisplay display, EGLConfig config,
|
||||||
EGLConfig config,
|
int p_width, int p_height) {
|
||||||
int p_width,
|
|
||||||
int p_height) {
|
|
||||||
// allocate space for the WindowSurface object
|
// allocate space for the WindowSurface object
|
||||||
WindowSurface *win = new WindowSurface(display, config);
|
WindowSurface *win = new WindowSurface(display, config);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
|
|
@ -63,7 +59,6 @@ WindowSurface *WindowSurface::create(EGLDisplay display,
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) {
|
void WindowSurface::setColorBuffer(ColorBufferPtr p_colorBuffer) {
|
||||||
mAttachedColorBuffer = p_colorBuffer;
|
mAttachedColorBuffer = p_colorBuffer;
|
||||||
|
|
||||||
|
|
@ -113,9 +108,7 @@ bool WindowSurface::flushColorBuffer() {
|
||||||
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
||||||
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
||||||
|
|
||||||
if (!s_egl.eglMakeCurrent(mDisplay,
|
if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface,
|
||||||
mSurface,
|
|
||||||
mSurface,
|
|
||||||
mDrawContext->getEGLContext())) {
|
mDrawContext->getEGLContext())) {
|
||||||
fprintf(stderr, "Error making draw context current\n");
|
fprintf(stderr, "Error making draw context current\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -129,8 +122,7 @@ bool WindowSurface::flushColorBuffer() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
|
bool WindowSurface::resize(unsigned int p_width, unsigned int p_height) {
|
||||||
{
|
|
||||||
if (mSurface && mWidth == p_width && mHeight == p_height) {
|
if (mSurface && mWidth == p_width && mHeight == p_height) {
|
||||||
// no need to resize
|
// no need to resize
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -140,13 +132,12 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
|
||||||
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
|
||||||
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
|
||||||
EGLSurface prevPbuf = mSurface;
|
EGLSurface prevPbuf = mSurface;
|
||||||
bool needRebindContext = mSurface &&
|
bool needRebindContext =
|
||||||
(prevReadSurf == mSurface ||
|
mSurface && (prevReadSurf == mSurface || prevDrawSurf == mSurface);
|
||||||
prevDrawSurf == mSurface);
|
|
||||||
|
|
||||||
if (needRebindContext) {
|
if (needRebindContext) {
|
||||||
s_egl.eglMakeCurrent(
|
s_egl.eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||||
mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -164,9 +155,7 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
|
||||||
EGL_WIDTH, (EGLint)p_width, EGL_HEIGHT, (EGLint)p_height, EGL_NONE,
|
EGL_WIDTH, (EGLint)p_width, EGL_HEIGHT, (EGLint)p_height, EGL_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
mSurface = s_egl.eglCreatePbufferSurface(mDisplay,
|
mSurface = s_egl.eglCreatePbufferSurface(mDisplay, mConfig, pbufAttribs);
|
||||||
mConfig,
|
|
||||||
pbufAttribs);
|
|
||||||
if (mSurface == EGL_NO_SURFACE) {
|
if (mSurface == EGL_NO_SURFACE) {
|
||||||
fprintf(stderr, "Renderer error: failed to create/resize pbuffer!!\n");
|
fprintf(stderr, "Renderer error: failed to create/resize pbuffer!!\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -177,10 +166,8 @@ bool WindowSurface::resize(unsigned int p_width, unsigned int p_height)
|
||||||
|
|
||||||
if (needRebindContext) {
|
if (needRebindContext) {
|
||||||
s_egl.eglMakeCurrent(
|
s_egl.eglMakeCurrent(
|
||||||
mDisplay,
|
mDisplay, (prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf,
|
||||||
(prevDrawSurf == prevPbuf) ? mSurface : prevDrawSurf,
|
(prevReadSurf == prevPbuf) ? mSurface : prevReadSurf, prevContext);
|
||||||
(prevReadSurf == prevPbuf) ? mSurface : prevReadSurf,
|
|
||||||
prevContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,7 @@ public:
|
||||||
// |config| is the host EGLConfig value.
|
// |config| is the host EGLConfig value.
|
||||||
// |width| and |height| are the initial size of the Pbuffer.
|
// |width| and |height| are the initial size of the Pbuffer.
|
||||||
// Return a new WindowSurface instance on success, or NULL on failure.
|
// Return a new WindowSurface instance on success, or NULL on failure.
|
||||||
static WindowSurface* create(EGLDisplay display,
|
static WindowSurface* create(EGLDisplay display, EGLConfig config, int width,
|
||||||
EGLConfig config,
|
|
||||||
int width,
|
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
// Destructor.
|
// Destructor.
|
||||||
|
|
@ -58,11 +56,7 @@ public:
|
||||||
bool flushColorBuffer();
|
bool flushColorBuffer();
|
||||||
|
|
||||||
// Used by bind() below.
|
// Used by bind() below.
|
||||||
enum BindType {
|
enum BindType { BIND_READ, BIND_DRAW, BIND_READDRAW };
|
||||||
BIND_READ,
|
|
||||||
BIND_DRAW,
|
|
||||||
BIND_READDRAW
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(digit): What is this used for exactly? For example, the
|
// TODO(digit): What is this used for exactly? For example, the
|
||||||
// mReadContext is never used by this class. The mDrawContext is only
|
// mReadContext is never used by this class. The mDrawContext is only
|
||||||
|
|
|
||||||
|
|
@ -15,46 +15,52 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/logger.h"
|
|
||||||
#include "anbox/graphics/gl_renderer_server.h"
|
#include "anbox/graphics/gl_renderer_server.h"
|
||||||
#include "anbox/graphics/layer_composer.h"
|
|
||||||
#include "anbox/graphics/emugl/RenderControl.h"
|
#include "anbox/graphics/emugl/RenderControl.h"
|
||||||
|
#include "anbox/graphics/layer_composer.h"
|
||||||
|
#include "anbox/logger.h"
|
||||||
#include "anbox/wm/manager.h"
|
#include "anbox/wm/manager.h"
|
||||||
|
|
||||||
#include "OpenglRender/render_api.h"
|
#include "OpenglRender/render_api.h"
|
||||||
|
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm) :
|
GLRendererServer::GLRendererServer(const std::shared_ptr<wm::Manager> &wm)
|
||||||
wm_(wm),
|
: wm_(wm), composer_(std::make_shared<LayerComposer>(wm)) {
|
||||||
composer_(std::make_shared<LayerComposer>(wm))
|
|
||||||
{
|
|
||||||
|
|
||||||
if (utils::is_env_set("USE_HOST_GLES")) {
|
if (utils::is_env_set("USE_HOST_GLES")) {
|
||||||
// Force the host EGL/GLES libraries as translator implementation
|
// Force the host EGL/GLES libraries as translator implementation
|
||||||
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0);
|
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 0);
|
||||||
::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0);
|
::setenv("ANDROID_GLESv1_LIB", "libGLESv2.so.2", 0);
|
||||||
::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0);
|
::setenv("ANDROID_GLESv2_LIB", "libGLESv2.so.2", 0);
|
||||||
} else {
|
} else {
|
||||||
auto translator_dir = utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP");
|
auto translator_dir =
|
||||||
::setenv("ANDROID_EGL_LIB", utils::string_format("%s/libEGL_translator.so", translator_dir).c_str(), 0);
|
utils::prefix_dir_from_env(TRANSLATOR_INSTALL_DIR, "SNAP");
|
||||||
::setenv("ANDROID_GLESv1_LIB", utils::string_format("%s/libGLES_CM_translator.so", translator_dir).c_str(), 0);
|
::setenv(
|
||||||
::setenv("ANDROID_GLESv2_LIB", utils::string_format("%s/libGLES_V2_translator.so", translator_dir).c_str(), 0);
|
"ANDROID_EGL_LIB",
|
||||||
|
utils::string_format("%s/libEGL_translator.so", translator_dir).c_str(),
|
||||||
|
0);
|
||||||
|
::setenv("ANDROID_GLESv1_LIB",
|
||||||
|
utils::string_format("%s/libGLES_CM_translator.so", translator_dir)
|
||||||
|
.c_str(),
|
||||||
|
0);
|
||||||
|
::setenv("ANDROID_GLESv2_LIB",
|
||||||
|
utils::string_format("%s/libGLES_V2_translator.so", translator_dir)
|
||||||
|
.c_str(),
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initLibrary())
|
if (!initLibrary())
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer"));
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Failed to initialize OpenGL renderer"));
|
||||||
|
|
||||||
registerLayerComposer(composer_);
|
registerLayerComposer(composer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLRendererServer::~GLRendererServer() {
|
GLRendererServer::~GLRendererServer() { stopOpenGLRenderer(); }
|
||||||
stopOpenGLRenderer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void logger_write(const char *format, ...) {
|
void logger_write(const char *format, ...) {
|
||||||
char message[2048];
|
char message[2048];
|
||||||
|
|
@ -73,17 +79,19 @@ void GLRendererServer::start() {
|
||||||
log_funcs.fine = logger_write;
|
log_funcs.fine = logger_write;
|
||||||
|
|
||||||
char server_addr[256] = {0};
|
char server_addr[256] = {0};
|
||||||
// The width & height we supply here are the dimensions the internal framebuffer
|
// The width & height we supply here are the dimensions the internal
|
||||||
// will use. Making this static prevents us for now to resize the window we create
|
// framebuffer
|
||||||
|
// will use. Making this static prevents us for now to resize the window we
|
||||||
|
// create
|
||||||
// later for the actual display.
|
// later for the actual display.
|
||||||
if (!initOpenGLRenderer(0, server_addr, sizeof(server_addr), log_funcs, logger_write))
|
if (!initOpenGLRenderer(0, server_addr, sizeof(server_addr), log_funcs,
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup OpenGL renderer"));
|
logger_write))
|
||||||
|
BOOST_THROW_EXCEPTION(
|
||||||
|
std::runtime_error("Failed to setup OpenGL renderer"));
|
||||||
|
|
||||||
socket_path_ = server_addr;
|
socket_path_ = server_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLRendererServer::socket_path() const {
|
std::string GLRendererServer::socket_path() const { return socket_path_; }
|
||||||
return socket_path_;
|
|
||||||
}
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
#ifndef ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
||||||
#define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
#define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace input {
|
namespace input {
|
||||||
|
|
|
||||||
|
|
@ -17,36 +17,31 @@
|
||||||
|
|
||||||
#include "anbox/graphics/layer_composer.h"
|
#include "anbox/graphics/layer_composer.h"
|
||||||
#include "anbox/graphics/emugl/Renderer.h"
|
#include "anbox/graphics/emugl/Renderer.h"
|
||||||
#include "anbox/wm/manager.h"
|
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
#include "anbox/wm/manager.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
LayerComposer::LayerComposer(const std::shared_ptr<wm::Manager> &wm) :
|
LayerComposer::LayerComposer(const std::shared_ptr<wm::Manager> &wm)
|
||||||
wm_(wm)
|
: wm_(wm) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerComposer::~LayerComposer()
|
LayerComposer::~LayerComposer() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayerComposer::submit_layers(const RenderableList &renderables)
|
void LayerComposer::submit_layers(const RenderableList &renderables) {
|
||||||
{
|
|
||||||
std::map<std::shared_ptr<wm::Window>, RenderableList> win_layers;
|
std::map<std::shared_ptr<wm::Window>, RenderableList> win_layers;
|
||||||
for (const auto &renderable : renderables)
|
for (const auto &renderable : renderables) {
|
||||||
{
|
|
||||||
// Ignore all surfaces which are not meant for a task
|
// Ignore all surfaces which are not meant for a task
|
||||||
if (!utils::string_starts_with(renderable.name(), "org.anbox.surface."))
|
if (!utils::string_starts_with(renderable.name(), "org.anbox.surface."))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wm::Task::Id task_id = 0;
|
wm::Task::Id task_id = 0;
|
||||||
if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) != 1 || !task_id)
|
if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) !=
|
||||||
|
1 ||
|
||||||
|
!task_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto w = wm_->find_window_for_task(task_id);
|
auto w = wm_->find_window_for_task(task_id);
|
||||||
if (!w)
|
if (!w) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (win_layers.find(w) == win_layers.end()) {
|
if (win_layers.find(w) == win_layers.end()) {
|
||||||
win_layers.insert({w, {renderable}});
|
win_layers.insert({w, {renderable}});
|
||||||
|
|
@ -56,23 +51,20 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
|
||||||
win_layers[w].push_back(renderable);
|
win_layers[w].push_back(renderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &w : win_layers)
|
for (const auto &w : win_layers) {
|
||||||
{
|
|
||||||
const auto &window = w.first;
|
const auto &window = w.first;
|
||||||
const auto &renderables = w.second;
|
const auto &renderables = w.second;
|
||||||
RenderableList final_renderables;
|
RenderableList final_renderables;
|
||||||
auto new_window_frame = Rect::Invalid;
|
auto new_window_frame = Rect::Invalid;
|
||||||
|
|
||||||
for (auto &r : renderables)
|
for (auto &r : renderables) {
|
||||||
{
|
|
||||||
if (new_window_frame == Rect::Invalid)
|
if (new_window_frame == Rect::Invalid)
|
||||||
new_window_frame = r.screen_position();
|
new_window_frame = r.screen_position();
|
||||||
else
|
else
|
||||||
new_window_frame.merge(r.screen_position());
|
new_window_frame.merge(r.screen_position());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &r : renderables)
|
for (auto &r : renderables) {
|
||||||
{
|
|
||||||
// As we get absolute display coordinates from the Android hwcomposer we
|
// As we get absolute display coordinates from the Android hwcomposer we
|
||||||
// need to recalculate all layer coordinates into relatives ones to the
|
// need to recalculate all layer coordinates into relatives ones to the
|
||||||
// window they are drawn into.
|
// window they are drawn into.
|
||||||
|
|
@ -80,8 +72,7 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
|
||||||
auto top = r.screen_position().top() - new_window_frame.top();
|
auto top = r.screen_position().top() - new_window_frame.top();
|
||||||
|
|
||||||
auto rect = Rect{
|
auto rect = Rect{
|
||||||
left - r.crop().left(),
|
left - r.crop().left(), top - r.crop().top(),
|
||||||
top - r.crop().top(),
|
|
||||||
r.screen_position().width() + left,
|
r.screen_position().width() + left,
|
||||||
r.screen_position().height() + top,
|
r.screen_position().height() + top,
|
||||||
};
|
};
|
||||||
|
|
@ -93,7 +84,8 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
|
||||||
|
|
||||||
w.first->update_frame(new_window_frame);
|
w.first->update_frame(new_window_frame);
|
||||||
|
|
||||||
Renderer::get()->draw(window->native_handle(),
|
Renderer::get()->draw(
|
||||||
|
window->native_handle(),
|
||||||
Rect{0, 0, window->frame().width(), window->frame().height()},
|
Rect{0, 0, window->frame().width(), window->frame().height()},
|
||||||
final_renderables);
|
final_renderables);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,43 +15,44 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/logger.h"
|
|
||||||
#include "anbox/graphics/opengles_message_processor.h"
|
#include "anbox/graphics/opengles_message_processor.h"
|
||||||
#include "anbox/network/local_socket_messenger.h"
|
#include "anbox/logger.h"
|
||||||
#include "anbox/network/connections.h"
|
#include "anbox/network/connections.h"
|
||||||
#include "anbox/network/delegate_message_processor.h"
|
#include "anbox/network/delegate_message_processor.h"
|
||||||
|
#include "anbox/network/local_socket_messenger.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
OpenGlesMessageProcessor::OpenGlesMessageProcessor(const std::string &renderer_socket_path,
|
OpenGlesMessageProcessor::OpenGlesMessageProcessor(
|
||||||
const std::shared_ptr<Runtime> &rt,
|
const std::string &renderer_socket_path, const std::shared_ptr<Runtime> &rt,
|
||||||
const std::shared_ptr<network::SocketMessenger> &messenger) :
|
const std::shared_ptr<network::SocketMessenger> &messenger)
|
||||||
client_messenger_(messenger) {
|
: client_messenger_(messenger) {
|
||||||
|
|
||||||
connect_and_attach(renderer_socket_path, rt);
|
connect_and_attach(renderer_socket_path, rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGlesMessageProcessor::~OpenGlesMessageProcessor() {
|
OpenGlesMessageProcessor::~OpenGlesMessageProcessor() {}
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path,
|
void OpenGlesMessageProcessor::connect_and_attach(
|
||||||
const std::shared_ptr<Runtime> &rt) {
|
const std::string &socket_path, const std::shared_ptr<Runtime> &rt) {
|
||||||
|
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(
|
||||||
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(rt->service());
|
rt->service());
|
||||||
socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path));
|
socket->connect(boost::asio::local::stream_protocol::endpoint(socket_path));
|
||||||
|
|
||||||
messenger_ = std::make_shared<network::LocalSocketMessenger>(socket);
|
messenger_ = std::make_shared<network::LocalSocketMessenger>(socket);
|
||||||
renderer_ = std::make_shared<network::SocketConnection>(
|
renderer_ = std::make_shared<network::SocketConnection>(
|
||||||
messenger_, messenger_, 0, nullptr,
|
messenger_, messenger_, 0, nullptr,
|
||||||
std::make_shared<network::DelegateMessageProcessor>([&](const std::vector<std::uint8_t> &data) {
|
std::make_shared<network::DelegateMessageProcessor>(
|
||||||
client_messenger_->send(reinterpret_cast<const char*>(data.data()), data.size());
|
[&](const std::vector<std::uint8_t> &data) {
|
||||||
|
client_messenger_->send(reinterpret_cast<const char *>(data.data()),
|
||||||
|
data.size());
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
renderer_->set_name("opengles-renderer");
|
renderer_->set_name("opengles-renderer");
|
||||||
renderer_->read_next_message();
|
renderer_->read_next_message();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGlesMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
bool OpenGlesMessageProcessor::process_data(
|
||||||
|
const std::vector<std::uint8_t> &data) {
|
||||||
messenger_->send(reinterpret_cast<const char *>(data.data()), data.size());
|
messenger_->send(reinterpret_cast<const char *>(data.data()), data.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,17 @@
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
#include "anbox/runtime.h"
|
|
||||||
#include "anbox/network/message_processor.h"
|
#include "anbox/network/message_processor.h"
|
||||||
#include "anbox/network/socket_messenger.h"
|
|
||||||
#include "anbox/network/socket_connection.h"
|
#include "anbox/network/socket_connection.h"
|
||||||
|
#include "anbox/network/socket_messenger.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
class OpenGlesMessageProcessor : public network::MessageProcessor {
|
class OpenGlesMessageProcessor : public network::MessageProcessor {
|
||||||
public:
|
public:
|
||||||
OpenGlesMessageProcessor(const std::string &renderer_socket_path,
|
OpenGlesMessageProcessor(
|
||||||
|
const std::string &renderer_socket_path,
|
||||||
const std::shared_ptr<Runtime> &rt,
|
const std::shared_ptr<Runtime> &rt,
|
||||||
const std::shared_ptr<network::SocketMessenger> &messenger);
|
const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||||
~OpenGlesMessageProcessor();
|
~OpenGlesMessageProcessor();
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
* Kevin DuBois <kevin.dubois@canonical.com>
|
* Kevin DuBois <kevin.dubois@canonical.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef ANBOX_GRAPHICS_PRIMITIVES_H_
|
#ifndef ANBOX_GRAPHICS_PRIMITIVES_H_
|
||||||
#define ANBOX_GRAPHICS_PRIMITIVES_H_
|
#define ANBOX_GRAPHICS_PRIMITIVES_H_
|
||||||
|
|
||||||
|
|
@ -25,19 +24,15 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
struct Vertex
|
struct Vertex {
|
||||||
{
|
|
||||||
GLfloat position[3];
|
GLfloat position[3];
|
||||||
GLfloat texcoord[2];
|
GLfloat texcoord[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Primitive
|
struct Primitive {
|
||||||
{
|
|
||||||
enum { max_vertices = 4 };
|
enum { max_vertices = 4 };
|
||||||
|
|
||||||
Primitive()
|
Primitive() : type(GL_TRIANGLE_FAN), nvertices(4) {
|
||||||
: type(GL_TRIANGLE_FAN), nvertices(4)
|
|
||||||
{
|
|
||||||
// Default is a quad. Just need to assign vertices[] and tex_id.
|
// Default is a quad. Just need to assign vertices[] and tex_id.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,59 +22,47 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
void ProgramFamily::Shader::init(GLenum type, const GLchar* src)
|
void ProgramFamily::Shader::init(GLenum type, const GLchar* src) {
|
||||||
{
|
if (!id) {
|
||||||
if (!id)
|
|
||||||
{
|
|
||||||
id = s_gles2.glCreateShader(type);
|
id = s_gles2.glCreateShader(type);
|
||||||
if (id)
|
if (id) {
|
||||||
{
|
|
||||||
s_gles2.glShaderSource(id, 1, &src, NULL);
|
s_gles2.glShaderSource(id, 1, &src, NULL);
|
||||||
s_gles2.glCompileShader(id);
|
s_gles2.glCompileShader(id);
|
||||||
GLint ok;
|
GLint ok;
|
||||||
s_gles2.glGetShaderiv(id, GL_COMPILE_STATUS, &ok);
|
s_gles2.glGetShaderiv(id, GL_COMPILE_STATUS, &ok);
|
||||||
if (!ok)
|
if (!ok) {
|
||||||
{
|
|
||||||
GLchar log[1024];
|
GLchar log[1024];
|
||||||
s_gles2.glGetShaderInfoLog(id, sizeof log - 1, NULL, log);
|
s_gles2.glGetShaderInfoLog(id, sizeof log - 1, NULL, log);
|
||||||
log[sizeof log - 1] = '\0';
|
log[sizeof log - 1] = '\0';
|
||||||
s_gles2.glDeleteShader(id);
|
s_gles2.glDeleteShader(id);
|
||||||
id = 0;
|
id = 0;
|
||||||
throw std::runtime_error(std::string("Compile failed: ")+
|
throw std::runtime_error(std::string("Compile failed: ") + log +
|
||||||
log + " for:\n" + src);
|
" for:\n" + src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramFamily::~ProgramFamily() noexcept
|
ProgramFamily::~ProgramFamily() noexcept {
|
||||||
{
|
|
||||||
// shader and program lifetimes are managed manually, so that we don't
|
// shader and program lifetimes are managed manually, so that we don't
|
||||||
// need any reference counting or to worry about how many copy constructions
|
// need any reference counting or to worry about how many copy constructions
|
||||||
// might have been followed by destructor calls during container resizes.
|
// might have been followed by destructor calls during container resizes.
|
||||||
|
|
||||||
for (auto& p : program)
|
for (auto& p : program) {
|
||||||
{
|
if (p.second.id) s_gles2.glDeleteProgram(p.second.id);
|
||||||
if (p.second.id)
|
|
||||||
s_gles2.glDeleteProgram(p.second.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& v : vshader)
|
for (auto& v : vshader) {
|
||||||
{
|
if (v.second.id) s_gles2.glDeleteShader(v.second.id);
|
||||||
if (v.second.id)
|
|
||||||
s_gles2.glDeleteShader(v.second.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& f : fshader)
|
for (auto& f : fshader) {
|
||||||
{
|
if (f.second.id) s_gles2.glDeleteShader(f.second.id);
|
||||||
if (f.second.id)
|
|
||||||
s_gles2.glDeleteShader(f.second.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint ProgramFamily::add_program(const GLchar* const vshader_src,
|
GLuint ProgramFamily::add_program(const GLchar* const vshader_src,
|
||||||
const GLchar* const fshader_src)
|
const GLchar* const fshader_src) {
|
||||||
{
|
|
||||||
auto& v = vshader[vshader_src];
|
auto& v = vshader[vshader_src];
|
||||||
if (!v.id) v.init(GL_VERTEX_SHADER, vshader_src);
|
if (!v.id) v.init(GL_VERTEX_SHADER, vshader_src);
|
||||||
|
|
||||||
|
|
@ -82,16 +70,14 @@ GLuint ProgramFamily::add_program(const GLchar* const vshader_src,
|
||||||
if (!f.id) f.init(GL_FRAGMENT_SHADER, fshader_src);
|
if (!f.id) f.init(GL_FRAGMENT_SHADER, fshader_src);
|
||||||
|
|
||||||
auto& p = program[{v.id, f.id}];
|
auto& p = program[{v.id, f.id}];
|
||||||
if (!p.id)
|
if (!p.id) {
|
||||||
{
|
|
||||||
p.id = s_gles2.glCreateProgram();
|
p.id = s_gles2.glCreateProgram();
|
||||||
s_gles2.glAttachShader(p.id, v.id);
|
s_gles2.glAttachShader(p.id, v.id);
|
||||||
s_gles2.glAttachShader(p.id, f.id);
|
s_gles2.glAttachShader(p.id, f.id);
|
||||||
s_gles2.glLinkProgram(p.id);
|
s_gles2.glLinkProgram(p.id);
|
||||||
GLint ok;
|
GLint ok;
|
||||||
s_gles2.glGetProgramiv(p.id, GL_LINK_STATUS, &ok);
|
s_gles2.glGetProgramiv(p.id, GL_LINK_STATUS, &ok);
|
||||||
if (!ok)
|
if (!ok) {
|
||||||
{
|
|
||||||
GLchar log[1024];
|
GLchar log[1024];
|
||||||
s_gles2.glGetProgramInfoLog(p.id, sizeof log - 1, NULL, log);
|
s_gles2.glGetProgramInfoLog(p.id, sizeof log - 1, NULL, log);
|
||||||
log[sizeof log - 1] = '\0';
|
log[sizeof log - 1] = '\0';
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
#ifndef ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
|
#ifndef ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
|
||||||
#define ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
|
#define ANBOX_GRAPHICS_PROGRAM_FAMILY_H_
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
|
|
@ -35,8 +35,7 @@ namespace graphics {
|
||||||
* different programs within the family to share common patterns of uniform
|
* different programs within the family to share common patterns of uniform
|
||||||
* usage too.
|
* usage too.
|
||||||
*/
|
*/
|
||||||
class ProgramFamily
|
class ProgramFamily {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
ProgramFamily() = default;
|
ProgramFamily() = default;
|
||||||
ProgramFamily(ProgramFamily const&) = delete;
|
ProgramFamily(ProgramFamily const&) = delete;
|
||||||
|
|
@ -47,8 +46,7 @@ public:
|
||||||
const GLchar* const static_fshader_src);
|
const GLchar* const static_fshader_src);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Shader
|
struct Shader {
|
||||||
{
|
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
void init(GLenum type, const GLchar* src);
|
void init(GLenum type, const GLchar* src);
|
||||||
};
|
};
|
||||||
|
|
@ -56,8 +54,7 @@ private:
|
||||||
ShaderMap vshader, fshader;
|
ShaderMap vshader, fshader;
|
||||||
|
|
||||||
typedef std::pair<GLuint, GLuint> ShaderPair;
|
typedef std::pair<GLuint, GLuint> ShaderPair;
|
||||||
struct Program
|
struct Program {
|
||||||
{
|
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
};
|
};
|
||||||
std::map<ShaderPair, Program> program;
|
std::map<ShaderPair, Program> program;
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,16 @@ namespace graphics {
|
||||||
const Rect Rect::Invalid{-1, -1, -1, -1};
|
const Rect Rect::Invalid{-1, -1, -1, -1};
|
||||||
const Rect Rect::Empty{0, 0, 0, 0};
|
const Rect Rect::Empty{0, 0, 0, 0};
|
||||||
|
|
||||||
void Rect::merge(const Rect &rhs)
|
void Rect::merge(const Rect &rhs) {
|
||||||
{
|
|
||||||
left_ = std::min(left_, rhs.left());
|
left_ = std::min(left_, rhs.left());
|
||||||
top_ = std::min(top_, rhs.top());
|
top_ = std::min(top_, rhs.top());
|
||||||
right_ = std::max(right_, rhs.right());
|
right_ = std::max(right_, rhs.right());
|
||||||
bottom_ = std::max(bottom_, rhs.bottom());
|
bottom_ = std::max(bottom_, rhs.bottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &out, const Rect &rect)
|
std::ostream &operator<<(std::ostream &out, const Rect &rect) {
|
||||||
{
|
return out << "{" << rect.left() << "," << rect.top() << "," << rect.right()
|
||||||
return out << "{" << rect.left() << "," << rect.top() << ","<< rect.right() << "," << rect.bottom() << "}";
|
<< "," << rect.bottom() << "}";
|
||||||
}
|
}
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -31,65 +31,35 @@ public:
|
||||||
|
|
||||||
inline Rect() : Rect(Empty) {}
|
inline Rect() : Rect(Empty) {}
|
||||||
|
|
||||||
inline Rect(const std::int32_t &left,
|
inline Rect(const std::int32_t &left, const std::int32_t &top,
|
||||||
const std::int32_t &top,
|
const std::int32_t &right, const std::int32_t &bottom)
|
||||||
const std::int32_t &right,
|
: left_(left), top_(top), right_(right), bottom_(bottom) {}
|
||||||
const std::int32_t &bottom) :
|
|
||||||
left_(left),
|
|
||||||
top_(top),
|
|
||||||
right_(right),
|
|
||||||
bottom_(bottom) {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Rect(const std::int32_t &width, const std::int32_t &height) :
|
inline Rect(const std::int32_t &width, const std::int32_t &height)
|
||||||
left_(0),
|
: left_(0), top_(0), right_(width), bottom_(height) {}
|
||||||
top_(0),
|
|
||||||
right_(width),
|
|
||||||
bottom_(height) {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void clear() {
|
inline void clear() { left_ = top_ = right_ = bottom_ = 0; }
|
||||||
left_ = top_ = right_ = bottom_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool valid() const {
|
inline bool valid() const { return width() >= 0 && height() >= 0; }
|
||||||
return width() >= 0 && height() >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t width() const {
|
inline std::int32_t width() const { return right_ - left_; }
|
||||||
return right_ - left_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t height() const {
|
inline std::int32_t height() const { return bottom_ - top_; }
|
||||||
return bottom_ - top_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t left() const {
|
inline std::int32_t left() const { return left_; }
|
||||||
return left_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t top() const {
|
inline std::int32_t top() const { return top_; }
|
||||||
return top_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t right() const {
|
inline std::int32_t right() const { return right_; }
|
||||||
return right_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::int32_t bottom() const {
|
inline std::int32_t bottom() const { return bottom_; }
|
||||||
return bottom_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const Rect &rhs) const {
|
inline bool operator==(const Rect &rhs) const {
|
||||||
return (left_ == rhs.left() &&
|
return (left_ == rhs.left() && top_ == rhs.top() && right_ == rhs.right() &&
|
||||||
top_ == rhs.top() &&
|
|
||||||
right_ == rhs.right() &&
|
|
||||||
bottom_ == rhs.bottom());
|
bottom_ == rhs.bottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator != (const Rect &rhs) const {
|
inline bool operator!=(const Rect &rhs) const { return !operator==(rhs); }
|
||||||
return !operator == (rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void merge(const Rect &rhs);
|
void merge(const Rect &rhs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,37 +16,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/input/device.h"
|
#include "anbox/input/device.h"
|
||||||
|
#include "anbox/logger.h"
|
||||||
#include "anbox/network/delegate_connection_creator.h"
|
#include "anbox/network/delegate_connection_creator.h"
|
||||||
#include "anbox/network/delegate_message_processor.h"
|
#include "anbox/network/delegate_message_processor.h"
|
||||||
#include "anbox/network/local_socket_messenger.h"
|
#include "anbox/network/local_socket_messenger.h"
|
||||||
#include "anbox/qemu/null_message_processor.h"
|
#include "anbox/qemu/null_message_processor.h"
|
||||||
#include "anbox/logger.h"
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace input {
|
namespace input {
|
||||||
std::shared_ptr<Device> Device::create(const std::string &path, const std::shared_ptr<Runtime> &runtime) {
|
std::shared_ptr<Device> Device::create(
|
||||||
|
const std::string &path, const std::shared_ptr<Runtime> &runtime) {
|
||||||
auto sp = std::make_shared<Device>();
|
auto sp = std::make_shared<Device>();
|
||||||
|
|
||||||
auto delegate_connector = std::make_shared<network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>(
|
auto delegate_connector = std::make_shared<
|
||||||
[sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) {
|
network::DelegateConnectionCreator<boost::asio::local::stream_protocol>>(
|
||||||
sp->new_client(socket);
|
[sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const
|
||||||
});
|
&socket) { sp->new_client(socket); });
|
||||||
|
|
||||||
sp->connector_ = std::make_shared<network::PublishedSocketConnector>(path, runtime, delegate_connector);
|
sp->connector_ = std::make_shared<network::PublishedSocketConnector>(
|
||||||
|
path, runtime, delegate_connector);
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device() :
|
Device::Device()
|
||||||
next_connection_id_(0),
|
: next_connection_id_(0),
|
||||||
connections_(std::make_shared<network::Connections<network::SocketConnection>>()) {
|
connections_(
|
||||||
|
std::make_shared<network::Connections<network::SocketConnection>>()) {
|
||||||
::memset(&info_, 0, sizeof(info_));
|
::memset(&info_, 0, sizeof(info_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {}
|
||||||
}
|
|
||||||
|
|
||||||
void Device::send_events(const std::vector<Event> &events) {
|
void Device::send_events(const std::vector<Event> &events) {
|
||||||
struct CompatEvent {
|
struct CompatEvent {
|
||||||
|
|
@ -143,16 +145,15 @@ void Device::set_unique_id(const std::string &unique_id) {
|
||||||
snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
|
snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Device::socket_path() const {
|
std::string Device::socket_path() const { return connector_->socket_file(); }
|
||||||
return connector_->socket_file();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Device::next_id() {
|
int Device::next_id() { return next_connection_id_++; }
|
||||||
return next_connection_id_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) {
|
void Device::new_client(
|
||||||
auto const messenger = std::make_shared<network::LocalSocketMessenger>(socket);
|
std::shared_ptr<boost::asio::local::stream_protocol::socket> const
|
||||||
|
&socket) {
|
||||||
|
auto const messenger =
|
||||||
|
std::make_shared<network::LocalSocketMessenger>(socket);
|
||||||
auto const &connection = std::make_shared<network::SocketConnection>(
|
auto const &connection = std::make_shared<network::SocketConnection>(
|
||||||
messenger, messenger, next_id(), connections_,
|
messenger, messenger, next_id(), connections_,
|
||||||
std::make_shared<qemu::NullMessageProcessor>());
|
std::make_shared<qemu::NullMessageProcessor>());
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_INPUT_DEVICE_H_
|
#ifndef ANBOX_INPUT_DEVICE_H_
|
||||||
#define ANBOX_INPUT_DEVICE_H_
|
#define ANBOX_INPUT_DEVICE_H_
|
||||||
|
|
||||||
#include "anbox/network/published_socket_connector.h"
|
|
||||||
#include "anbox/network/connections.h"
|
#include "anbox/network/connections.h"
|
||||||
|
#include "anbox/network/published_socket_connector.h"
|
||||||
#include "anbox/network/socket_connection.h"
|
#include "anbox/network/socket_connection.h"
|
||||||
#include "anbox/runtime.h"
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
|
|
@ -37,13 +37,15 @@ struct Event {
|
||||||
|
|
||||||
class Device : public std::enable_shared_from_this<Device> {
|
class Device : public std::enable_shared_from_this<Device> {
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<Device> create(const std::string &path, const std::shared_ptr<Runtime> &runtime);
|
static std::shared_ptr<Device> create(
|
||||||
|
const std::string &path, const std::shared_ptr<Runtime> &runtime);
|
||||||
|
|
||||||
Device();
|
Device();
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
void send_events(const std::vector<Event> &events);
|
void send_events(const std::vector<Event> &events);
|
||||||
void send_event(const std::uint16_t &code, const std::uint16_t &event, const std::int32_t &value);
|
void send_event(const std::uint16_t &code, const std::uint16_t &event,
|
||||||
|
const std::int32_t &value);
|
||||||
|
|
||||||
void set_name(const std::string &name);
|
void set_name(const std::string &name);
|
||||||
void set_driver_version(const int &version);
|
void set_driver_version(const int &version);
|
||||||
|
|
@ -65,10 +67,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int next_id();
|
int next_id();
|
||||||
void new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket);
|
void new_client(std::shared_ptr<
|
||||||
|
boost::asio::local::stream_protocol::socket> const &socket);
|
||||||
|
|
||||||
// NOTE: If you modify this struct you have to modify the version on
|
// NOTE: If you modify this struct you have to modify the version on
|
||||||
// the Android side too. See frameworks/native/services/inputflinger/EventHub.cpp
|
// the Android side too. See
|
||||||
|
// frameworks/native/services/inputflinger/EventHub.cpp
|
||||||
struct Info {
|
struct Info {
|
||||||
char name[80];
|
char name[80];
|
||||||
int driver_version;
|
int driver_version;
|
||||||
|
|
|
||||||
|
|
@ -16,22 +16,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "anbox/input/manager.h"
|
#include "anbox/input/manager.h"
|
||||||
|
#include "anbox/config.h"
|
||||||
#include "anbox/input/device.h"
|
#include "anbox/input/device.h"
|
||||||
#include "anbox/runtime.h"
|
#include "anbox/runtime.h"
|
||||||
#include "anbox/config.h"
|
|
||||||
#include "anbox/utils.h"
|
#include "anbox/utils.h"
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace input {
|
namespace input {
|
||||||
Manager::Manager(const std::shared_ptr<Runtime> &runtime) :
|
Manager::Manager(const std::shared_ptr<Runtime> &runtime) : runtime_(runtime) {
|
||||||
runtime_(runtime) {
|
|
||||||
utils::ensure_paths({config::host_input_device_path()});
|
utils::ensure_paths({config::host_input_device_path()});
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager() {
|
Manager::~Manager() {}
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Device> Manager::create_device() {
|
std::shared_ptr<Device> Manager::create_device() {
|
||||||
const auto id = next_id();
|
const auto id = next_id();
|
||||||
|
|
@ -47,7 +45,8 @@ std::uint32_t Manager::next_id() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Manager::build_device_path(const std::uint32_t &id) {
|
std::string Manager::build_device_path(const std::uint32_t &id) {
|
||||||
return (boost::format("%1%/event%2%") % config::host_input_device_path() % id).str();
|
return (boost::format("%1%/event%2%") % config::host_input_device_path() % id)
|
||||||
|
.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace input
|
} // namespace input
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
#ifndef ANBOX_INPUT_MANAGER_H_
|
#ifndef ANBOX_INPUT_MANAGER_H_
|
||||||
#define ANBOX_INPUT_MANAGER_H_
|
#define ANBOX_INPUT_MANAGER_H_
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue