diff options
144 files changed, 3134 insertions, 10066 deletions
diff --git a/aidl/gui/android/view/Surface.aidl b/aidl/gui/android/view/Surface.aidl index 674c16387e..7e892205d5 100644 --- a/aidl/gui/android/view/Surface.aidl +++ b/aidl/gui/android/view/Surface.aidl @@ -17,4 +17,4 @@ package android.view; -parcelable Surface cpp_header "gui/Surface.h"; +parcelable Surface cpp_header "gui/view/Surface.h"; diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index ce0caede26..8f2dee180f 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -552,17 +552,13 @@ static void pokeHalServices() hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos); Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName); if (!interfaceRet.isOk()) { - fprintf(stderr, "failed to get service %s: %s\n", - fqInstanceName.c_str(), - interfaceRet.description().c_str()); + // ignore continue; } sp<IBase> interface = interfaceRet; auto notifyRet = interface->notifySyspropsChanged(); if (!notifyRet.isOk()) { - fprintf(stderr, "failed to notifySyspropsChanged on service %s: %s\n", - fqInstanceName.c_str(), - notifyRet.description().c_str()); + // ignore } } }); diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk index efc050b65c..d1e94ed3cf 100644 --- a/cmds/dumpstate/Android.mk +++ b/cmds/dumpstate/Android.mk @@ -103,8 +103,7 @@ LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ LOCAL_MODULE := dumpstate -LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) \ - android.hardware.vibrator@1.0 +LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES) diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 67172b65f9..e33f099d3a 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -42,7 +42,6 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h> -#include <android/hardware/vibrator/1.0/IVibrator.h> #include <cutils/native_handle.h> #include <cutils/properties.h> #include <openssl/sha.h> @@ -54,8 +53,6 @@ #include "dumpstate.h" using ::android::hardware::dumpstate::V1_0::IDumpstateDevice; -using ::android::hardware::vibrator::V1_0::IVibrator; -using VibratorStatus = ::android::hardware::vibrator::V1_0::Status; // TODO: remove once moved to namespace using android::os::dumpstate::CommandOptions; @@ -1347,7 +1344,8 @@ static void SendShellBroadcast(const std::string& action, const std::vector<std: // TODO: explicity setting Shell's component to allow broadcast to launch it. // That might break other components that are listening to the bugreport notifications - // (android.intent.action.BUGREPORT_STARTED and android.intent.action.BUGREPORT_STOPED), but + // (com.android.internal.intent.action.BUGREPORT_STARTED and + // com.android.internal.intent.action.BUGREPORT_STOPED), but // those should be just handled by Shell anyways. // A more generic alternative would be passing the -f 0x01000000 flag (or whatever // value is defined by FLAG_RECEIVER_INCLUDE_BACKGROUND), but that would reset the @@ -1363,6 +1361,16 @@ static void SendShellBroadcast(const std::string& action, const std::vector<std: .Build()); } +static void Vibrate(int duration_ms) { + // clang-format off + RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"}, + CommandOptions::WithTimeout(10) + .Log("Vibrate: '%s'\n") + .Always() + .Build()); + // clang-format on +} + int main(int argc, char *argv[]) { int do_add_date = 0; int do_zip_file = 0; @@ -1593,7 +1601,7 @@ int main(int argc, char *argv[]) { "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), }; // clang-format on - SendShellBroadcast("android.intent.action.BUGREPORT_STARTED", am_args); + SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args); } if (use_control_socket) { dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str()); @@ -1608,22 +1616,8 @@ int main(int argc, char *argv[]) { fclose(cmdline); } - ::android::sp<IVibrator> vibrator = nullptr; if (do_vibrate) { - vibrator = IVibrator::getService(); - - if (vibrator != nullptr) { - // cancel previous vibration if any - ::android::hardware::Return<VibratorStatus> offStatus = vibrator->off(); - if (!offStatus.isOk() || offStatus != VibratorStatus::OK) { - MYLOGE("Vibrator off failed."); - } else { - ::android::hardware::Return<VibratorStatus> onStatus = vibrator->on(150); - if (!onStatus.isOk() || onStatus != VibratorStatus::OK) { - MYLOGE("Vibrator on failed."); - } - } - } + Vibrate(150); } if (do_fb && ds.do_early_screenshot_) { @@ -1803,21 +1797,9 @@ int main(int argc, char *argv[]) { } /* vibrate a few but shortly times to let user know it's finished */ - if (vibrator != nullptr) { - // in case dumpstate magically completes before the above vibration - ::android::hardware::Return<VibratorStatus> offStatus = vibrator->off(); - if (!offStatus.isOk() || offStatus != VibratorStatus::OK) { - MYLOGE("Vibrator off failed."); - } else { - for (int i = 0; i < 3; i++) { - ::android::hardware::Return<VibratorStatus> onStatus = vibrator->on(75); - if (!onStatus.isOk() || onStatus != VibratorStatus::OK) { - MYLOGE("Vibrator on failed."); - break; - } - usleep((75 + 50) * 1000); - } - } + for (int i = 0; i < 3; i++) { + Vibrate(75); + usleep((75 + 50) * 1000); } /* tell activity manager we're done */ @@ -1844,9 +1826,10 @@ int main(int argc, char *argv[]) { am_args.push_back("--es"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back(SHA256_file_hash(ds.path_)); - SendShellBroadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); + SendShellBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", + am_args); } else { - SendShellBroadcast("android.intent.action.BUGREPORT_FINISHED", am_args); + SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); } } else { MYLOGE("Skipping finished broadcast because bugreport could not be generated\n"); diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp index c5ae9d28ac..34769644d5 100644 --- a/cmds/dumpsys/Android.bp +++ b/cmds/dumpsys/Android.bp @@ -15,8 +15,6 @@ cc_defaults { "libutils", "liblog", "libbinder", - "android.hidl.manager@1.0", - "libhidlbase" ], clang: true, diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index 860b7b42de..f0e7200069 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -45,7 +45,8 @@ using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteFully; -static int sort_func(const String16* lhs, const String16* rhs) { +static int sort_func(const String16* lhs, const String16* rhs) +{ return lhs->compare(*rhs); } @@ -54,11 +55,10 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" - " dumpsys [-t TIMEOUT] [--help | --hw | -l | --skip SERVICES | SERVICE [ARGS]]\n" + " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n" " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n" - " --hw: list all hw services running on the device\n" " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n" " SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n"); } @@ -72,42 +72,16 @@ static bool IsSkipped(const Vector<String16>& skipped, const String16& service) return false; } -static void ListHardwareServices(android::hidl::manager::V1_0::IServiceManager* hm) { - using android::hardware::hidl_vec; - using android::hardware::hidl_string; - using android::hardware::Return; - using android::sp; - - if (hm == nullptr) { - ALOGE("Unable to get hardware service manager!"); - aerr << "Failed to get hardware service manager!"; - return; - } - - Return<void> ret = hm->list([](const hidl_vec<hidl_string> ®istered){ - aout << "Currently running hardware services:" << endl; - for (const auto &service : registered) { - aout << " " << service << endl; - } - }); - - if (!ret.isOk()) { - aerr << "Failed to list hardware services: " << ret.description(); - } -} - int Dumpsys::main(int argc, char* const argv[]) { Vector<String16> services; Vector<String16> args; Vector<String16> skippedServices; bool showListOnly = false; - bool listHwOnly = false; bool skipServices = false; int timeoutArg = 10; static struct option longOptions[] = { {"skip", no_argument, 0, 0 }, {"help", no_argument, 0, 0 }, - {"hw", no_argument, 0, 0 }, { 0, 0, 0, 0 } }; @@ -131,8 +105,6 @@ int Dumpsys::main(int argc, char* const argv[]) { } else if (!strcmp(longOptions[optionIndex].name, "help")) { usage(); return 0; - } else if (!strcmp(longOptions[optionIndex].name, "hw")) { - listHwOnly = true; } break; @@ -171,17 +143,11 @@ int Dumpsys::main(int argc, char* const argv[]) { } if ((skipServices && skippedServices.empty()) || - (showListOnly && (!services.empty() || !skippedServices.empty())) || - (listHwOnly && (skipServices || services.size() > 0 || showListOnly))) { + (showListOnly && (!services.empty() || !skippedServices.empty()))) { usage(); return -1; } - if (listHwOnly) { - ListHardwareServices(hm_); - return 0; - } - if (services.empty() || showListOnly) { // gets all services services = sm_->listServices(); diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h index 20d515d572..2534dded13 100644 --- a/cmds/dumpsys/dumpsys.h +++ b/cmds/dumpsys/dumpsys.h @@ -17,21 +17,18 @@ #ifndef FRAMEWORK_NATIVE_CMD_DUMPSYS_H_ #define FRAMEWORK_NATIVE_CMD_DUMPSYS_H_ -#include <android/hidl/manager/1.0/IServiceManager.h> #include <binder/IServiceManager.h> namespace android { class Dumpsys { public: - Dumpsys(android::IServiceManager* sm, - android::hidl::manager::V1_0::IServiceManager* hm) : sm_(sm), hm_(hm) { + Dumpsys(android::IServiceManager* sm) : sm_(sm) { } int main(int argc, char* const argv[]); private: android::IServiceManager* sm_; - android::hidl::manager::V1_0::IServiceManager* hm_; }; } diff --git a/cmds/dumpsys/main.cpp b/cmds/dumpsys/main.cpp index b180c98e79..8ba0eba0fa 100644 --- a/cmds/dumpsys/main.cpp +++ b/cmds/dumpsys/main.cpp @@ -27,7 +27,6 @@ #include <stdio.h> using namespace android; -using HServiceManager = android::hidl::manager::V1_0::IServiceManager; int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); @@ -39,8 +38,6 @@ int main(int argc, char* const argv[]) { return 20; } - sp<HServiceManager> hm = HServiceManager::getService("manager"); - - Dumpsys dumpsys(sm.get(), hm.get()); + Dumpsys dumpsys(sm.get()); return dumpsys.main(argc, argv); } diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp index e00444fcf6..7698ed5b95 100644 --- a/cmds/dumpsys/tests/Android.bp +++ b/cmds/dumpsys/tests/Android.bp @@ -5,12 +5,8 @@ cc_test { srcs: ["dumpsys_test.cpp"], shared_libs: [ - "android.hidl.manager@1.0", "libbase", "libbinder", - "liblog", - "libhidlbase", - "libhidltransport", "libutils", ], diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 01a2fa3b22..a61cb009b0 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -44,12 +44,6 @@ using ::testing::internal::CaptureStdout; using ::testing::internal::GetCapturedStderr; using ::testing::internal::GetCapturedStdout; -using android::hardware::hidl_vec; -using android::hardware::hidl_string; -using android::hardware::Void; -using HServiceManager = android::hidl::manager::V1_0::IServiceManager; -using IServiceNotification = android::hidl::manager::V1_0::IServiceNotification; - class ServiceManagerMock : public IServiceManager { public: MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&)); @@ -61,27 +55,6 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD0(onAsBinder, IBinder*()); }; -class HardwareServiceManagerMock : public HServiceManager { - public: - template<typename T> - using R = android::hardware::Return<T>; // conflicts with ::testing::Return - - MOCK_METHOD2(get, R<sp<IBase>>(const hidl_string&, const hidl_string&)); - MOCK_METHOD3(add, - R<bool>(const hidl_vec<hidl_string>&, - const hidl_string&, - const sp<IBase>&)); - MOCK_METHOD1(list, R<void>(list_cb)); - MOCK_METHOD2(listByInterface, - R<void>(const hidl_string&, listByInterface_cb)); - MOCK_METHOD3(registerForNotifications, - R<bool>(const hidl_string&, - const hidl_string&, - const sp<IServiceNotification>&)); - MOCK_METHOD1(debugDump, R<void>(debugDump_cb)); - -}; - class BinderMock : public BBinder { public: BinderMock() { @@ -111,26 +84,6 @@ Action<WriteOnFdFunction> WriteOnFd(const std::string& output) { return MakeAction(new WriteOnFdAction(output)); } -// gmock black magic to provide a WithArg<0>(List(services)) matcher -typedef void HardwareListFunction(HServiceManager::list_cb); - -class HardwareListAction : public ActionInterface<HardwareListFunction> { - public: - explicit HardwareListAction(const hidl_vec<hidl_string> &services) : services_(services) { - } - virtual Result Perform(const ArgumentTuple& args) { - auto cb = ::std::tr1::get<0>(args); - cb(services_); - } - - private: - hidl_vec<hidl_string> services_; -}; - -Action<HardwareListFunction> HardwareList(const hidl_vec<hidl_string> &services) { - return MakeAction(new HardwareListAction(services)); -} - // Matcher for args using Android's Vector<String16> format // TODO: move it to some common testing library MATCHER_P(AndroidElementsAre, expected, "") { @@ -168,7 +121,7 @@ ACTION_P(Sleep, timeout) { class DumpsysTest : public Test { public: - DumpsysTest() : sm_(), hm_(), dump_(&sm_, &hm_), stdout_(), stderr_() { + DumpsysTest() : sm_(), dump_(&sm_), stdout_(), stderr_() { } void ExpectListServices(std::vector<std::string> services) { @@ -176,22 +129,9 @@ class DumpsysTest : public Test { for (auto& service : services) { services16.add(String16(service.c_str())); } - EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16)); } - void ExpectListHardwareServices(std::vector<std::string> services) { - hidl_vec<hidl_string> hidl_services; - hidl_services.resize(services.size()); - for (size_t i = 0; i < services.size(); i++) { - hidl_services[i] = services[i]; - } - - EXPECT_CALL(hm_, list(_)).WillRepeatedly(DoAll( - WithArg<0>(HardwareList(hidl_services)), - Return(Void()))); - } - sp<BinderMock> ExpectCheckService(const char* name, bool running = true) { sp<BinderMock> binder_mock; if (running) { @@ -235,10 +175,8 @@ class DumpsysTest : public Test { EXPECT_THAT(status, Eq(0)); } - void AssertRunningServices(const std::vector<std::string>& services, - const std::string &message = "Currently running services:") { - std::string expected(message); - expected.append("\n"); + void AssertRunningServices(const std::vector<std::string>& services) { + std::string expected("Currently running services:\n"); for (const std::string& service : services) { expected.append(" ").append(service).append("\n"); } @@ -266,21 +204,12 @@ class DumpsysTest : public Test { } ServiceManagerMock sm_; - HardwareServiceManagerMock hm_; Dumpsys dump_; private: std::string stdout_, stderr_; }; -TEST_F(DumpsysTest, ListHwServices) { - ExpectListHardwareServices({"Locksmith", "Valet"}); - - CallMain({"--hw"}); - - AssertRunningServices({"Locksmith", "Valet"}, "Currently running hardware services:"); -} - // Tests 'dumpsys -l' when all services are running TEST_F(DumpsysTest, ListAllServices) { ExpectListServices({"Locksmith", "Valet"}); diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index aa32d6b1e7..0fb207bb44 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -854,13 +854,16 @@ static int open_output_file(const char* file_name, bool recreate, int permission return open(file_name, flags, permissions); } -static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) { +static bool set_permissions_and_ownership( + int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) { + // Primary apks are owned by the system. Secondary dex files are owned by the app. + int owning_uid = is_secondary_dex ? uid : AID_SYSTEM; if (fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP | (is_public ? S_IROTH : 0)) < 0) { ALOGE("installd cannot chmod '%s' during dexopt\n", path); return false; - } else if (fchown(fd, AID_SYSTEM, uid) < 0) { + } else if (fchown(fd, owning_uid, uid) < 0) { ALOGE("installd cannot chown '%s' during dexopt\n", path); return false; } @@ -1009,10 +1012,11 @@ class Dex2oatFileWrapper { // (re)Creates the app image if needed. Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided, - bool is_public, int uid) { + bool is_public, int uid, bool is_secondary_dex) { // Use app images only if it is enabled (by a set image format) and we are compiling // profile-guided (so the app image doesn't conservatively contain all classes). - if (!profile_guided) { + // Note that we don't create an image for secondary dex files. + if (is_secondary_dex || !profile_guided) { return Dex2oatFileWrapper(); } @@ -1043,7 +1047,7 @@ Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_g } } } else if (!set_permissions_and_ownership( - wrapper_fd.get(), is_public, uid, image_path.c_str())) { + wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) { ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str()); wrapper_fd.reset(-1); } @@ -1101,7 +1105,7 @@ Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profil // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to // out_vdex_wrapper_fd. Returns true for success or false in case of errors. bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed, - const char* instruction_set, bool is_public, int uid, + const char* instruction_set, bool is_public, int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd, Dex2oatFileWrapper* out_vdex_wrapper_fd) { CHECK(in_vdex_wrapper_fd != nullptr); @@ -1164,7 +1168,7 @@ bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_ } } if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid, - out_vdex_path_str.c_str())) { + out_vdex_path_str.c_str(), is_secondary_dex)) { ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str()); return false; } @@ -1187,7 +1191,8 @@ Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir, [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); }); if (wrapper_fd.get() < 0) { PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path; - } else if (!set_permissions_and_ownership(wrapper_fd.get(), is_public, uid, out_oat_path)) { + } else if (!set_permissions_and_ownership( + wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) { ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path); wrapper_fd.reset(-1); } @@ -1445,7 +1450,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins Dex2oatFileWrapper in_vdex_fd; Dex2oatFileWrapper out_vdex_fd; if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid, - &in_vdex_fd, &out_vdex_fd)) { + is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) { return -1; } @@ -1454,7 +1459,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins // Create the app image file if needed. Dex2oatFileWrapper image_fd = - maybe_open_app_image(out_oat_path, profile_guided, is_public, uid); + maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex); // Open the reference profile if needed. Dex2oatFileWrapper reference_profile_fd = diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp index c3805985c4..5aab35a450 100644 --- a/cmds/lshal/Android.bp +++ b/cmds/lshal/Android.bp @@ -22,6 +22,6 @@ cc_binary { "libhidltransport", ], srcs: [ - "lshal.cpp" + "Lshal.cpp" ], } diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp new file mode 100644 index 0000000000..ce058c8a47 --- /dev/null +++ b/cmds/lshal/Lshal.cpp @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Lshal.h" + +#include <getopt.h> + +#include <fstream> +#include <iomanip> +#include <iostream> +#include <map> +#include <sstream> +#include <regex> + +#include <android-base/parseint.h> +#include <android/hidl/manager/1.0/IServiceManager.h> +#include <hidl/ServiceManagement.h> + +#include "Timeout.h" + +using ::android::hardware::hidl_string; +using ::android::hidl::manager::V1_0::IServiceManager; + +namespace android { +namespace lshal { + +template <typename A> +std::string join(const A &components, const std::string &separator) { + std::stringstream out; + bool first = true; + for (const auto &component : components) { + if (!first) { + out << separator; + } + out << component; + + first = false; + } + return out.str(); +} + +static std::string toHexString(uint64_t t) { + std::ostringstream os; + os << std::hex << std::setfill('0') << std::setw(16) << t; + return os.str(); +} + +static std::pair<hidl_string, hidl_string> split(const hidl_string &s, char c) { + const char *pos = strchr(s.c_str(), c); + if (pos == nullptr) { + return {s, {}}; + } + return {hidl_string(s.c_str(), pos - s.c_str()), hidl_string(pos + 1)}; +} + +static std::vector<std::string> split(const std::string &s, char c) { + std::vector<std::string> components{}; + size_t startPos = 0; + size_t matchPos; + while ((matchPos = s.find(c, startPos)) != std::string::npos) { + components.push_back(s.substr(startPos, matchPos - startPos)); + startPos = matchPos + 1; + } + + if (startPos <= s.length()) { + components.push_back(s.substr(startPos)); + } + return components; +} + +std::string getCmdline(pid_t pid) { + std::ifstream ifs("/proc/" + std::to_string(pid) + "/cmdline"); + std::string cmdline; + if (!ifs.is_open()) { + return ""; + } + ifs >> cmdline; + return cmdline; +} + +const std::string &Lshal::getCmdline(pid_t pid) { + auto pair = mCmdlines.find(pid); + if (pair != mCmdlines.end()) { + return pair->second; + } + mCmdlines[pid] = ::android::lshal::getCmdline(pid); + return mCmdlines[pid]; +} + +void Lshal::removeDeadProcesses(Pids *pids) { + static const pid_t myPid = getpid(); + std::remove_if(pids->begin(), pids->end(), [this](auto pid) { + return pid == myPid || this->getCmdline(pid).empty(); + }); +} + +bool Lshal::getReferencedPids( + pid_t serverPid, std::map<uint64_t, Pids> *objects) const { + + std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid)); + if (!ifs.is_open()) { + return false; + } + + static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); + + std::string line; + std::smatch match; + while(getline(ifs, line)) { + if (!std::regex_search(line, match, prefix)) { + // the line doesn't start with the correct prefix + continue; + } + std::string ptrString = "0x" + match.str(2); // use number after c + uint64_t ptr; + if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) { + // Should not reach here, but just be tolerant. + mErr << "Could not parse number " << ptrString << std::endl; + continue; + } + const std::string proc = " proc "; + auto pos = line.rfind(proc); + if (pos != std::string::npos) { + for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) { + int32_t pid; + if (!::android::base::ParseInt(pidStr, &pid)) { + mErr << "Could not parse number " << pidStr << std::endl; + continue; + } + (*objects)[ptr].push_back(pid); + } + } + } + return true; +} + +void Lshal::postprocess() { + if (mSortColumn) { + std::sort(mTable.begin(), mTable.end(), mSortColumn); + } + for (TableEntry &entry : mTable) { + entry.serverCmdline = getCmdline(entry.serverPid); + removeDeadProcesses(&entry.clientPids); + for (auto pid : entry.clientPids) { + entry.clientCmdlines.push_back(this->getCmdline(pid)); + } + } +} + +void Lshal::printLine( + const std::string &interfaceName, + const std::string &transport, const std::string &server, + const std::string &serverCmdline, + const std::string &address, const std::string &clients, + const std::string &clientCmdlines) const { + if (mSelectedColumns & ENABLE_INTERFACE_NAME) + mOut << std::setw(80) << interfaceName << "\t"; + if (mSelectedColumns & ENABLE_TRANSPORT) + mOut << std::setw(10) << transport << "\t"; + if (mSelectedColumns & ENABLE_SERVER_PID) { + if (mEnableCmdlines) { + mOut << std::setw(15) << serverCmdline << "\t"; + } else { + mOut << std::setw(5) << server << "\t"; + } + } + if (mSelectedColumns & ENABLE_SERVER_ADDR) + mOut << std::setw(16) << address << "\t"; + if (mSelectedColumns & ENABLE_CLIENT_PIDS) { + if (mEnableCmdlines) { + mOut << std::setw(0) << clientCmdlines; + } else { + mOut << std::setw(0) << clients; + } + } + mOut << std::endl; +} + +void Lshal::dump() const { + mOut << "All services:" << std::endl; + mOut << std::left; + printLine("Interface", "Transport", "Server", "Server CMD", "PTR", "Clients", "Clients CMD"); + for (const auto &entry : mTable) { + printLine(entry.interfaceName, + entry.transport, + entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid), + entry.serverCmdline, + entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress), + join(entry.clientPids, " "), + join(entry.clientCmdlines, ";")); + } +} + +void Lshal::putEntry(TableEntry &&entry) { + mTable.push_back(std::forward<TableEntry>(entry)); +} + +Status Lshal::fetchAllLibraries(const sp<IServiceManager> &manager) { + using namespace ::android::hardware; + using namespace ::android::hidl::manager::V1_0; + using namespace ::android::hidl::base::V1_0; + auto ret = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &fqInstanceNames) { + for (const auto &fqInstanceName : fqInstanceNames) { + putEntry({ + .interfaceName = fqInstanceName, + .transport = "passthrough", + .serverPid = NO_PID, + .serverObjectAddress = NO_PTR, + .clientPids = {} + }); + } + }); + if (!ret.isOk()) { + mErr << "Error: Failed to call list on getPassthroughServiceManager(): " + << ret.description() << std::endl; + return DUMP_ALL_LIBS_ERROR; + } + return OK; +} + +Status Lshal::fetchPassthrough(const sp<IServiceManager> &manager) { + using namespace ::android::hardware; + using namespace ::android::hidl::manager::V1_0; + using namespace ::android::hidl::base::V1_0; + auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) { + for (const auto &info : infos) { + putEntry({ + .interfaceName = + std::string{info.interfaceName.c_str()} + "/" + + std::string{info.instanceName.c_str()}, + .transport = "passthrough", + .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID, + .serverObjectAddress = NO_PTR, + .clientPids = info.clientPids + }); + } + }); + if (!ret.isOk()) { + mErr << "Error: Failed to call debugDump on defaultServiceManager(): " + << ret.description() << std::endl; + return DUMP_PASSTHROUGH_ERROR; + } + return OK; +} + +Status Lshal::fetchBinderized(const sp<IServiceManager> &manager) { + using namespace ::std; + using namespace ::android::hardware; + using namespace ::android::hidl::manager::V1_0; + using namespace ::android::hidl::base::V1_0; + const std::string mode = "hwbinder"; + Status status = OK; + auto listRet = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &fqInstanceNames) { + // server pid, .ptr value of binder object, child pids + std::map<std::string, DebugInfo> allDebugInfos; + std::map<pid_t, std::map<uint64_t, Pids>> allPids; + for (const auto &fqInstanceName : fqInstanceNames) { + const auto pair = split(fqInstanceName, '/'); + const auto &serviceName = pair.first; + const auto &instanceName = pair.second; + auto getRet = timeoutIPC(manager, &IServiceManager::get, serviceName, instanceName); + if (!getRet.isOk()) { + mErr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "cannot be fetched from service manager:" + << getRet.description() << std::endl; + status |= DUMP_BINDERIZED_ERROR; + continue; + } + sp<IBase> service = getRet; + if (service == nullptr) { + mErr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "cannot be fetched from service manager (null)"; + status |= DUMP_BINDERIZED_ERROR; + continue; + } + auto debugRet = timeoutIPC(service, &IBase::getDebugInfo, [&] (const auto &debugInfo) { + allDebugInfos[fqInstanceName] = debugInfo; + if (debugInfo.pid >= 0) { + allPids[static_cast<pid_t>(debugInfo.pid)].clear(); + } + }); + if (!debugRet.isOk()) { + mErr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "debugging information cannot be retrieved:" + << debugRet.description() << std::endl; + status |= DUMP_BINDERIZED_ERROR; + } + } + for (auto &pair : allPids) { + pid_t serverPid = pair.first; + if (!getReferencedPids(serverPid, &allPids[serverPid])) { + mErr << "Warning: no information for PID " << serverPid + << ", are you root?" << std::endl; + status |= DUMP_BINDERIZED_ERROR; + } + } + for (const auto &fqInstanceName : fqInstanceNames) { + auto it = allDebugInfos.find(fqInstanceName); + if (it == allDebugInfos.end()) { + putEntry({ + .interfaceName = fqInstanceName, + .transport = mode, + .serverPid = NO_PID, + .serverObjectAddress = NO_PTR, + .clientPids = {} + }); + continue; + } + const DebugInfo &info = it->second; + putEntry({ + .interfaceName = fqInstanceName, + .transport = mode, + .serverPid = info.pid, + .serverObjectAddress = info.ptr, + .clientPids = info.pid == NO_PID || info.ptr == NO_PTR + ? Pids{} : allPids[info.pid][info.ptr] + }); + } + + }); + if (!listRet.isOk()) { + mErr << "Error: Failed to list services for " << mode << ": " + << listRet.description() << std::endl; + status |= DUMP_BINDERIZED_ERROR; + } + return status; +} + +Status Lshal::fetch() { + Status status = OK; + auto bManager = ::android::hardware::defaultServiceManager(); + if (bManager == nullptr) { + mErr << "Failed to get defaultServiceManager()!" << std::endl; + status |= NO_BINDERIZED_MANAGER; + } else { + status |= fetchBinderized(bManager); + // Passthrough PIDs are registered to the binderized manager as well. + status |= fetchPassthrough(bManager); + } + + auto pManager = ::android::hardware::getPassthroughServiceManager(); + if (pManager == nullptr) { + mErr << "Failed to get getPassthroughServiceManager()!" << std::endl; + status |= NO_PASSTHROUGH_MANAGER; + } else { + status |= fetchAllLibraries(pManager); + } + return status; +} + +void Lshal::usage() const { + mErr + << "usage: lshal" << std::endl + << " Dump all hals with default ordering and columns [-itpc]." << std::endl + << " lshal [--interface|-i] [--transport|-t]" << std::endl + << " [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl + << " [--sort={interface|i|pid|p}]" << std::endl + << " -i, --interface: print the interface name column" << std::endl + << " -n, --instance: print the instance name column" << std::endl + << " -t, --transport: print the transport mode column" << std::endl + << " -p, --pid: print the server PID, or server cmdline if -m is set" << std::endl + << " -a, --address: print the server object address column" << std::endl + << " -c, --clients: print the client PIDs, or client cmdlines if -m is set" + << std::endl + << " -m, --cmdline: print cmdline instead of PIDs" << std::endl + << " --sort=i, --sort=interface: sort by interface name" << std::endl + << " --sort=p, --sort=pid: sort by server pid" << std::endl + << " lshal [-h|--help]" << std::endl + << " -h, --help: show this help information." << std::endl; +} + +Status Lshal::parseArgs(int argc, char **argv) { + static struct option longOptions[] = { + // long options with short alternatives + {"help", no_argument, 0, 'h' }, + {"interface", no_argument, 0, 'i' }, + {"transport", no_argument, 0, 't' }, + {"pid", no_argument, 0, 'p' }, + {"address", no_argument, 0, 'a' }, + {"clients", no_argument, 0, 'c' }, + {"cmdline", no_argument, 0, 'm' }, + + // long options without short alternatives + {"sort", required_argument, 0, 's' }, + { 0, 0, 0, 0 } + }; + + int optionIndex; + int c; + optind = 1; + for (;;) { + // using getopt_long in case we want to add other options in the future + c = getopt_long(argc, argv, "hitpacm", longOptions, &optionIndex); + if (c == -1) { + break; + } + switch (c) { + case 's': { + if (strcmp(optarg, "interface") == 0 || strcmp(optarg, "i") == 0) { + mSortColumn = TableEntry::sortByInterfaceName; + } else if (strcmp(optarg, "pid") == 0 || strcmp(optarg, "p") == 0) { + mSortColumn = TableEntry::sortByServerPid; + } else { + mErr << "Unrecognized sorting column: " << optarg << std::endl; + usage(); + return USAGE; + } + break; + } + case 'i': { + mSelectedColumns |= ENABLE_INTERFACE_NAME; + break; + } + case 't': { + mSelectedColumns |= ENABLE_TRANSPORT; + break; + } + case 'p': { + mSelectedColumns |= ENABLE_SERVER_PID; + break; + } + case 'a': { + mSelectedColumns |= ENABLE_SERVER_ADDR; + break; + } + case 'c': { + mSelectedColumns |= ENABLE_CLIENT_PIDS; + break; + } + case 'm': { + mEnableCmdlines = true; + break; + } + case 'h': // falls through + default: // see unrecognized options + usage(); + return USAGE; + } + } + + if (mSelectedColumns == 0) { + mSelectedColumns = ENABLE_INTERFACE_NAME + | ENABLE_TRANSPORT | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS; + } + return OK; +} + +int Lshal::main(int argc, char **argv) { + Status status = parseArgs(argc, argv); + if (status != OK) { + return status; + } + status = fetch(); + postprocess(); + dump(); + return status; +} + +} // namespace lshal +} // namespace android + +int main(int argc, char **argv) { + return ::android::lshal::Lshal{}.main(argc, argv); +} diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h new file mode 100644 index 0000000000..ead99dc068 --- /dev/null +++ b/cmds/lshal/Lshal.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ +#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ + +#include <stdint.h> + +#include <iostream> +#include <string> +#include <vector> + +#include <android/hidl/manager/1.0/IServiceManager.h> + +#include "TableEntry.h" + +namespace android { +namespace lshal { + +enum : unsigned int { + OK = 0, + USAGE = 1 << 0, + NO_BINDERIZED_MANAGER = 1 << 1, + NO_PASSTHROUGH_MANAGER = 1 << 2, + DUMP_BINDERIZED_ERROR = 1 << 3, + DUMP_PASSTHROUGH_ERROR = 1 << 4, + DUMP_ALL_LIBS_ERROR = 1 << 5, +}; +using Status = unsigned int; + +class Lshal { +public: + int main(int argc, char **argv); + +private: + Status parseArgs(int argc, char **argv); + Status fetch(); + void postprocess(); + void dump() const; + void usage() const; + void putEntry(TableEntry &&entry); + Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); + Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); + Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager); + bool getReferencedPids( + pid_t serverPid, std::map<uint64_t, Pids> *objects) const; + void printLine( + const std::string &interfaceName, + const std::string &transport, const std::string &server, + const std::string &serverCmdline, + const std::string &address, const std::string &clients, + const std::string &clientCmdlines) const ; + // Return /proc/{pid}/cmdline if it exists, else empty string. + const std::string &getCmdline(pid_t pid); + // Call getCmdline on all pid in pids. If it returns empty string, the process might + // have died, and the pid is removed from pids. + void removeDeadProcesses(Pids *pids); + + Table mTable{}; + std::ostream &mErr = std::cerr; + std::ostream &mOut = std::cout; + TableEntryCompare mSortColumn = nullptr; + TableEntrySelect mSelectedColumns = 0; + // If true, cmdlines will be printed instead of pid. + bool mEnableCmdlines; + // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it. + // If an entry exist but is an empty string, process might have died. + // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline. + std::map<pid_t, std::string> mCmdlines; +}; + + +} // namespace lshal +} // namespace android + +#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_ diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h new file mode 100644 index 0000000000..4ec3a0ced1 --- /dev/null +++ b/cmds/lshal/TableEntry.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ +#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ + +#include <stdint.h> + +#include <string> +#include <vector> +#include <iostream> + +namespace android { +namespace lshal { + +using Pids = std::vector<int32_t>; + +struct TableEntry { + std::string interfaceName; + std::string transport; + int32_t serverPid; + std::string serverCmdline; + uint64_t serverObjectAddress; + Pids clientPids; + std::vector<std::string> clientCmdlines; + + static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) { + return a.interfaceName < b.interfaceName; + }; + static bool sortByServerPid(const TableEntry &a, const TableEntry &b) { + return a.serverPid < b.serverPid; + }; +}; + +using Table = std::vector<TableEntry>; +using TableEntryCompare = std::function<bool(const TableEntry &, const TableEntry &)>; + +enum : unsigned int { + ENABLE_INTERFACE_NAME = 1 << 0, + ENABLE_TRANSPORT = 1 << 1, + ENABLE_SERVER_PID = 1 << 2, + ENABLE_SERVER_ADDR = 1 << 3, + ENABLE_CLIENT_PIDS = 1 << 4 +}; + +using TableEntrySelect = unsigned int; + +enum { + NO_PID = -1, + NO_PTR = 0 +}; + +} // namespace lshal +} // namespace android + +#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_ diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h new file mode 100644 index 0000000000..bf883c0a4c --- /dev/null +++ b/cmds/lshal/Timeout.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <condition_variable> +#include <chrono> +#include <functional> +#include <mutex> +#include <thread> + +#include <hidl/Status.h> + +namespace android { +namespace lshal { + +static constexpr std::chrono::milliseconds IPC_CALL_WAIT{500}; + +class BackgroundTaskState { +public: + BackgroundTaskState(){} + void notify() { + std::unique_lock<std::mutex> lock(mMutex); + mFinished = true; + lock.unlock(); + mCondVar.notify_all(); + } + template<class C, class D> + bool wait(std::chrono::time_point<C, D> end) { + std::unique_lock<std::mutex> lock(mMutex); + mCondVar.wait_until(lock, end, [this](){ return this->mFinished; }); + return mFinished; + } +private: + std::mutex mMutex; + std::condition_variable mCondVar; + bool mFinished = false; +}; + +template<class R, class P> +bool timeout(std::chrono::duration<R, P> delay, const std::function<void(void)> &func) { + auto now = std::chrono::system_clock::now(); + BackgroundTaskState state{}; + std::thread t([&state, &func] { + func(); + state.notify(); + }); + t.detach(); + bool success = state.wait(now + delay); + return success; +} + +template<class Function, class I, class... Args> +typename std::result_of<Function(I *, Args...)>::type +timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) { + using ::android::hardware::Status; + typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()}; + auto boundFunc = std::bind(std::forward<Function>(func), + interfaceObject.get(), std::forward<Args>(args)...); + bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] { + ret = boundFunc(); + }); + if (!success) { + return Status::fromStatusT(TIMED_OUT); + } + return ret; +} + +} // namespace lshal +} // namespace android diff --git a/cmds/lshal/lshal.cpp b/cmds/lshal/lshal.cpp deleted file mode 100644 index bc5eaf24c5..0000000000 --- a/cmds/lshal/lshal.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include <getopt.h> - -#include <map> -#include <fstream> -#include <iomanip> -#include <iostream> -#include <sstream> -#include <regex> - -#include <android-base/parseint.h> -#include <android/hidl/manager/1.0/IServiceManager.h> -#include <hidl/ServiceManagement.h> - -template <typename A, typename B, typename C, typename D, typename E> -void printColumn(std::stringstream &stream, - const A &a, const B &b, const C &c, const D &d, const E &e) { - using namespace ::std; - stream << left - << setw(70) << a << "\t" - << setw(20) << b << "\t" - << setw(10) << c << "\t" - << setw(5) << d << "\t" - << setw(0) << e - << endl; -} - -std::string toHexString(uint64_t t) { - std::ostringstream os; - os << std::hex << std::setfill('0') << std::setw(16) << t; - return os.str(); -} - -::android::status_t getReferencedPids( - pid_t serverPid, std::map<uint64_t, std::string> *objects) { - - std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid)); - if (!ifs.is_open()) { - return ::android::PERMISSION_DENIED; - } - - static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); - - std::string line; - std::smatch match; - while(getline(ifs, line)) { - if (!std::regex_search(line, match, prefix)) { - // the line doesn't start with the correct prefix - continue; - } - std::string ptrString = "0x" + match.str(2); // use number after c - uint64_t ptr; - if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) { - // Should not reach here, but just be tolerant. - std::cerr << "Could not parse number " << ptrString << std::endl; - continue; - } - const std::string proc = " proc "; - auto pos = line.rfind(proc); - if (pos != std::string::npos) { - (*objects)[ptr] += line.substr(pos + proc.size()); - } - } - return ::android::OK; -} - - -int dump() { - using namespace ::std; - using namespace ::android::hardware; - using namespace ::android::hidl::manager::V1_0; - - std::map<std::string, ::android::sp<IServiceManager>> mapping = { - {"hwbinder", defaultServiceManager()}, - {"passthrough", getPassthroughServiceManager()} - }; - - std::stringstream stream; - - stream << "All services:" << endl; - stream << left; - printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients"); - - for (const auto &pair : mapping) { - const std::string &mode = pair.first; - const ::android::sp<IServiceManager> &manager = pair.second; - - if (manager == nullptr) { - cerr << "Failed to get IServiceManager for " << mode << "!" << endl; - continue; - } - - auto ret = manager->debugDump([&](const auto ®istered) { - // server pid, .ptr value of binder object, child pids - std::map<pid_t, std::map<uint64_t, std::string>> allPids; - for (const auto &info : registered) { - if (info.pid < 0) { - continue; - } - pid_t serverPid = info.pid; - allPids[serverPid].clear(); - } - for (auto &pair : allPids) { - pid_t serverPid = pair.first; - if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) { - std::cerr << "Warning: no information for PID " << serverPid - << ", are you root?" << std::endl; - } - } - for (const auto &info : registered) { - printColumn(stream, - info.interfaceName, - info.instanceName.empty() ? "N/A" : info.instanceName, - mode, - info.pid < 0 ? "N/A" : std::to_string(info.pid), - info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]); - } - }); - if (!ret.isOk()) { - cerr << "Failed to list services for " << mode << ": " - << ret.description() << endl; - } - } - cout << stream.rdbuf(); - return 0; -} - -int usage() { - using namespace ::std; - cerr - << "usage: lshal" << endl - << " To dump all hals." << endl - << "or:" << endl - << " lshal [-h|--help]" << endl - << " -h, --help: show this help information." << endl; - return -1; -} - -int main(int argc, char **argv) { - static struct option longOptions[] = { - {"help", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; - - int optionIndex; - int c; - optind = 1; - for (;;) { - // using getopt_long in case we want to add other options in the future - c = getopt_long(argc, argv, "h", longOptions, &optionIndex); - if (c == -1) { - break; - } - switch (c) { - case 'h': // falls through - default: // see unrecognized options - return usage(); - } - } - return dump(); - -} diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h index 94afae545d..de5c1c7b64 100644 --- a/include/audiomanager/IPlayer.h +++ b/include/audiomanager/IPlayer.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <sys/types.h> +#include <media/VolumeShaper.h> #include <utils/RefBase.h> #include <utils/Errors.h> #include <binder/IInterface.h> @@ -45,6 +46,9 @@ public: virtual void setStartDelayMs(int delayMs) = 0; + virtual void applyVolumeShaper( + const sp<VolumeShaper::Configuration>& configuration, + const sp<VolumeShaper::Operation>& operation) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h index 46ca2c2ec0..9e1ae9409e 100644 --- a/include/gui/FrameTimestamps.h +++ b/include/gui/FrameTimestamps.h @@ -95,6 +95,11 @@ struct FrameEvents { std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE}; }; +struct CompositorTiming { + nsecs_t deadline{0}; + nsecs_t interval{16666667}; + nsecs_t presentLatency{0}; +}; // A short history of frames that are synchronized between the consumer and // producer via deltas. @@ -111,6 +116,8 @@ public: protected: std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames; + + CompositorTiming mCompositorTiming; }; @@ -119,6 +126,16 @@ class ProducerFrameEventHistory : public FrameEventHistory { public: ~ProducerFrameEventHistory() override; + // Public for testing. + static nsecs_t snapToNextTick( + nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval); + + nsecs_t getNextCompositeDeadline(const nsecs_t now) const; + nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; } + nsecs_t getCompositeToPresentLatency() const { + return mCompositorTiming.presentLatency; + } + // virtual for testing. virtual void updateAcquireFence( uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire); @@ -189,12 +206,15 @@ class ConsumerFrameEventHistory : public FrameEventHistory { public: ~ConsumerFrameEventHistory() override; + void initializeCompositorTiming(const CompositorTiming& compositorTiming); + void addQueue(const NewFrameEventsEntry& newEntry); void addLatch(uint64_t frameNumber, nsecs_t latchTime); void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime); void addPostComposition(uint64_t frameNumber, const std::shared_ptr<FenceTime>& gpuCompositionDone, - const std::shared_ptr<FenceTime>& displayPresent); + const std::shared_ptr<FenceTime>& displayPresent, + const CompositorTiming& compositorTiming); void addRetire(uint64_t frameNumber, const std::shared_ptr<FenceTime>& displayRetire); void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime, @@ -244,7 +264,7 @@ public: size_t& count); private: - static size_t minFlattenedSize(); + static constexpr size_t minFlattenedSize(); size_t mIndex{0}; uint64_t mFrameNumber{0}; @@ -306,9 +326,10 @@ public: size_t& count); private: - static size_t minFlattenedSize(); + static constexpr size_t minFlattenedSize(); std::vector<FrameEventsDelta> mDeltas; + CompositorTiming mCompositorTiming; }; diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h index 9e189076f2..54c9829484 100644 --- a/include/gui/GraphicBufferAlloc.h +++ b/include/gui/GraphicBufferAlloc.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H -#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H +#ifndef ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H +#define ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H #include <stdint.h> #include <sys/types.h> @@ -25,10 +25,16 @@ #include <utils/Errors.h> namespace android { -// --------------------------------------------------------------------------- class GraphicBuffer; +/* + * Concrete implementation of the IGraphicBufferAlloc interface. + * + * This can create GraphicBuffer instance across processes. This is mainly used + * by surfaceflinger. + */ + class GraphicBufferAlloc : public BnGraphicBufferAlloc { public: GraphicBufferAlloc(); @@ -40,7 +46,6 @@ public: }; -// --------------------------------------------------------------------------- -}; // namespace android +} // namespace android -#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H +#endif // ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 60203f7c4f..a3c2bfa25b 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -17,8 +17,6 @@ #ifndef ANDROID_GUI_SURFACE_H #define ANDROID_GUI_SURFACE_H -#include <binder/Parcelable.h> - #include <gui/IGraphicBufferProducer.h> #include <gui/BufferQueueDefs.h> @@ -137,12 +135,18 @@ public: status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, float outTransformMatrix[16]); + status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration); + /* Enables or disables frame timestamp tracking. It is disabled by default * to avoid overhead during queue and dequeue for applications that don't * need the feature. If disabled, calls to getFrameTimestamps will fail. */ void enableFrameTimestamps(bool enable); + status_t getCompositorTiming( + nsecs_t* compositeDeadline, nsecs_t* compositeInterval, + nsecs_t* compositeToPresentLatency); + // See IGraphicBufferProducer::getFrameTimestamps status_t getFrameTimestamps(uint64_t frameNumber, nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime, @@ -150,7 +154,6 @@ public: nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime, nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime, nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime); - status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration); status_t getUniqueId(uint64_t* outId) const; @@ -159,6 +162,7 @@ protected: // Virtual for testing. virtual sp<ISurfaceComposer> composerService() const; + virtual nsecs_t now() const; private: // can't be copied @@ -206,9 +210,11 @@ private: int dispatchSetSurfaceDamage(va_list args); int dispatchSetSharedBufferMode(va_list args); int dispatchSetAutoRefresh(va_list args); + int dispatchGetDisplayRefreshCycleDuration(va_list args); + int dispatchGetNextFrameId(va_list args); int dispatchEnableFrameTimestamps(va_list args); + int dispatchGetCompositorTiming(va_list args); int dispatchGetFrameTimestamps(va_list args); - int dispatchGetDisplayRefreshCycleDuration(va_list args); protected: virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); @@ -410,43 +416,6 @@ protected: std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory; }; -namespace view { - -/** - * A simple holder for an IGraphicBufferProducer, to match the managed-side - * android.view.Surface parcelable behavior. - * - * This implements android/view/Surface.aidl - * - * TODO: Convert IGraphicBufferProducer into AIDL so that it can be directly - * used in managed Binder calls. - */ -class Surface : public Parcelable { - public: - - String16 name; - sp<IGraphicBufferProducer> graphicBufferProducer; - - virtual status_t writeToParcel(Parcel* parcel) const override; - virtual status_t readFromParcel(const Parcel* parcel) override; - - // nameAlreadyWritten set to true by Surface.java, because it splits - // Parceling itself between managed and native code, so it only wants a part - // of the full parceling to happen on its native side. - status_t writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const; - - // nameAlreadyRead set to true by Surface.java, because it splits - // Parceling itself between managed and native code, so it only wants a part - // of the full parceling to happen on its native side. - status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead); - - private: - - static String16 readMaybeEmptyString16(const Parcel* parcel); -}; - -} // namespace view - -}; // namespace android +} // namespace android #endif // ANDROID_GUI_SURFACE_H diff --git a/include/gui/view/Surface.h b/include/gui/view/Surface.h new file mode 100644 index 0000000000..cc64fd45dd --- /dev/null +++ b/include/gui/view/Surface.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_GUI_VIEW_SURFACE_H +#define ANDROID_GUI_VIEW_SURFACE_H + +#include <utils/Errors.h> +#include <utils/StrongPointer.h> +#include <utils/String16.h> + +#include <binder/Parcelable.h> + +namespace android { + +class IGraphicBufferProducer; + +namespace view { + +/** + * A simple holder for an IGraphicBufferProducer, to match the managed-side + * android.view.Surface parcelable behavior. + * + * This implements android/view/Surface.aidl + * + * TODO: Convert IGraphicBufferProducer into AIDL so that it can be directly + * used in managed Binder calls. + */ +class Surface : public Parcelable { + public: + + String16 name; + sp<IGraphicBufferProducer> graphicBufferProducer; + + virtual status_t writeToParcel(Parcel* parcel) const override; + virtual status_t readFromParcel(const Parcel* parcel) override; + + // nameAlreadyWritten set to true by Surface.java, because it splits + // Parceling itself between managed and native code, so it only wants a part + // of the full parceling to happen on its native side. + status_t writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const; + + // nameAlreadyRead set to true by Surface.java, because it splits + // Parceling itself between managed and native code, so it only wants a part + // of the full parceling to happen on its native side. + status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead); + + private: + + static String16 readMaybeEmptyString16(const Parcel* parcel); +}; + +} // namespace view +} // namespace android + +#endif // ANDROID_GUI_VIEW_SURFACE_H diff --git a/include/ui/Fence.h b/include/ui/Fence.h index 58df24c4e0..37811bcd7c 100644 --- a/include/ui/Fence.h +++ b/include/ui/Fence.h @@ -23,8 +23,6 @@ #include <utils/RefBase.h> #include <utils/Timers.h> -#include <experimental/optional> - namespace android { class String8; @@ -105,26 +103,29 @@ public: // error occurs then SIGNAL_TIME_INVALID is returned. nsecs_t getSignalTime() const; -#if __cplusplus > 201103L - // hasSignaled returns whether the fence has signaled yet. Prefer this to + enum class Status { + Invalid, // Fence is invalid + Unsignaled, // Fence is valid but has not yet signaled + Signaled, // Fence is valid and has signaled + }; + + // getStatus() returns whether the fence has signaled yet. Prefer this to // getSignalTime() or wait() if all you care about is whether the fence has - // signaled. Returns an optional bool, which will have a value if there was - // no error. - inline std::experimental::optional<bool> hasSignaled() { + // signaled. + inline Status getStatus() { // The sync_wait call underlying wait() has been measured to be // significantly faster than the sync_fence_info call underlying // getSignalTime(), which might otherwise appear to be the more obvious // way to check whether a fence has signaled. switch (wait(0)) { case NO_ERROR: - return true; + return Status::Signaled; case -ETIME: - return false; + return Status::Unsignaled; default: - return {}; + return Status::Invalid; } } -#endif // Flattenable interface size_t getFlattenedSize() const; diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index 95ca0f347b..759c9ec647 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -76,11 +76,6 @@ public: GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage, std::string requestorName = "<Unknown>"); - // creates w * h buffer with a layer count - GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, - uint32_t inLayerCount, uint32_t inUsage, - std::string requestorName = "<Unknown>"); - // creates w * h buffer with a layer count using gralloc1 GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage, diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h index 8e93f724ff..001769fddf 100644 --- a/include/ui/GraphicBufferMapper.h +++ b/include/ui/GraphicBufferMapper.h @@ -39,7 +39,9 @@ class GraphicBufferMapper : public Singleton<GraphicBufferMapper> public: static inline GraphicBufferMapper& get() { return getInstance(); } + // This may NOT work on devices without a valid Gralloc2::Mapper. status_t registerBuffer(buffer_handle_t handle); + status_t registerBuffer(const GraphicBuffer* buffer); status_t unregisterBuffer(buffer_handle_t handle); diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index cb17da4d87..ddf107297e 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -96,6 +96,7 @@ cc_library_shared { "SurfaceControl.cpp", "SurfaceComposerClient.cpp", "SyncFeatures.cpp", + "view/Surface.cpp", ], shared_libs: [ diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index be2b1afd36..c26de6673b 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -318,16 +318,16 @@ status_t ConsumerBase::addReleaseFenceLocked(int slot, return OK; } - auto signaled = mSlots[slot].mFence->hasSignaled(); + auto status = mSlots[slot].mFence->getStatus(); - if (!signaled) { + if (status == Fence::Status::Invalid) { CB_LOGE("fence has invalid state"); return BAD_VALUE; } - if (*signaled) { + if (status == Fence::Status::Signaled) { mSlots[slot].mFence = fence; - } else { + } else { // status == Fence::Status::Unsignaled char fenceName[32] = {}; snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot); sp<Fence> mergedFence = Fence::merge( diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp index 73537bfc27..a6fa38aae5 100644 --- a/libs/gui/FrameTimestamps.cpp +++ b/libs/gui/FrameTimestamps.cpp @@ -235,6 +235,23 @@ void FrameEventHistory::dump(String8& outString) const { ProducerFrameEventHistory::~ProducerFrameEventHistory() = default; +nsecs_t ProducerFrameEventHistory::snapToNextTick( + nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval) { + nsecs_t tickOffset = (tickPhase - timestamp) % tickInterval; + // Integer modulo rounds towards 0 and not -inf before taking the remainder, + // so adjust the offset if it is negative. + if (tickOffset < 0) { + tickOffset += tickInterval; + } + return timestamp + tickOffset; +} + +nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline( + const nsecs_t now) const{ + return snapToNextTick( + now, mCompositorTiming.deadline, mCompositorTiming.interval); +} + void ProducerFrameEventHistory::updateAcquireFence( uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) { FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset); @@ -256,6 +273,8 @@ void ProducerFrameEventHistory::updateAcquireFence( void ProducerFrameEventHistory::applyDelta( const FrameEventHistoryDelta& delta) { + mCompositorTiming = delta.mCompositorTiming; + for (auto& d : delta.mDeltas) { // Avoid out-of-bounds access. if (d.mIndex >= mFrames.size()) { @@ -346,6 +365,11 @@ std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime( ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default; +void ConsumerFrameEventHistory::initializeCompositorTiming( + const CompositorTiming& compositorTiming) { + mCompositorTiming = compositorTiming; +} + void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) { // Overwrite all fields of the frame with default values unless set here. FrameEvents newTimestamps; @@ -393,7 +417,10 @@ void ConsumerFrameEventHistory::addPreComposition( void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber, const std::shared_ptr<FenceTime>& gpuCompositionDone, - const std::shared_ptr<FenceTime>& displayPresent) { + const std::shared_ptr<FenceTime>& displayPresent, + const CompositorTiming& compositorTiming) { + mCompositorTiming = compositorTiming; + FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); if (frame == nullptr) { ALOGE_IF(mProducerWantsEvents, @@ -450,6 +477,8 @@ void ConsumerFrameEventHistory::getFrameDelta( void ConsumerFrameEventHistory::getAndResetDelta( FrameEventHistoryDelta* delta) { + delta->mCompositorTiming = mCompositorTiming; + // Write these in order of frame number so that it is easy to // add them to a FenceTimeline in the proper order producer side. delta->mDeltas.reserve(mFramesDirty.size()); @@ -499,9 +528,8 @@ FrameEventsDelta::FrameEventsDelta( } } -size_t FrameEventsDelta::minFlattenedSize() { - constexpr size_t min = - sizeof(FrameEventsDelta::mFrameNumber) + +constexpr size_t FrameEventsDelta::minFlattenedSize() { + return sizeof(FrameEventsDelta::mFrameNumber) + sizeof(uint8_t) + // mIndex sizeof(uint8_t) + // mAddPostCompositeCalled sizeof(uint8_t) + // mAddRetireCalled @@ -512,7 +540,6 @@ size_t FrameEventsDelta::minFlattenedSize() { sizeof(FrameEventsDelta::mFirstRefreshStartTime) + sizeof(FrameEventsDelta::mLastRefreshStartTime) + sizeof(FrameEventsDelta::mDequeueReadyTime); - return min; } // Flattenable implementation @@ -618,6 +645,8 @@ status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size, FrameEventHistoryDelta& FrameEventHistoryDelta::operator=( FrameEventHistoryDelta&& src) { + mCompositorTiming = src.mCompositorTiming; + if (CC_UNLIKELY(!mDeltas.empty())) { ALOGE("FrameEventHistoryDelta: Clobbering history."); } @@ -626,8 +655,9 @@ FrameEventHistoryDelta& FrameEventHistoryDelta::operator=( return *this; } -size_t FrameEventHistoryDelta::minFlattenedSize() { - return sizeof(uint32_t); +constexpr size_t FrameEventHistoryDelta::minFlattenedSize() { + return sizeof(uint32_t) + // mDeltas.size() + sizeof(mCompositorTiming); } size_t FrameEventHistoryDelta::getFlattenedSize() const { @@ -654,6 +684,8 @@ status_t FrameEventHistoryDelta::flatten( return NO_MEMORY; } + FlattenableUtils::write(buffer, size, mCompositorTiming); + FlattenableUtils::write( buffer, size, static_cast<uint32_t>(mDeltas.size())); for (auto& d : mDeltas) { @@ -671,6 +703,8 @@ status_t FrameEventHistoryDelta::unflatten( return NO_MEMORY; } + FlattenableUtils::read(buffer, size, mCompositorTiming); + uint32_t deltaCount = 0; FlattenableUtils::read(buffer, size, deltaCount); if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) { diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp index f2d367711a..cc7d403040 100644 --- a/libs/gui/GraphicBufferAlloc.cpp +++ b/libs/gui/GraphicBufferAlloc.cpp @@ -15,21 +15,15 @@ ** limitations under the License. */ -#include <log/log.h> +#include <gui/GraphicBufferAlloc.h> -#include <ui/GraphicBuffer.h> +#include <log/log.h> -#include <gui/GraphicBufferAlloc.h> -// ---------------------------------------------------------------------------- namespace android { -// ---------------------------------------------------------------------------- -GraphicBufferAlloc::GraphicBufferAlloc() { -} - -GraphicBufferAlloc::~GraphicBufferAlloc() { -} +GraphicBufferAlloc::GraphicBufferAlloc() = default; +GraphicBufferAlloc::~GraphicBufferAlloc() = default; sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, @@ -44,15 +38,12 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width, if (err == NO_MEMORY) { GraphicBuffer::dumpAllocationsToSystemLog(); } - ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) " - "failed (%s), handle=%p", + ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p", width, height, layerCount, strerror(-err), graphicBuffer->handle); - return 0; + graphicBuffer.clear(); } return graphicBuffer; } -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- +} // namespace android diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 2fd29d5d7f..e2f733a41a 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -210,6 +210,10 @@ Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersi mFlags |= SENSOR_FLAG_WAKE_UP; } break; + case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT: + mStringType = SENSOR_STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT; + mFlags |= SENSOR_FLAG_ON_CHANGE_MODE; + break; case SENSOR_TYPE_WRIST_TILT_GESTURE: mStringType = SENSOR_STRING_TYPE_WRIST_TILT_GESTURE; mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE; diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp index 46eaf286ce..513b889b18 100644 --- a/libs/gui/SensorManager.cpp +++ b/libs/gui/SensorManager.cpp @@ -196,7 +196,8 @@ Sensor const* SensorManager::getDefaultSensor(int type) if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION || type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE || type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE || - type == SENSOR_TYPE_WRIST_TILT_GESTURE) { + type == SENSOR_TYPE_WRIST_TILT_GESTURE || + type == SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT) { wakeUpSensor = true; } // For now we just return the first sensor of that type we find. diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index c66362074e..d285ef0ce9 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -18,9 +18,9 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 -#include <android/native_window.h> +#include <gui/Surface.h> -#include <binder/Parcel.h> +#include <android/native_window.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -32,7 +32,6 @@ #include <gui/BufferItem.h> #include <gui/IProducerListener.h> -#include <gui/Surface.h> #include <gui/ISurfaceComposer.h> #include <private/gui/ComposerService.h> @@ -101,6 +100,10 @@ sp<ISurfaceComposer> Surface::composerService() const { return ComposerService::getComposerService(); } +nsecs_t Surface::now() const { + return systemTime(); +} + sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const { return mGraphicBufferProducer; } @@ -143,11 +146,51 @@ status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, outTransformMatrix); } +status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { + ATRACE_CALL(); + + DisplayStatInfo stats; + status_t err = composerService()->getDisplayStats(NULL, &stats); + + *outRefreshDuration = stats.vsyncPeriod; + + return NO_ERROR; +} + void Surface::enableFrameTimestamps(bool enable) { Mutex::Autolock lock(mMutex); + // If going from disabled to enabled, get the initial values for + // compositor and display timing. + if (!mEnableFrameTimestamps && enable) { + FrameEventHistoryDelta delta; + mGraphicBufferProducer->getFrameTimestamps(&delta); + mFrameEventHistory->applyDelta(delta); + } mEnableFrameTimestamps = enable; } +status_t Surface::getCompositorTiming( + nsecs_t* compositeDeadline, nsecs_t* compositeInterval, + nsecs_t* compositeToPresentLatency) { + Mutex::Autolock lock(mMutex); + if (!mEnableFrameTimestamps) { + return INVALID_OPERATION; + } + + if (compositeDeadline != nullptr) { + *compositeDeadline = + mFrameEventHistory->getNextCompositeDeadline(now()); + } + if (compositeInterval != nullptr) { + *compositeInterval = mFrameEventHistory->getCompositeInterval(); + } + if (compositeToPresentLatency != nullptr) { + *compositeToPresentLatency = + mFrameEventHistory->getCompositeToPresentLatency(); + } + return NO_ERROR; +} + static bool checkConsumerForUpdates( const FrameEvents* e, const uint64_t lastFrameNumber, const nsecs_t* outLatchTime, @@ -261,16 +304,6 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, return NO_ERROR; } -status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) { - ATRACE_CALL(); - - DisplayStatInfo stats; - status_t err = composerService()->getDisplayStats(NULL, &stats); - - *outRefreshDuration = stats.vsyncPeriod; - - return NO_ERROR; -} int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { Surface* c = getSelf(window); @@ -832,15 +865,21 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_AUTO_REFRESH: res = dispatchSetAutoRefresh(args); break; + case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION: + res = dispatchGetDisplayRefreshCycleDuration(args); + break; + case NATIVE_WINDOW_GET_NEXT_FRAME_ID: + res = dispatchGetNextFrameId(args); + break; case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS: res = dispatchEnableFrameTimestamps(args); break; + case NATIVE_WINDOW_GET_COMPOSITOR_TIMING: + res = dispatchGetCompositorTiming(args); + break; case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS: res = dispatchGetFrameTimestamps(args); break; - case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION: - res = dispatchGetDisplayRefreshCycleDuration(args); - break; default: res = NAME_NOT_FOUND; break; @@ -961,14 +1000,33 @@ int Surface::dispatchSetAutoRefresh(va_list args) { return setAutoRefresh(autoRefresh); } +int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) { + nsecs_t* outRefreshDuration = va_arg(args, int64_t*); + return getDisplayRefreshCycleDuration(outRefreshDuration); +} + +int Surface::dispatchGetNextFrameId(va_list args) { + uint64_t* nextFrameId = va_arg(args, uint64_t*); + *nextFrameId = getNextFrameNumber(); + return NO_ERROR; +} + int Surface::dispatchEnableFrameTimestamps(va_list args) { bool enable = va_arg(args, int); enableFrameTimestamps(enable); return NO_ERROR; } +int Surface::dispatchGetCompositorTiming(va_list args) { + nsecs_t* compositeDeadline = va_arg(args, int64_t*); + nsecs_t* compositeInterval = va_arg(args, int64_t*); + nsecs_t* compositeToPresentLatency = va_arg(args, int64_t*); + return getCompositorTiming(compositeDeadline, compositeInterval, + compositeToPresentLatency); +} + int Surface::dispatchGetFrameTimestamps(va_list args) { - uint32_t framesAgo = va_arg(args, uint32_t); + uint64_t frameId = va_arg(args, uint64_t); nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*); nsecs_t* outAcquireTime = va_arg(args, int64_t*); nsecs_t* outLatchTime = va_arg(args, int64_t*); @@ -979,18 +1037,13 @@ int Surface::dispatchGetFrameTimestamps(va_list args) { nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*); nsecs_t* outDequeueReadyTime = va_arg(args, int64_t*); nsecs_t* outReleaseTime = va_arg(args, int64_t*); - return getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo, + return getFrameTimestamps(frameId, outRequestedPresentTime, outAcquireTime, outLatchTime, outFirstRefreshStartTime, outLastRefreshStartTime, outGlCompositionDoneTime, outDisplayPresentTime, outDisplayRetireTime, outDequeueReadyTime, outReleaseTime); } -int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) { - nsecs_t* outRefreshDuration = va_arg(args, int64_t*); - return getDisplayRefreshCycleDuration(outRefreshDuration); -} - int Surface::connect(int api) { static sp<IProducerListener> listener = new DummyProducerListener(); return connect(api, listener); @@ -1539,74 +1592,4 @@ status_t Surface::getUniqueId(uint64_t* outId) const { return mGraphicBufferProducer->getUniqueId(outId); } -namespace view { - -status_t Surface::writeToParcel(Parcel* parcel) const { - return writeToParcel(parcel, false); -} - -status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const { - if (parcel == nullptr) return BAD_VALUE; - - status_t res = OK; - - if (!nameAlreadyWritten) { - res = parcel->writeString16(name); - if (res != OK) return res; - - /* isSingleBuffered defaults to no */ - res = parcel->writeInt32(0); - if (res != OK) return res; - } - - res = parcel->writeStrongBinder( - IGraphicBufferProducer::asBinder(graphicBufferProducer)); - - return res; -} - -status_t Surface::readFromParcel(const Parcel* parcel) { - return readFromParcel(parcel, false); -} - -status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) { - if (parcel == nullptr) return BAD_VALUE; - - status_t res = OK; - if (!nameAlreadyRead) { - name = readMaybeEmptyString16(parcel); - // Discard this for now - int isSingleBuffered; - res = parcel->readInt32(&isSingleBuffered); - if (res != OK) { - ALOGE("Can't read isSingleBuffered"); - return res; - } - } - - sp<IBinder> binder; - - res = parcel->readNullableStrongBinder(&binder); - if (res != OK) { - ALOGE("%s: Can't read strong binder", __FUNCTION__); - return res; - } - - graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder); - - return OK; -} - -String16 Surface::readMaybeEmptyString16(const Parcel* parcel) { - size_t len; - const char16_t* str = parcel->readString16Inplace(&len); - if (str != nullptr) { - return String16(str, len); - } else { - return String16(); - } -} - -} // namespace view - }; // namespace android diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 412c0f6486..52980270f2 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -479,8 +479,17 @@ public: return mFakeSurfaceComposer; } + nsecs_t now() const override { + return mNow; + } + + void setNow(nsecs_t now) { + mNow = now; + } + public: sp<FakeSurfaceComposer> mFakeSurfaceComposer; + nsecs_t mNow = 0; // mFrameEventHistory owns the instance of FakeProducerFrameEventHistory, // but this raw pointer gives access to test functionality. @@ -500,10 +509,12 @@ protected: struct RefreshEvents { RefreshEvents(FenceToFenceTimeMap& fenceMap, nsecs_t refreshStart) - : mFenceMap(fenceMap), - kStartTime(refreshStart + 1), - kGpuCompositionDoneTime(refreshStart + 2), - kPresentTime(refreshStart + 3) {} + : mFenceMap(fenceMap), + kCompositorTiming( + {refreshStart, refreshStart + 1, refreshStart + 2 }), + kStartTime(refreshStart + 3), + kGpuCompositionDoneTime(refreshStart + 4), + kPresentTime(refreshStart + 5) {} void signalPostCompositeFences() { mFenceMap.signalAllForTest( @@ -516,6 +527,8 @@ protected: FenceAndFenceTime mGpuCompositionDone { mFenceMap }; FenceAndFenceTime mPresent { mFenceMap }; + const CompositorTiming kCompositorTiming; + const nsecs_t kStartTime; const nsecs_t kGpuCompositionDoneTime; const nsecs_t kPresentTime; @@ -592,14 +605,20 @@ protected: native_window_set_buffer_count(mWindow.get(), 4); } + void disableFrameTimestamps() { + mFakeConsumer->mGetFrameTimestampsEnabled = false; + native_window_enable_frame_timestamps(mWindow.get(), 0); + mFrameTimestampsEnabled = false; + } + void enableFrameTimestamps() { mFakeConsumer->mGetFrameTimestampsEnabled = true; native_window_enable_frame_timestamps(mWindow.get(), 1); mFrameTimestampsEnabled = true; } - int getAllFrameTimestamps(uint32_t framesAgo) { - return native_window_get_frame_timestamps(mWindow.get(), framesAgo, + int getAllFrameTimestamps(uint64_t frameId) { + return native_window_get_frame_timestamps(mWindow.get(), frameId, &outRequestedPresentTime, &outAcquireTime, &outLatchTime, &outFirstRefreshStartTime, &outLastRefreshStartTime, &outGpuCompositionDoneTime, &outDisplayPresentTime, @@ -619,6 +638,13 @@ protected: outReleaseTime = -1; } + uint64_t getNextFrameId() { + uint64_t frameId = -1; + int status = native_window_get_next_frame_id(mWindow.get(), &frameId); + EXPECT_EQ(status, NO_ERROR); + return frameId; + } + void dequeueAndQueue(uint64_t frameIndex) { int fence = -1; ANativeWindowBuffer* buffer = nullptr; @@ -674,7 +700,8 @@ protected: oldFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime : FenceTime::NO_FENCE; mCfeh->addPostComposition(nOldFrame, gpuDoneFenceTime, - oldFrame->mRefreshes[2].mPresent.mFenceTime); + oldFrame->mRefreshes[2].mPresent.mFenceTime, + oldFrame->mRefreshes[2].kCompositorTiming); } // Latch the new frame. @@ -691,7 +718,8 @@ protected: std::shared_ptr<FenceTime>(oldFrame->mRelease.mFenceTime)); } mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime, - newFrame->mRefreshes[0].mPresent.mFenceTime); + newFrame->mRefreshes[0].mPresent.mFenceTime, + newFrame->mRefreshes[0].kCompositorTiming); // Retire the previous buffer just after compositing the new buffer. if (oldFrame != nullptr) { @@ -703,7 +731,8 @@ protected: newFrame->mRefreshes[1].mGpuCompositionDone.mFenceTime : FenceTime::NO_FENCE; mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime, - newFrame->mRefreshes[1].mPresent.mFenceTime); + newFrame->mRefreshes[1].mPresent.mFenceTime, + newFrame->mRefreshes[1].kCompositorTiming); } void QueryPresentRetireSupported( @@ -733,7 +762,8 @@ protected: int64_t outDequeueReadyTime = -1; int64_t outReleaseTime = -1; - FrameEvents mFrames[2] { { mFenceMap, 1000 }, { mFenceMap, 2000 } }; + FrameEvents mFrames[3] { + { mFenceMap, 1000 }, { mFenceMap, 2000 }, { mFenceMap, 3000 } }; }; @@ -748,6 +778,8 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); + const uint64_t fId = getNextFrameId(); + // Verify the producer doesn't get frame timestamps piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); @@ -761,27 +793,58 @@ TEST_F(GetFrameTimestampsTest, DefaultDisabled) { EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); // Verify attempts to get frame timestamps fail. - const uint32_t framesAgo = 0; - int result = getAllFrameTimestamps(framesAgo); + int result = getAllFrameTimestamps(fId); EXPECT_EQ(INVALID_OPERATION, result); EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); + + // Verify compositor timing query fails. + nsecs_t compositeDeadline = 0; + nsecs_t compositeInterval = 0; + nsecs_t compositeToPresentLatency = 0; + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(INVALID_OPERATION, result); } // This test verifies that the frame timestamps are retrieved if explicitly // enabled via native_window_enable_frame_timestamps. TEST_F(GetFrameTimestampsTest, EnabledSimple) { + CompositorTiming initialCompositorTiming { + 1000000000, // 1s deadline + 16666667, // 16ms interval + 50000000, // 50ms present latency + }; + mCfeh->initializeCompositorTiming(initialCompositorTiming); + enableFrameTimestamps(); + // Verify the compositor timing query gets the initial compositor values + // after timststamps are enabled; even before the first frame is queued + // or dequeued. + nsecs_t compositeDeadline = 0; + nsecs_t compositeInterval = 0; + nsecs_t compositeToPresentLatency = 0; + mSurface->setNow(initialCompositorTiming.deadline - 1); + int result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline); + EXPECT_EQ(initialCompositorTiming.interval, compositeInterval); + EXPECT_EQ(initialCompositorTiming.presentLatency, + compositeToPresentLatency); + int fence; ANativeWindowBuffer* buffer; EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); - EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount); + EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount); + + const uint64_t fId1 = getNextFrameId(); // Verify getFrameTimestamps is piggybacked on dequeue. ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence)); EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount); - EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount); + EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount); NewFrameEventsEntry f1; f1.frameNumber = 1; @@ -798,14 +861,13 @@ TEST_F(GetFrameTimestampsTest, EnabledSimple) { ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence)); EXPECT_EQ(1, mFakeConsumer->mAddFrameTimestampsCount); EXPECT_EQ(1u, mFakeConsumer->mLastAddedFrameNumber); - EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount); + EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount); // Verify queries for timestamps that the producer doesn't know about // triggers a call to see if the consumer has any new timestamps. - const uint32_t framesAgo = 0; - int result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); - EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount); + EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount); } void GetFrameTimestampsTest::QueryPresentRetireSupported( @@ -833,16 +895,245 @@ TEST_F(GetFrameTimestampsTest, QueryRetireSupported) { QueryPresentRetireSupported(false, true); } -// This test verifies that: -// 1) The timestamps recorded in the consumer's FrameTimestampsHistory are -// properly retrieved by the producer for the correct frames. -// 2) When framesAgo is 0, it is querying for the most recently queued frame. +TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) { + nsecs_t phase = 4000; + nsecs_t interval = 1000; + + // Timestamp in previous interval. + nsecs_t timestamp = 3500; + EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp in next interval. + timestamp = 4500; + EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp multiple intervals before. + timestamp = 2500; + EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp multiple intervals after. + timestamp = 6500; + EXPECT_EQ(7000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp on previous interval. + timestamp = 3000; + EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp on next interval. + timestamp = 5000; + EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); + + // Timestamp equal to phase. + timestamp = 4000; + EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick( + timestamp, phase, interval)); +} + +// int(big_timestamp / interval) < 0, which can cause a crash or invalid result +// if the number of intervals elapsed is internally stored in an int. +TEST_F(GetFrameTimestampsTest, SnapToNextTickOverflow) { + nsecs_t phase = 0; + nsecs_t interval = 4000; + nsecs_t big_timestamp = 8635916564000; + int32_t intervals = big_timestamp / interval; + + EXPECT_LT(intervals, 0); + EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick( + big_timestamp, phase, interval)); + EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick( + big_timestamp, big_timestamp, interval)); +} + +// This verifies the compositor timing is updated by refresh events +// and piggy backed on a queue, dequeue, and enabling of timestamps.. +TEST_F(GetFrameTimestampsTest, CompositorTimingUpdatesBasic) { + CompositorTiming initialCompositorTiming { + 1000000000, // 1s deadline + 16666667, // 16ms interval + 50000000, // 50ms present latency + }; + mCfeh->initializeCompositorTiming(initialCompositorTiming); + + enableFrameTimestamps(); + + // We get the initial values before any frames are submitted. + nsecs_t compositeDeadline = 0; + nsecs_t compositeInterval = 0; + nsecs_t compositeToPresentLatency = 0; + mSurface->setNow(initialCompositorTiming.deadline - 1); + int result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline); + EXPECT_EQ(initialCompositorTiming.interval, compositeInterval); + EXPECT_EQ(initialCompositorTiming.presentLatency, + compositeToPresentLatency); + + const uint64_t fId1 = getNextFrameId(); + dequeueAndQueue(0); + addFrameEvents(true, NO_FRAME_INDEX, 0); + + // Still get the initial values because the frame events for frame 0 + // didn't get a chance to piggyback on a queue or dequeue yet. + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline); + EXPECT_EQ(initialCompositorTiming.interval, compositeInterval); + EXPECT_EQ(initialCompositorTiming.presentLatency, + compositeToPresentLatency); + + const uint64_t fId2 = getNextFrameId(); + dequeueAndQueue(1); + addFrameEvents(true, 0, 1); + + // Now expect the composite values associated with frame 1. + mSurface->setNow(mFrames[0].mRefreshes[1].kCompositorTiming.deadline); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.deadline, + compositeDeadline); + EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.interval, + compositeInterval); + EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.presentLatency, + compositeToPresentLatency); + + dequeueAndQueue(2); + addFrameEvents(true, 1, 2); + + // Now expect the composite values associated with frame 2. + mSurface->setNow(mFrames[1].mRefreshes[1].kCompositorTiming.deadline); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.deadline, + compositeDeadline); + EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.interval, + compositeInterval); + EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.presentLatency, + compositeToPresentLatency); + + // Re-enabling frame timestamps should get the latest values. + disableFrameTimestamps(); + enableFrameTimestamps(); + + // Now expect the composite values associated with frame 3. + mSurface->setNow(mFrames[2].mRefreshes[1].kCompositorTiming.deadline); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.deadline, + compositeDeadline); + EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.interval, + compositeInterval); + EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.presentLatency, + compositeToPresentLatency); +} + +// This verifies the compositor deadline properly snaps to the the next +// deadline based on the current time. +TEST_F(GetFrameTimestampsTest, CompositorTimingDeadlineSnaps) { + CompositorTiming initialCompositorTiming { + 1000000000, // 1s deadline + 16666667, // 16ms interval + 50000000, // 50ms present latency + }; + mCfeh->initializeCompositorTiming(initialCompositorTiming); + + enableFrameTimestamps(); + + nsecs_t compositeDeadline = 0; + nsecs_t compositeInterval = 0; + nsecs_t compositeToPresentLatency = 0; + + // A "now" just before the deadline snaps to the deadline. + mSurface->setNow(initialCompositorTiming.deadline - 1); + int result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline); + nsecs_t expectedDeadline = initialCompositorTiming.deadline; + EXPECT_EQ(expectedDeadline, compositeDeadline); + + const uint64_t fId1 = getNextFrameId(); + dequeueAndQueue(0); + addFrameEvents(true, NO_FRAME_INDEX, 0); + + // A "now" just after the deadline snaps properly. + mSurface->setNow(initialCompositorTiming.deadline + 1); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + expectedDeadline = + initialCompositorTiming.deadline +initialCompositorTiming.interval; + EXPECT_EQ(expectedDeadline, compositeDeadline); + + const uint64_t fId2 = getNextFrameId(); + dequeueAndQueue(1); + addFrameEvents(true, 0, 1); + + // A "now" just after the next interval snaps properly. + mSurface->setNow( + mFrames[0].mRefreshes[1].kCompositorTiming.deadline + + mFrames[0].mRefreshes[1].kCompositorTiming.interval + 1); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + expectedDeadline = + mFrames[0].mRefreshes[1].kCompositorTiming.deadline + + mFrames[0].mRefreshes[1].kCompositorTiming.interval * 2; + EXPECT_EQ(expectedDeadline, compositeDeadline); + + dequeueAndQueue(2); + addFrameEvents(true, 1, 2); + + // A "now" over 1 interval before the deadline snaps properly. + mSurface->setNow( + mFrames[1].mRefreshes[1].kCompositorTiming.deadline - + mFrames[1].mRefreshes[1].kCompositorTiming.interval - 1); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + expectedDeadline = + mFrames[1].mRefreshes[1].kCompositorTiming.deadline - + mFrames[1].mRefreshes[1].kCompositorTiming.interval; + EXPECT_EQ(expectedDeadline, compositeDeadline); + + // Re-enabling frame timestamps should get the latest values. + disableFrameTimestamps(); + enableFrameTimestamps(); + + // A "now" over 2 intervals before the deadline snaps properly. + mSurface->setNow( + mFrames[2].mRefreshes[1].kCompositorTiming.deadline - + mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2 - 1); + result = native_window_get_compositor_timing(mWindow.get(), + &compositeDeadline, &compositeInterval, &compositeToPresentLatency); + EXPECT_EQ(NO_ERROR, result); + expectedDeadline = + mFrames[2].mRefreshes[1].kCompositorTiming.deadline - + mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2; + EXPECT_EQ(expectedDeadline, compositeDeadline); +} + +// This verifies the timestamps recorded in the consumer's +// FrameTimestampsHistory are properly retrieved by the producer for the +// correct frames. TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { enableFrameTimestamps(); + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); + const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); @@ -853,9 +1144,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { mFrames[1].signalRefreshFences(); // Verify timestamps are correct for frame 1. - uint32_t framesAgo = 1; resetTimestamps(); - int result = getAllFrameTimestamps(framesAgo); + int result = getAllFrameTimestamps(fId1); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); @@ -870,9 +1160,8 @@ TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) { EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime); // Verify timestamps are correct for frame 2. - framesAgo = 0; resetTimestamps(); - result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId2); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime); @@ -893,9 +1182,8 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); - const uint32_t framesAgo = 0; - // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify queue-related timestamps for f1 are available immediately in the @@ -903,7 +1191,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + int result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); @@ -915,7 +1203,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[0].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + result = native_window_get_frame_timestamps(mWindow.get(), fId1, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); @@ -924,6 +1212,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime); // Dequeue and queue frame 2. + const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); // Verify queue-related timestamps for f2 are available immediately in the @@ -931,7 +1220,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { // acquire fence. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); @@ -943,7 +1232,7 @@ TEST_F(GetFrameTimestampsTest, QueueTimestampsNoSync) { mFrames[1].signalQueueFences(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + result = native_window_get_frame_timestamps(mWindow.get(), fId2, &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); @@ -961,6 +1250,7 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. + const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); @@ -971,9 +1261,8 @@ TEST_F(GetFrameTimestampsTest, ZeroRequestedTimestampsNoSync) { mFrames[1].signalRefreshFences(); // Verify a request for no timestamps doesn't result in a sync call. - const uint32_t framesAgo = 0; int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + int result = native_window_get_frame_timestamps(mWindow.get(), fId2, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); EXPECT_EQ(NO_ERROR, result); @@ -987,6 +1276,7 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); @@ -1001,10 +1291,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. - uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = getAllFrameTimestamps(framesAgo); + int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1021,10 +1310,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { // Verify available timestamps are correct for frame 1 again, before any // fence has been signaled. // This time a sync call should not be necessary. - framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1043,10 +1331,9 @@ TEST_F(GetFrameTimestampsTest, FencesInProducerNoSync) { mFrames[0].signalReleaseFences(); // Verify all timestamps are available without a sync call. - framesAgo = 1; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1069,9 +1356,8 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { enableFrameTimestamps(); mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); - const uint32_t framesAgo = 1; - // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); @@ -1088,7 +1374,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = getAllFrameTimestamps(framesAgo); + int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1110,7 +1396,7 @@ TEST_F(GetFrameTimestampsTest, NoGpuNoSync) { // sync call. resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1132,10 +1418,12 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true); // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); mFrames[0].signalQueueFences(); // Dequeue and queue frame 2. + const uint64_t fId2 = getNextFrameId(); dequeueAndQueue(1); mFrames[1].signalQueueFences(); @@ -1146,10 +1434,9 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { // fence has been signaled. // Note: A sync call is necessary here since the events triggered by // addFrameEvents didn't get to piggyback on the earlier queues/dequeues. - uint32_t framesAgo = 1; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = getAllFrameTimestamps(framesAgo); + int result = getAllFrameTimestamps(fId1); EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime); @@ -1167,15 +1454,14 @@ TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) { mFrames[0].signalReleaseFences(); mFrames[1].signalRefreshFences(); - // Verify querying for all timestmaps of f2 does not do a sync call. - // Even though the lastRefresh, retire, dequeueReady, and release times aren't + // Verify querying for all timestmaps of f2 does not do a sync call. Even + // though the lastRefresh, retire, dequeueReady, and release times aren't // available, a sync call should not occur because it's not possible for f2 // to encounter the final value for those events until another frame is // queued. - framesAgo = 0; resetTimestamps(); oldCount = mFakeConsumer->mGetFrameTimestampsCount; - result = getAllFrameTimestamps(framesAgo); + result = getAllFrameTimestamps(fId2); EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount); EXPECT_EQ(NO_ERROR, result); EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime); @@ -1200,14 +1486,14 @@ void GetFrameTimestampsTest::PresentOrRetireUnsupportedNoSyncTest( displayPresentSupported, displayRetireSupported); // Dequeue and queue frame 1. + const uint64_t fId1 = getNextFrameId(); dequeueAndQueue(0); // Verify a query for the Present and Retire times do not trigger // a sync call if they are not supported. - const uint32_t framesAgo = 0; resetTimestamps(); int oldCount = mFakeConsumer->mGetFrameTimestampsCount; - int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo, + int result = native_window_get_frame_timestamps(mWindow.get(), fId1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, displayPresentSupported ? nullptr : &outDisplayPresentTime, displayRetireSupported ? nullptr : &outDisplayRetireTime, diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp new file mode 100644 index 0000000000..5ed3d3bebb --- /dev/null +++ b/libs/gui/view/Surface.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Surface" + +#include <gui/view/Surface.h> + +#include <binder/Parcel.h> + +#include <utils/Log.h> + +#include <gui/IGraphicBufferProducer.h> + +namespace android { +namespace view { + +status_t Surface::writeToParcel(Parcel* parcel) const { + return writeToParcel(parcel, false); +} + +status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const { + if (parcel == nullptr) return BAD_VALUE; + + status_t res = OK; + + if (!nameAlreadyWritten) { + res = parcel->writeString16(name); + if (res != OK) return res; + + /* isSingleBuffered defaults to no */ + res = parcel->writeInt32(0); + if (res != OK) return res; + } + + res = parcel->writeStrongBinder( + IGraphicBufferProducer::asBinder(graphicBufferProducer)); + + return res; +} + +status_t Surface::readFromParcel(const Parcel* parcel) { + return readFromParcel(parcel, false); +} + +status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) { + if (parcel == nullptr) return BAD_VALUE; + + status_t res = OK; + if (!nameAlreadyRead) { + name = readMaybeEmptyString16(parcel); + // Discard this for now + int isSingleBuffered; + res = parcel->readInt32(&isSingleBuffered); + if (res != OK) { + ALOGE("Can't read isSingleBuffered"); + return res; + } + } + + sp<IBinder> binder; + + res = parcel->readNullableStrongBinder(&binder); + if (res != OK) { + ALOGE("%s: Can't read strong binder", __FUNCTION__); + return res; + } + + graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder); + + return OK; +} + +String16 Surface::readMaybeEmptyString16(const Parcel* parcel) { + size_t len; + const char16_t* str = parcel->readString16Inplace(&len); + if (str != nullptr) { + return String16(str, len); + } else { + return String16(); + } +} + +} // namespace view +} // namespace android diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 5ef95ec965..b54442667f 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -50,8 +50,8 @@ GraphicBuffer::GraphicBuffer() height = stride = format = - layerCount = usage = 0; + layerCount = 0; handle = NULL; } @@ -64,8 +64,8 @@ GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, height = stride = format = - layerCount = usage = 0; + layerCount = 0; handle = NULL; mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, inUsage, std::move(requestorName)); @@ -81,8 +81,8 @@ GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, height = stride = format = - layerCount = usage = 0; + layerCount = 0; handle = NULL; mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount, producerUsage, consumerUsage, std::move(requestorName)); diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index b0ed2df596..a3b6e18cdd 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -63,7 +63,14 @@ status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) if (mMapper->valid()) { error = static_cast<gralloc1_error_t>(mMapper->retain(handle)); } else { + // This always returns GRALLOC1_BAD_HANDLE when handle is from a + // remote process and mDevice is backed by Gralloc1On0Adapter. error = mDevice->retain(handle); + if (error == GRALLOC1_ERROR_BAD_HANDLE && + mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { + ALOGE("registerBuffer by handle is not supported with " + "Gralloc1On0Adapter"); + } } ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d", diff --git a/libs/vr/libgvr/.clang-format b/libs/vr/libgvr/.clang-format deleted file mode 100644 index 328716087e..0000000000 --- a/libs/vr/libgvr/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -Language: Cpp -DisableFormat: true diff --git a/libs/vr/libgvr/Android.mk b/libs/vr/libgvr/Android.mk deleted file mode 100644 index 0daf2ea17c..0000000000 --- a/libs/vr/libgvr/Android.mk +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -LOCAL_PATH := $(call my-dir) - -include_dirs := \ - $(LOCAL_PATH)/include \ - $(LOCAL_PATH)/prebuilt/include - -# Java platform library for the system implementation of the GVR API. -include $(CLEAR_VARS) -LOCAL_MODULE := com.google.vr.gvr.platform -LOCAL_REQUIRED_MODULES := libgvr_system_loader libgvr_system -LOCAL_SRC_FILES := $(call all-java-files-under, java) -include $(BUILD_JAVA_LIBRARY) - -# Library to perform dlopen on the actual platform library. -include $(CLEAR_VARS) -LOCAL_MODULE := libgvr_system_loader -LOCAL_SRC_FILES := library_loader.cpp -include $(BUILD_SHARED_LIBRARY) - -# Shared library implementing the GVR API. -include $(CLEAR_VARS) -LOCAL_MODULE := libgvr_system - -LOCAL_SRC_FILES := \ - shim_gvr.cpp \ - shim_gvr_controller.cpp \ - shim_gvr_private.cpp \ - deviceparams/CardboardDevice.nolite.proto - -LOCAL_MODULE_CLASS := SHARED_LIBRARIES - -LOCAL_C_INCLUDES := $(include_dirs) -LOCAL_C_INCLUDES += $(call local-generated-sources-dir)/proto/$(LOCAL_PATH) -LOCAL_EXPORT_C_INCLUDE_DIRS := $(include_dirs) - -gvr_api_linker_script := $(LOCAL_PATH)/exported_apis.lds -LOCAL_ADDITIONAL_DEPENDENCIES := $(gvr_api_linker_script) - -LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -LOCAL_LDFLAGS += -Wl,-version-script,$(gvr_api_linker_script) - -LOCAL_SHARED_LIBRARIES := \ - libandroid_runtime \ - libbase \ - libbinder \ - libcutils \ - libutils \ - libgui \ - libui \ - libEGL \ - libGLESv2 \ - libvulkan \ - libhardware \ - liblog \ - libsync \ - libprotobuf-cpp-full - -LOCAL_STATIC_LIBRARIES := \ - libdisplay \ - libbufferhub \ - libbufferhubqueue \ - libdvrcommon \ - libeds \ - libdvrgraphics \ - libsensor \ - libperformance \ - libpdx_default_transport \ - -include $(BUILD_SHARED_LIBRARY) - -# Prebuilt shared library for libgvr_audio.so -include $(CLEAR_VARS) -LOCAL_MODULE := libgvr_audio -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_MODULE_SUFFIX := .so -LOCAL_MULTILIB := both -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 -LOCAL_SRC_FILES_arm := prebuilt/lib/android_arm/libgvr_audio.so -LOCAL_SRC_FILES_arm64 := prebuilt/lib/android_arm64/libgvr_audio.so -LOCAL_SRC_FILES_x86 := prebuilt/lib/android_x86/libgvr_audio.so -LOCAL_SRC_FILES_x86_64 := prebuilt/lib/android_x86_64/libgvr_audio.so -include $(BUILD_PREBUILT) - -# Prebuilt shared library for libgvr.so -include $(CLEAR_VARS) -LOCAL_MODULE := libgvr -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/prebuilt/include -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_MODULE_SUFFIX := .so -LOCAL_MULTILIB := both -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 -LOCAL_SRC_FILES_arm := prebuilt/lib/android_arm/libgvr.so -LOCAL_SRC_FILES_arm64 := prebuilt/lib/android_arm64/libgvr.so -LOCAL_SRC_FILES_x86 := prebuilt/lib/android_x86/libgvr.so -LOCAL_SRC_FILES_x86_64 := prebuilt/lib/android_x86_64/libgvr.so -include $(BUILD_PREBUILT) - -# Prebuilt Java static library for common_library.aar -include $(CLEAR_VARS) -LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ - gvr_common_library_aar:prebuilt/lib/common_library.aar -include $(BUILD_MULTI_PREBUILT) - -# Dummy libgvr_ext to be used along side libgvr.so prebuilt. -# This shall be replaced with Google3 prebuilts in future. -include $(CLEAR_VARS) -LOCAL_MODULE := libgvr_ext -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_SRC_FILES := dummy_gvr_ext.cpp -LOCAL_LDLIBS := -llog -LOCAL_MODULE_TAGS := optional -LOCAL_SHARED_LIBRARIES += libgvr -LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64 -include $(BUILD_STATIC_LIBRARY) diff --git a/libs/vr/libgvr/CPPLINT.cfg b/libs/vr/libgvr/CPPLINT.cfg deleted file mode 100644 index 2da1c504c1..0000000000 --- a/libs/vr/libgvr/CPPLINT.cfg +++ /dev/null @@ -1 +0,0 @@ -filter=-build/header_guard,-build/include_alpha diff --git a/libs/vr/libgvr/README.dreamos b/libs/vr/libgvr/README.dreamos deleted file mode 100644 index d847210c98..0000000000 --- a/libs/vr/libgvr/README.dreamos +++ /dev/null @@ -1 +0,0 @@ -Files under public/vr/gvr were imported from the public Google VR SDK. diff --git a/libs/vr/libgvr/com.google.vr.gvr.platform.xml b/libs/vr/libgvr/com.google.vr.gvr.platform.xml deleted file mode 100644 index 9297c7f3b8..0000000000 --- a/libs/vr/libgvr/com.google.vr.gvr.platform.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<permissions> - <library name="com.google.vr.gvr.platform" - file="/system/framework/com.google.vr.gvr.platform.jar" /> -</permissions> diff --git a/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto b/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto deleted file mode 100644 index 77b5d72878..0000000000 --- a/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto +++ /dev/null @@ -1,299 +0,0 @@ - -syntax = "proto2"; - -option java_package = "com.google.vrtoolkit.cardboard.proto"; -option java_outer_classname = "CardboardDevice"; -option optimize_for = SPEED; - -package proto; - - -/** - * Message describing properties of a VR head mount device (HMD) which uses an - * interchangeable smartphone as a display (e.g. Google Cardboard). - * - * While some properties are certain (e.g. inter_lens_distance), others - * represent nominal values which may be refined depending on context (e.g. - * viewport_angles). - * - * Lengths are in meters unless noted otherwise. Fields are _required_ - * unless noted otherwise. - * - * Some context on why this set of parameters are deemed necessary and - * sufficient: - * * FOV scale can be reasonably approximated from lens-to-screen distance - * and display size (i.e. knowing lens focal length isn't crucial). - * * Lenses are assumed to be horizontally centered with respect to - * display. - * * The display is not necessarily vertically centered. For interchangeable - * phones where the device rests against a tray, we can derive - * the vertical offset from tray-to-lens height along with phone-specific - * bezel and screen sizes (supplied separately). - */ -message DeviceParams { - // String identifying the device's vendor (e.g. "Google, Inc."). - // A device's [vendor, model] pair is expected to be globally unique. - optional string vendor = 1; - - // String identifying the device's model, including revision info if - // needed (e.g. "Cardboard v1"). A device's [vendor, model] pair is - // expected to be globally unique. - optional string model = 2; - - // Distance from the display screen to the optical center of lenses. - // This is a required field for distortion rendering, and must be positive. - optional float screen_to_lens_distance = 3; - - // Horizontal distance between optical center of the lenses. - // This is a required field for distortion rendering, and must be positive. - optional float inter_lens_distance = 4; - - // Four-element tuple (left, right, bottom, top) of left eye's view extent - // angles relative to center, assuming the following: - // * eye is aligned with optical center of lens - // * display screen is equal or larger than extents viewable through lens - // * nominal eye-to-lens distance - // * mirrored field of view will be applied to the right eye - // These values are essentially used as an optimization to avoid rendering - // pixels which can't be seen. - // This is a required field for distortion rendering, and angles must be - // positive. - repeated float left_eye_field_of_view_angles = 5 [packed = true]; - - enum VerticalAlignmentType { - BOTTOM = 0; // phone rests against a fixed bottom tray - CENTER = 1; // phone screen assumed to be centered w.r.t. lenses - TOP = 2; // phone rests against a fixed top tray - } - - // Set according to vertical alignment strategy-- see enum comments above. - // NOTE: If you set this to CENTER, see special instructions for the - // tray_to_lens_distance field below. - optional VerticalAlignmentType vertical_alignment = 11 [default = BOTTOM]; - - // If the phone is aligned vertically within the device by resting against - // a fixed top or bottom tray, this is the distance from the tray to - // optical center of the lenses. - // This is a required field for distortion rendering, and must be positive. - // NOTE: Due to a bug in initial versions of the SDK's, this field - // must be set explicitly to .035 when vertical_alignment = CENTER. - optional float tray_to_lens_distance = 6; - - // Coefficients Ki for pincushion distortion function which maps - // from position on real screen to virtual screen (i.e. texture) relative - // to optical center: - // - // p' = p (1 + K1 r^2 + K2 r^4 + ... + Kn r^(2n)) - // - // where r is the distance in tan-angle units from the optical center, - // p the input point, and p' the output point. Tan-angle units can be - // computed as distance on the screen divided by distance from the - // virtual eye to the screen. - repeated float distortion_coefficients = 7 [packed = true]; - // Slots 8, 9 reserved for per-color channel distortion. - - // Optionally, whether the head mount uses a magnet in any part of its - // design. Intended as hint as to whether phone's magnetometer is - // available for tasks such as orientation tracking. - optional bool has_magnet = 10; - - enum ButtonType { - // No physical button, and touch screen is not easily accessible. - NONE = 0; - // HMD has integrated magnet switch similar to original Cardboard. - MAGNET = 1; - // At least a portion of touch screen is easily accessible to user for taps. - TOUCH = 2; - // Touch screen is triggered indirectly via integrated button on the HMD. - INDIRECT_TOUCH = 3; - } - - // Specify primary input mechanism of the HMD. Intended for advisory - // purposes only, to address simple questions such as "can HMD - // be used with apps requiring a physical button event?" or "what icon - // should be used to represent button action to the user?". - optional ButtonType primary_button = 12 [default = MAGNET]; - - // Some internal data for Cardboard. This data is not intended to be - // set or used by developers, and any data in this proto is not guaranteed - // to be supported with new SDK updates. - optional CardboardInternalParams internal = 1729; - - // Optionally, specifies the additional parameters that are necessary for - // a Daydream-ready headset. This field is non-null if the headset is - // Daydream-ready. - // TODO(b/30112366) The inclusion of this message inside a DeviceParams is a - // somewhat ugly result of some historical choices in the SDK. We should - // consider refactoring our code to allow us to remove this, and the - // CardboardInternalParams messages from this proto. - optional DaydreamInternalParams daydream_internal = 196883; -} - -// TODO(b/27108179): CardboardInternalParams should be migrated into its own -// file, and not live in this file. - -/** - * Message describing parameters that are used internally by Cardboard - * and VRToolkit. These parameters don't necessarily fit into the DeviceParams - * notion of a VR viewer combined with user's phone (e.g. case of viewer with - * dedicated display, etc.) and are not intended to be used by developers - * and may or may not be supported or changed without notice on new releases - * of the Cardboard SDK or VR Toolkit. - */ -message CardboardInternalParams { - // Used to specify a per-eye post-process transformation -- an optional - // rotation and x-axis reflection -- to be applied after distortion - // correction. - enum OrientationType { - CCW_0_DEGREES = 0; - CCW_90_DEGREES = 1; - CCW_180_DEGREES = 2; - CCW_270_DEGREES = 3; - CCW_0_DEGREES_MIRRORED = 4; - CCW_90_DEGREES_MIRRORED = 5; - CCW_180_DEGREES_MIRRORED = 6; - CCW_270_DEGREES_MIRRORED = 7; - } - - // Specify a post-process transformation that is applied after the distortion - // function. This field is optional, if not specified, CCW_0_DEGREES is - // assumed. If repeated, the first orientation is for the left eye, the second - // is for the right eye. - // - // For example, if [CCW_90_DEGREES, CCW_270_DEGREES_MIRRORED] is specified, - // - // this input: - // - // ***************** ***************** - // *1 2* *1 2* - // * * * * *** * - // * * * * * * * - // * **** * * * * * - // *4 3* *4 3* - // ***************** ***************** - // - // is rendered on the screen like this: - // - // ***************** ***************** - // *2 * 3* *3 * 2* - // * * * * ** * - // * * * * * * - // * *** * * *** * - // *1 4* *4 1* - // ***************** ***************** - repeated OrientationType eye_orientations = 1 [packed = true]; - - // Specify a horizontal offset from the middle of the screen to the center of - // the lens, in meters. If one is not provided, half of the inter lens - // distance is used. - // - // This is only necessary if the HMD has some sort of periscope effect, where - // the position of the lenses, relative to the screen, is different than - // their position relative to the user. - // - // For example, in the HMD below, two mirrors reflect the image from the - // screen to the user, creating a larger inter lens distance than the screen - // can support. - // - // [In the diagram below, S = screen, L = lens] - // - // screen_center_to_lens_distance - // |--| - // - // ------------------------- - // | SSSSSSSSSSSS | - // | | | | | - // | /----/ | \----\ | - // | | | | | - // | LLL LLL | - // - // |---------------| - // inter_lens_distance - // - optional float screen_center_to_lens_distance = 2; - - // Optional x-dimension physical pixels per inch of the external display, - // assuming landscape orientation. If set, this will override OS-reported - // values. - optional float x_ppi_override = 3; - - // Optional y-dimension physical pixels per inch of the external display, - // assuming landscape orientation. If set, this will override OS-reported - // values. - optional float y_ppi_override = 4; - - // Optional string identifying the device's accelerometer and gyroscope. - // If either field is filled out, the corresponding sensor (gyroscope or - // accelerometer) will be used for head tracking. - // - // Valid strings are usually found in: - // vendor/<vendorname>/<devicename>/xxx/sensors.cpp - // - // For dynamic sensors, this string will be provided in a separate way. - // - // NB: Vendors and manufacturers should make the name of the sensor as - // specific as possible, since if multiple sensors with the same name are - // connected, the first will be used. - optional string accelerometer = 5; - optional string gyroscope = 6; -} - -/** - * Message describing the additional properties of a Daydream-ready headset that - * are not used for a normal cardboard viewer. These parameters are not intended - * to be used, or consumed, by developers and may or may not be supported or - * changed without notice on new releases of the Cardboard SDK or VR Toolkit. - */ -message DaydreamInternalParams { - // The version of the Daydream-ready specification to which this device - // conforms. - optional int32 version = 1; - - // Optionally, specifies the collection of screen alignment markers in the - // headset. - repeated ScreenAlignmentMarker alignment_markers = 2; -} - -/** - * Message describing a single screen alignment marker. - * - * A screen alignment marker is a capacitive touch point affixed to the headset - * which is capable of making contact with the screen. The location of the touch - * point is given in meters, measured along a horizontal axis which passes - * through the center of both lenses, and a vertical axis which is equidistant - * from the centers of the lenses. A positive vertical value indicates that the - * point lies above the horizontal axis, and a positive horizontal value - * indicates that the point lies to the right, as seen by a user of the headset, - * of the vertical axis. For example, if the following is a representation of a - * headset, viewed from the point of view of a user, with three points marked by - * the numbers 1, 2, and 3. - * - * ***************************************************************************** - * * ^ * - * * _____ | _____ * - * * / \ 1 / \ * - * * / \ | / \ * - * * / \ | / \ * - * * / \ | / \ * - * * / \ | / \ * - * *---------|-------*-------|----------+------2---|-------*-------|---------->* - * * \ / | \ / * - * * \ / | \ / * - * * \ / 3 | \ / * - * * \ / | \ / * - * * \_____/ | \_____/ * - * * | * - * * | * - * ***************************************************************************** - * - * Then the coordinates of point 1 could be horizontal = 0.0, vertical = 0.035; - * point 2 could be horizontal = 0.02; and point 3 could be horizontal = -0.01 - * vertical = -0.012 - */ -message ScreenAlignmentMarker { - // The horizontal coordinate of the touch point. - optional float horizontal = 1; - - // The vertical coordinate of the touch point. - optional float vertical = 2; -} diff --git a/libs/vr/libgvr/dummy_gvr_ext.cpp b/libs/vr/libgvr/dummy_gvr_ext.cpp deleted file mode 100644 index f73838dbc5..0000000000 --- a/libs/vr/libgvr/dummy_gvr_ext.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include <log/log.h> -#include <vr/gvr/capi/include/gvr.h> -#include <vr/gvr/capi/include/gvr_ext.h> -#include <vr/gvr/capi/include/gvr_types.h> - -gvr_frame_schedule* gvr_frame_schedule_create() { return NULL; } - -void gvr_frame_schedule_destroy(gvr_frame_schedule** /* schedule */) {} - -uint32_t gvr_frame_schedule_get_vsync_count( - gvr_frame_schedule* /* schedule */) { - return 0; -} - -gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr, - uint32_t /* vsync_count */) { - LOG_ALWAYS_FATAL("gvr_get_6dof_head_pose_in_start_space is not implemented. " - "Use gvr_get_head_space_from_start_space_pose instead."); - return gvr_mat4f({{{1.0f, 0.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 1.0f}}}); -} - -void gvr_wait_next_frame(gvr_swap_chain* /* swap_chain */, - int64_t /* sched_offset_nanos */, - gvr_frame_schedule* /* out_next_frame_schedule */) { - LOG_ALWAYS_FATAL("gvr_wait_next_frame is not implemented."); -} diff --git a/libs/vr/libgvr/exported_apis.lds b/libs/vr/libgvr/exported_apis.lds deleted file mode 100644 index 2d19303c68..0000000000 --- a/libs/vr/libgvr/exported_apis.lds +++ /dev/null @@ -1,16 +0,0 @@ -{ - global: - # Export GVR APIs, both public and private. - gvr_*; - - # Whitelist of DVR APIs required by VrCore for Ambrosia controller support. - dvrPoseCreate; - dvrPoseDestroy; - dvrPoseGet; - dvrPoseGetController; - dvrPoseGetVsyncCount; - - local: - # Hide everything else. - *; -}; diff --git a/libs/vr/libgvr/include/private/dvr/internal_types.h b/libs/vr/libgvr/include/private/dvr/internal_types.h deleted file mode 100644 index dafdb73a6f..0000000000 --- a/libs/vr/libgvr/include/private/dvr/internal_types.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef ANDROID_DVR_INTERNAL_TYPES_H_ -#define ANDROID_DVR_INTERNAL_TYPES_H_ - -#include <GLES2/gl2.h> -#include <atomic> -#include <memory> -#include <vector> -#include <unordered_map> - -#include <dvr/graphics.h> -#include <dvr/pose_client.h> -#include <gui/Surface.h> -#include <private/dvr/buffer_hub_queue_core.h> -#include <private/dvr/display_client.h> -#include <vr/gvr/capi/include/gvr.h> -#include <vr/gvr/capi/include/gvr_types.h> -#include <vr/gvr/capi/src/gvr_types_experimental.h> - -typedef struct gvr_user_prefs_ { -} gvr_user_prefs; - -typedef struct gvr_context_ { - int32_t last_error_; - JNIEnv* jni_env_; - DvrPose* pose_client_; - std::unique_ptr<android::dvr::DisplayClient> display_client_; - android::dvr::SystemDisplayMetrics display_metrics_; - gvr_mat4f left_eye_viewport_transform_; - gvr_mat4f right_eye_viewport_transform_; - gvr_mat4f next_frame_6dof_pose_; - gvr_mat4f next_frame_controller_pose_[2]; - gvr_user_prefs user_prefs_; - bool force_6dof_; - std::vector<gvr_swap_chain*> swap_chains_; - - gvr_context_() : - last_error_(GVR_ERROR_NONE), - jni_env_(nullptr), - pose_client_(nullptr), - force_6dof_(false) {} - - ~gvr_context_(); -} gvr_context; - -typedef struct gvr_buffer_spec_ { - gvr_sizei size; - int32_t msaa_samples; - int32_t color_format; - int32_t depth_stencil_format; - bool blur_behind; - bool initially_visible; - int z_order; - - // The default values are configured to match SVR defaults - gvr_buffer_spec_() - : size{0, 0}, - msaa_samples(0), - color_format(GVR_COLOR_FORMAT_RGBA_8888), - depth_stencil_format(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16), - blur_behind(true), - initially_visible(true), - z_order(0) {} -} gvr_buffer_spec; - -// This isn't a public gvr type -struct gvr_buffer { - gvr_buffer_spec spec; - GLuint frame_buffer; - GLuint color_render_buffer; - GLuint depth_stencil_render_buffer; - - // requested_size is used for resizing. It will be {-1, -1} when no resize is - // requested. Any other value indicates the app changed the size. - gvr_sizei requested_size; - - gvr_buffer(); - // If creation fails frame_buffer will be 0 - gvr_buffer(gvr_context* gvr, const gvr_buffer_spec& spec, - GLuint texture_id, GLenum texture_target); - ~gvr_buffer(); - - gvr_buffer(gvr_buffer&& other); - gvr_buffer& operator=(gvr_buffer&& other); - gvr_buffer(const gvr_buffer& other) = delete; - gvr_buffer& operator=(const gvr_buffer& other) = delete; - - // Set default values. Doesn't free GL resources first. - void SetDefaults(); - - // Frees all GL resources associated with the buffer - void FreeGl(); -}; - -typedef struct gvr_swap_chain_ { - gvr_context* context; - DvrGraphicsContext* graphics_context_; - std::vector<gvr_buffer> buffers_; - bool frame_acquired_; - bool wait_next_frame_called_by_app_; - std::atomic<int32_t> next_external_surface_id_; - std::unordered_map<int32_t, gvr_external_surface*> external_surfaces_; - - explicit gvr_swap_chain_(gvr_context* context) - : context(context), - graphics_context_(nullptr), - frame_acquired_(false), - wait_next_frame_called_by_app_(false), - next_external_surface_id_(0) {} - ~gvr_swap_chain_(); -} gvr_swap_chain; - -typedef struct gvr_buffer_viewport_ { - int32_t buffer_index; - gvr_rectf uv; - gvr_mat4f transform; - int32_t eye; - int32_t external_surface_id; - gvr_reprojection reprojection; - - gvr_buffer_viewport_() - : buffer_index(0), - uv{0, 0, 0, 0}, - transform{{{1.f, 0.f, 0.f, 0.f}, - {0.f, 1.f, 0.f, 0.f}, - {0.f, 0.f, 1.f, 0.f}, - {0.f, 0.f, 0.f, 1.f}}}, - eye(0), - external_surface_id(-1), - reprojection(GVR_REPROJECTION_FULL) {} - - gvr_buffer_viewport_(int32_t /* buffer_index */, gvr_rectf uv, - const gvr_mat4f& transform, int32_t eye, - int32_t external_surface_id, - gvr_reprojection reprojection) - : buffer_index(0), - uv(uv), - transform(transform), - eye(eye), - external_surface_id(external_surface_id), - reprojection(reprojection) {} - - bool operator==(const gvr_buffer_viewport_& other) const; - - bool operator!=(const gvr_buffer_viewport_& other) const { - return !operator==(other); - } -} gvr_buffer_viewport; - -typedef struct gvr_buffer_viewport_list_ { - std::vector<gvr_buffer_viewport> viewports; -} gvr_buffer_viewport_list; - -typedef struct gvr_frame_schedule_ { - uint32_t vsync_count; - gvr_clock_time_point scheduled_finish; - - gvr_frame_schedule_() : vsync_count(0) { - scheduled_finish.monotonic_system_time_nanos = 0; - } -} gvr_frame_schedule; - -typedef struct gvr_display_synchronizer_ {} gvr_display_synchronizer; - -typedef struct gvr_external_surface_ { - int32_t id; - gvr_swap_chain* swap_chain; - DvrVideoMeshSurface* video_surface; -} gvr_external_surface; - -#endif // ANDROID_DVR_INTERNAL_TYPES_H_ diff --git a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h b/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h deleted file mode 100644 index 8af434f657..0000000000 --- a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright 2016 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef VR_GVR_CAPI_INCLUDE_GVR_EXT_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_EXT_H_ - -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/// Constants that represent GVR error codes. -typedef enum { - // TODO(steventhomas): All errors should be switched to something more - // meaningful and this should eventually go away. - GVR_ERROR_INTERNAL = 9000, -} gvr_error_ext; - -typedef struct gvr_frame_schedule_ gvr_frame_schedule; - -gvr_frame_schedule* gvr_frame_schedule_create(); - -void gvr_frame_schedule_destroy(gvr_frame_schedule** schedule); - -uint32_t gvr_frame_schedule_get_vsync_count(gvr_frame_schedule* schedule); - -gvr_clock_time_point gvr_frame_schedule_get_scheduled_finish( - gvr_frame_schedule* schedule); - -/// Sleep until it's time to render the next frame. -// |start_delay_ns| adjusts how long this function blocks the app from starting -// its next frame. If |start_delay_ns| is 0, the function waits until the -// scheduled frame finish time for the current frame, which gives the app one -// full vsync period to render the next frame. If the app needs less than a full -// vysnc period to render the frame, pass in a non-zero |start_delay_ns| to -// delay the start of frame rendering further. For example, if the vsync period -// is 11.1ms and the app takes 6ms to render a frame, consider setting this to -// 5ms (note that the value is in nanoseconds, so 5,000,000ns) so that the app -// finishes the frame closer to the scheduled frame finish time. Delaying the -// start of rendering allows the app to use a more up-to-date pose for -// rendering. -// |start_delay_ns| must be a positive value or 0. If you're unsure what to set -// for |start_delay_ns|, use 0. -/// |out_next_frame_schedule| is an output parameter that will contain the -/// schedule for the next frame. It can be null. -void gvr_wait_next_frame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos, - gvr_frame_schedule* out_next_frame_schedule); - -gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr, - uint32_t vsync_count); - -gvr_mat4f gvr_get_head_space_from_start_space_pose( - gvr_context* gvr, const gvr_clock_time_point time); - -gvr_mat4f gvr_get_start_space_from_controller_space_pose( - gvr_context* gvr, int controller_id, const gvr_clock_time_point time); - -#ifdef __cplusplus -} // extern "C" -#endif - -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) -#include <utility> - -namespace gvr { - -/// Convenience C++ wrapper for gvr_frame_schedule. Frees the underlying -/// gvr_frame_schedule on destruction. -class FrameSchedule { - public: - FrameSchedule() { schedule_ = gvr_frame_schedule_create(); } - - ~FrameSchedule() { - if (schedule_) - gvr_frame_schedule_destroy(&schedule_); - } - - FrameSchedule(FrameSchedule&& other) { - std::swap(schedule_, other.schedule_); - } - - FrameSchedule& operator=(FrameSchedule&& other) { - std::swap(schedule_, other.schedule_); - return *this; - } - - gvr_frame_schedule* cobj() { return schedule_; } - const gvr_frame_schedule* cobj() const { return schedule_; } - - uint32_t GetVsyncCount() const { - return gvr_frame_schedule_get_vsync_count(schedule_); - } - - gvr_clock_time_point GetScheduledFinish() const { - return gvr_frame_schedule_get_scheduled_finish(schedule_); - } - - private: - gvr_frame_schedule* schedule_; -}; - -} // namespace gvr -#endif // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#endif // VR_GVR_CAPI_INCLUDE_GVR_EXT_H_ diff --git a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h b/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h deleted file mode 100644 index 1fae61175d..0000000000 --- a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_ - -#include <private/dvr/eigen.h> -#include <private/dvr/numeric.h> -#include <private/dvr/types.h> -#include <vr/gvr/capi/include/gvr_types.h> - -namespace android { -namespace dvr { - -inline gvr_rectf FovRadiansToDegrees(const gvr_rectf& fov) { - return gvr_rectf{ToDeg(fov.left), ToDeg(fov.right), ToDeg(fov.bottom), - ToDeg(fov.top)}; -} - -inline gvr_rectf FovDegreesToRadians(const gvr_rectf& fov) { - return gvr_rectf{ToRad(fov.left), ToRad(fov.right), ToRad(fov.bottom), - ToRad(fov.top)}; -} - -inline FieldOfView GvrToDvrFov(const gvr_rectf& fov) { - gvr_rectf fov_rad = FovDegreesToRadians(fov); - return FieldOfView(fov_rad.left, fov_rad.right, fov_rad.bottom, fov_rad.top); -} - -inline gvr_rectf DvrToGvrFov(const FieldOfView& fov) { - return FovRadiansToDegrees( - gvr_rectf{fov.GetLeft(), fov.GetRight(), fov.GetBottom(), fov.GetTop()}); -} - -inline gvr_mat4f GvrIdentityMatrix() { - gvr_mat4f identity; - memset(&identity.m, 0, sizeof(identity.m)); - for (int i = 0; i < 4; i++) - identity.m[i][i] = 1; - return identity; -} - -inline gvr_mat4f GvrTranslationMatrix(float x, float y, float z) { - gvr_mat4f trans = GvrIdentityMatrix(); - trans.m[0][3] = x; - trans.m[1][3] = y; - trans.m[2][3] = z; - return trans; -} - -inline gvr_mat4f EigenToGvrMatrix(const mat4& m) { - gvr_mat4f ret; - for (int i = 0; i < 4; ++i) - for (int j = 0; j < 4; ++j) - ret.m[i][j] = m(i, j); - return ret; -} - -inline mat4 GvrToEigenMatrix(const gvr::Mat4f& m) { - mat4 ret; - for (int i = 0; i < 4; ++i) - for (int j = 0; j < 4; ++j) - ret(i, j) = m.m[i][j]; - return ret; -} - -inline quat GvrToEigenRotation(const gvr_mat4f& m) { - mat3 ret; - for (int r = 0; r < 3; ++r) - for (int c = 0; c < 3; ++c) - ret(r, c) = m.m[r][c]; - return quat(ret.matrix()); -} - -inline vec3 GvrToEigenTranslation(const gvr_mat4f& m) { - return vec3(m.m[0][3], m.m[1][3], m.m[2][3]); -} - -// Converts a DVR pose to 6DOF head transform as a GVR matrix. -inline gvr_mat4f PosefToGvrMatrix(const Posef& pose) { - return EigenToGvrMatrix(pose.GetObjectFromReferenceMatrix()); -} - -// Converts a DVR pose to 3DOF head transform as a GVR matrix by stripping out -// position translation. -inline gvr_mat4f PosefTo3DofGvrMatrix(const Posef& pose) { - gvr_mat4f ret = PosefToGvrMatrix(pose); - ret.m[0][3] = 0; - ret.m[1][3] = 0; - ret.m[2][3] = 0; - return ret; -} - -// Converts a GVR matrix to a DVR pose. -inline Posef GvrMatrixToPosef(const gvr_mat4f& m) { - return Posef(GvrToEigenRotation(m), GvrToEigenTranslation(m)).Inverse(); -} - -// Calculates an transform with only the yaw and position components of |pose|. -// The inverse of this matrix cancels yaw and position without affecting roll or -// pitch. -inline mat4 CalculateRecenterTransform(const mat4& pose) { - const vec4 z_axis = pose * vec4::UnitZ(); - const float yaw = std::atan2(z_axis[0], z_axis[2]); - const vec3 position = pose.translation(); - return mat4(Eigen::AngleAxis<float>(yaw, vec3::UnitY())).translate(position); -} - -// Calculates a transform that negates the position component of |pose| and -// offsets the pose by |position|. The inverse of this matrix cancels the -// position component of pose and translates by |position| without affecting -// orientation. -inline mat4 CalculateOffsetTransform(const mat4& pose, const vec3& position) { - // Transform the origin by the pose matrix to produce the offset that cancels - // only the position of the pose. - // -1 T - // [ R | t ] [ 0 ] = -R * t - // [ 0 1 ] [ 1 ] - const vec3 position_offset = (pose.inverse() * vec4(0, 0, 0, 1)).head<3>(); - return mat4(mat4::Identity()).translate(position - position_offset); -} - -} // namespace dvr -} // namespace android - -#endif // VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_ diff --git a/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java b/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java deleted file mode 100644 index 381175c047..0000000000 --- a/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.google.vr.gvr.platform; - -import android.os.SystemProperties; - -/** - * Auxiliary class to load the system implementation of the GVR API. - * @hide - */ -public class Loader { - - private static final String VR_MODE_BOOT = "ro.boot.vr"; - - /** - * Opens a shared library containing the system implementation for the GVR API and returns the - * handle to it. - * - * @return A Long object describing the handle returned by dlopen. - */ - public static Long loadLibrary() { - // Note: caller verifications cannot be safely done here. Any app can find and use this API. - // Any sensitive functions must have appropriate checks on the service side. - - // Load a thin JNI library that runs dlopen on request. - System.loadLibrary("gvr_system_loader"); - - // Performs dlopen on the library and returns the handle. - return nativeLoadLibrary("libgvr_system.so"); - } - - /** - * Returns true if this device boots directly in VR mode. - */ - public static boolean getVrBoot() { - return SystemProperties.getBoolean(VR_MODE_BOOT, false); - } - - private static native long nativeLoadLibrary(String library); -} diff --git a/libs/vr/libgvr/library_loader.cpp b/libs/vr/libgvr/library_loader.cpp deleted file mode 100644 index 3cdc7d6d50..0000000000 --- a/libs/vr/libgvr/library_loader.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include <dlfcn.h> -#include <jni.h> - -#include <string> - -extern "C" { - -JNIEXPORT jlong JNICALL -Java_com_google_vr_gvr_platform_Loader_nativeLoadLibrary( - JNIEnv* env, jclass, jstring java_library) { - if (!java_library) - return 0; - - // Convert the Java String object to a C++ null-terminated string. - const char* data = env->GetStringUTFChars(java_library, NULL); - size_t size = env->GetStringUTFLength(java_library); - std::string library(data, size); - env->ReleaseStringUTFChars(java_library, data); - - // Return the handle to the requested library. - return reinterpret_cast<jlong>( - dlopen(library.c_str(), RTLD_NOW | RTLD_LOCAL)); -} - -} // extern "C" diff --git a/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh b/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh deleted file mode 100755 index 8e6ca2d22d..0000000000 --- a/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash -# Build and copy libgvr from Google3. Make sure that your local Google3 client -# is up-to-date by running `p4 sync` before executing this script. -# -# Usage: -# build_gvr_prebuilts.sh --google3_dir=<path_google3_client_root> - -source gbash.sh || exit - -DEFINE_string --required "google3_dir" "" \ - "Path to the root directory of Google3 client" - -BLAZE_COMMON_OPTS=( - --compilation_mode=opt - --copt=-fdata-sections - --copt=-ffunction-sections - --define='prod=1' - --define='enable_experimental_sdk=1' - --linkopt=-Wl,--gc-sections -) - -function copy_file() { - cp -v "${1}" ${CURRENT_DIR}/"${2}" -} - -function copy_gvr_headers() { - echo "Copy GVR headers ..." - - GVR_HEADER_DIR="include/vr/gvr/capi/include" - GVR_SOURCE_DIR="include/vr/gvr/capi/src" - - # GVR public headers - copy_file "vr/gvr/capi/include/gvr.h" ${GVR_HEADER_DIR} - copy_file "vr/gvr/capi/include/gvr_audio.h" ${GVR_HEADER_DIR} - copy_file "vr/gvr/capi/include/gvr_controller.h" ${GVR_HEADER_DIR} - copy_file "vr/gvr/capi/include/gvr_types.h" ${GVR_HEADER_DIR} - - # GVR private and experimental headers - copy_file "vr/gvr/capi/src/gvr_experimental.h" ${GVR_SOURCE_DIR} - copy_file "vr/gvr/capi/src/gvr_private.h" ${GVR_SOURCE_DIR} - copy_file "vr/gvr/capi/src/gvr_types_experimental.h" ${GVR_SOURCE_DIR} -} - -function build_gvr_libs() { - echo "Build GVR libraries ..." - - blaze build \ - //java/com/google/vr/sdk/release:common_library.aar \ - //vr/gvr/platform:libgvr.so \ - //vr/gvr/platform:libgvr_audio.so \ - ${BLAZE_COMMON_OPTS[@]} --config=android_arm --symlink_prefix blaze-arm- - - blaze build \ - //vr/gvr/platform:libgvr.so \ - //vr/gvr/platform:libgvr_audio.so \ - ${BLAZE_COMMON_OPTS[@]} --config=android_arm64 --symlink_prefix blaze-arm64- - - blaze build \ - //java/com/google/vr/sdk/release:common_library.aar \ - //vr/gvr/platform:libgvr.so \ - //vr/gvr/platform:libgvr_audio.so \ - ${BLAZE_COMMON_OPTS[@]} --config=android_x86 --symlink_prefix blaze-x86- - - blaze build \ - //vr/gvr/platform:libgvr.so \ - //vr/gvr/platform:libgvr_audio.so \ - ${BLAZE_COMMON_OPTS[@]} --config=android_x86_64 --symlink_prefix blaze-x86_64- - - copy_file "blaze-arm-genfiles/java/com/google/vr/sdk/release/common_library.aar" \ - "lib/common_library.aar" - copy_file "blaze-arm-genfiles/vr/gvr/platform/libgvr.so" "lib/android_arm" - copy_file "blaze-arm-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_arm" - copy_file "blaze-arm64-genfiles/vr/gvr/platform/libgvr.so" "lib/android_arm64" - copy_file "blaze-arm64-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_arm64" - copy_file "blaze-x86-genfiles/vr/gvr/platform/libgvr.so" "lib/android_x86" - copy_file "blaze-x86-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_x86" - copy_file "blaze-x86_64-genfiles/vr/gvr/platform/libgvr.so" "lib/android_x86_64" - copy_file "blaze-x86_64-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_x86_64" -} - -function main() { - set -ex - - CURRENT_DIR=$(pwd) - GOOGLE3_DIR=${FLAGS_google3_dir} - - cd ${GOOGLE3_DIR} - copy_gvr_headers - build_gvr_libs -} - -gbash::init_google "$@" -main "$@" diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h deleted file mode 100644 index c459ecac7a..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h +++ /dev/null @@ -1,1751 +0,0 @@ -/* Copyright 2016 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef VR_GVR_CAPI_INCLUDE_GVR_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_H_ - -#ifdef __ANDROID__ -#include <jni.h> -#endif - -#include <stdint.h> -#include <stdlib.h> - -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) -#include <array> -#include <memory> -#include <vector> -#endif - -#include "vr/gvr/capi/include/gvr_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// @defgroup base Google VR Base C API -/// @brief This is the Google VR C API. It supports clients writing VR -/// experiences for head mounted displays that consist of a mobile phone and a -/// VR viewer. -/// -/// Example API usage: -/// -/// #ifdef __ANDROID__ -/// // On Android, the gvr_context should almost always be obtained from -/// // the Java GvrLayout object via -/// // GvrLayout.getGvrApi().getNativeGvrContext(). -/// gvr_context* gvr = ...; -/// #else -/// gvr_context* gvr = gvr_create(); -/// #endif -/// -/// gvr_initialize_gl(gvr); -/// -/// gvr_buffer_viewport_list* viewport_list = -/// gvr_buffer_viewport_list_create(gvr); -/// gvr_get_recommended_buffer_viewports(gvr, viewport_list); -/// gvr_buffer_viewport* left_eye_vp = gvr_buffer_viewport_create(gvr); -/// gvr_buffer_viewport* right_eye_vp = gvr_buffer_viewport_create(gvr); -/// gvr_buffer_viewport_list_get_item(viewport_list, 0, left_eye_vp); -/// gvr_buffer_viewport_list_get_item(viewport_list, 1, right_eye_vp); -/// -/// while (client_app_should_render) { -/// // A client app should be ready for the render target size to change -/// // whenever a new QR code is scanned, or a new viewer is paired. -/// gvr_sizei render_target_size = -/// gvr_get_maximum_effective_render_target_size(gvr); -/// // The maximum effective render target size can be very large, most -/// // applications need to scale down to compensate. -/// render_target_size.width /= 2; -/// render_target_size.height /= 2; -/// gvr_swap_chain_resize_buffer(swap_chain, 0, render_target_size); -/// -/// // This function will depend on your render loop's implementation. -/// gvr_clock_time_point next_vsync = AppGetNextVsyncTime(); -/// -/// const gvr_mat4f head_view = -/// gvr_get_head_space_from_start_space_rotation(gvr, next_vsync); -/// const gvr_mat4f left_eye_view = MatrixMultiply( -/// gvr_get_eye_from_head_matrix(gvr, GVR_LEFT_EYE), head_view); -/// const gvr::Mat4f right_eye_view = MatrixMultiply( -/// gvr_get_eye_from_head_matrix(gvr, GVR_RIGHT_EYE), head_view); -/// -/// // Insert client rendering code here. -/// -/// AppSetRenderTarget(offscreen_texture_id); -/// -/// AppDoSomeRenderingForEye( -/// gvr_buffer_viewport_get_source_uv(left_eye_view), -/// left_eye_matrix); -/// AppDoSomeRenderingForEye( -/// gvr_buffer_viewport_get_source_uv(right_eye_view), -/// right_eye_matrix); -/// AppSetRenderTarget(primary_display); -/// -/// gvr_frame_submit(&frame, viewport_list, head_matrix); -/// } -/// -/// // Cleanup memory. -/// gvr_buffer_viewport_list_destroy(&viewport_list); -/// gvr_buffer_viewport_destroy(&left_eye_vp); -/// gvr_buffer_viewport_destroy(&right_eye_vp); -/// -/// #ifdef __ANDROID__ -/// // On Android, The Java GvrLayout owns the gvr_context. -/// #else -/// gvr_destroy(gvr); -/// #endif -/// -/// Head tracking is enabled by default, and will begin as soon as the -/// gvr_context is created. The client should call gvr_pause_tracking() and -/// gvr_resume_tracking() when the app is paused and resumed, respectively. -/// -/// Note: Unless otherwise noted, the functions in this API may not be -/// thread-safe with respect to the gvr_context, and it is up the caller to use -/// the API in a thread-safe manner. -/// -/// @{ - -/// Creates a new gvr instance. -/// -/// The instance must remain valid as long as any GVR object is in use. When -/// the application no longer needs to use the GVR SDK, call gvr_destroy(). -/// -/// -/// On Android, the gvr_context should *almost always* be obtained from the Java -/// GvrLayout object, rather than explicitly created here. The GvrLayout should -/// live in the app's View hierarchy, and its use is required to ensure -/// consistent behavior across all varieties of GVR-compatible viewers. See -/// the Java GvrLayout and GvrApi documentation for more details. -/// -#ifdef __ANDROID__ -/// @param env The JNIEnv associated with the current thread. -/// @param app_context The Android application context. This must be the -/// application context, NOT an Activity context (Note: from any Android -/// Activity in your app, you can call getApplicationContext() to -/// retrieve the application context). -/// @param class_loader The class loader to use when loading Java classes. -/// This must be your app's main class loader (usually accessible through -/// activity.getClassLoader() on any of your Activities). -/// -/// @return Pointer to the created gvr instance, NULL on failure. -gvr_context* gvr_create(JNIEnv* env, jobject app_context, jobject class_loader); -#else -/// @return Pointer to the created gvr instance, NULL on failure. -gvr_context* gvr_create(); -#endif // #ifdef __ANDROID__ - -/// Gets the current GVR runtime version. -/// -/// Note: This runtime version may differ from the version against which the -/// client app is compiled, as defined by the semantic version components in -/// gvr_version.h. -/// -/// @return The version as a gvr_version. -gvr_version gvr_get_version(); - -/// Gets a string representation of the current GVR runtime version. This is of -/// the form "MAJOR.MINOR.PATCH". -/// -/// Note: This runtime version may differ from the version against which the -/// client app is compiled, as defined in gvr_version.h by -/// GVR_SDK_VERSION_STRING. -/// -/// @return The version as a static char pointer. -const char* gvr_get_version_string(); - -/// Gets the current GVR error code, or GVR_ERROR_NONE if there is no error. -/// This function doesn't clear the error code; see gvr_clear_error(). -/// -/// @param gvr Pointer to the gvr instance. -/// @return The current gvr_error code, or GVR_ERROR_NONE if no error has -/// occurred. -int32_t gvr_get_error(gvr_context* gvr); - -/// Clears the current GVR error code, and returns the error code that was -/// cleared. -/// -/// @param gvr Pointer to the gvr instance. -/// @return The gvr_error code that was cleared by this function, or -/// GVR_ERROR_NONE if no error has occurred. -int32_t gvr_clear_error(gvr_context* gvr); - -/// Gets a human-readable string representing the given error code. -/// -/// @param error_code The gvr_error code. -/// @return A human-readable string representing the error code. -const char* gvr_get_error_string(int32_t error_code); - -/// Returns an opaque struct containing information about user preferences. -/// -/// The returned struct will remain valid as long as the context is valid. -/// The returned struct may be updated when the user changes their preferences, -/// so this function only needs to be called once, and calling it multiple -/// times will return the same object each time. -/// -/// @param gvr Pointer to the gvr instance. -/// @return An opaque struct containing information about user preferences. -const gvr_user_prefs* gvr_get_user_prefs(gvr_context* gvr); - -/// Returns the controller handedness of the given gvr_user_prefs struct. -/// -/// @param user_prefs Pointer to the gvr_user_prefs object returned by -/// gvr_get_user_prefs. -/// @return Either GVR_CONTROLLER_RIGHT_HANDED or GVR_CONTROLLER_LEFT_HANDED -/// depending on which hand the user holds the controller in. -int32_t gvr_user_prefs_get_controller_handedness( - const gvr_user_prefs* user_prefs); - -/// Destroys a gvr_context instance. The parameter will be nulled by this -/// operation. Once this function is called, the behavior of any subsequent -/// call to a GVR SDK function that references objects created from this -/// context is undefined. -/// -/// @param gvr Pointer to a pointer to the gvr instance to be destroyed and -/// nulled. -void gvr_destroy(gvr_context** gvr); - -/// Initializes necessary GL-related objects and uses the current thread and -/// GL context for rendering. Please make sure that a valid GL context is -/// available when this function is called. This should never be called more -/// than once on the same GL context (doing so would cause resource leaks). -/// -/// @param gvr Pointer to the gvr instance to be initialized. -void gvr_initialize_gl(gvr_context* gvr); - -/// Gets whether asynchronous reprojection is currently enabled. -/// -/// If enabled, frames will be collected by the rendering system and -/// asynchronously re-projected in sync with the scanout of the display. This -/// feature may not be available on every platform, and requires a -/// high-priority render thread with special extensions to function properly. -/// -/// Note: On Android, this feature can be enabled solely via the GvrLayout Java -/// instance which (indirectly) owns this gvr_context. The corresponding -/// method call is GvrLayout.setAsyncReprojectionEnabled(). -/// -/// Note: Because of the above requirements, asynchronous reprojection is only -/// currently available on Daydream-ready Android devices. This function will -/// always return false on other devices. -/// -/// @param gvr Pointer to the gvr instance. -/// @return Whether async reprojection is enabled. Defaults to false. -bool gvr_get_async_reprojection_enabled(const gvr_context* gvr); - -/// Gets the recommended buffer viewport configuration, populating a previously -/// allocated gvr_buffer_viewport_list object. The updated values include the -/// per-eye recommended viewport and field of view for the target. -/// -/// When the recommended viewports are used for distortion rendering, this -/// method should always be called after calling refresh_viewer_profile(). That -/// will ensure that the populated viewports reflect the currently paired -/// viewer. -/// -/// @param gvr Pointer to the gvr instance from which to get the viewports. -/// @param viewport_list Pointer to a previously allocated viewport list. This -/// will be populated with the recommended buffer viewports and resized if -/// necessary. -void gvr_get_recommended_buffer_viewports( - const gvr_context* gvr, gvr_buffer_viewport_list* viewport_list); - -/// Gets the screen (non-distorted) buffer viewport configuration, populating a -/// previously allocated gvr_buffer_viewport_list object. The updated values -/// include the per-eye recommended viewport and field of view for the target. -/// -/// @param gvr Pointer to the gvr instance from which to get the viewports. -/// @param viewport_list Pointer to a previously allocated viewport list. This -/// will be populated with the screen buffer viewports and resized if -/// necessary. -void gvr_get_screen_buffer_viewports(const gvr_context* gvr, - gvr_buffer_viewport_list* viewport_list); - -/// Returns the maximum effective size for the client's render target, given the -/// parameters of the head mounted device selected. At this resolution, we have -/// a 1:1 ratio between source pixels and screen pixels in the most magnified -/// region of the screen. Applications should rarely, if ever, need to render -/// to a larger target, as it will simply result in sampling artifacts. -/// -/// Note that this is probably too large for most applications to use as a -/// render target size. Applications should scale this value to be appropriate -/// to their graphical load. -/// -/// @param gvr Pointer to the gvr instance from which to get the size. -/// -/// @return Maximum effective size for the target render target. -gvr_sizei gvr_get_maximum_effective_render_target_size(const gvr_context* gvr); - -/// Returns a non-distorted size for the screen, given the parameters -/// of the phone and/or the head mounted device selected. -/// -/// @param gvr Pointer to the gvr instance from which to get the size. -/// -/// @return Screen (non-distorted) size for the render target. -gvr_sizei gvr_get_screen_target_size(const gvr_context* gvr); - -// Sets the size of the underlying render surface. -// -// By default, it is assumed that the display size matches the surface -// size. If that is the case for the client app, this method need never be -// called. However, in certain cases (e.g., hardware scaling), this will not -// always hold, in which case the distortion pass must be informed of the -// custom surface size. -// -// Note that the caller is responsible for resizing any BufferSpec objects -// created before this function is called. Otherwise there will be rendering -// artifacts, such as edges appearing pixelated. This function will change the -// result of get_maximum_effective_render_target_size(), so that function can be -// used to compute the appropriate size for buffers. -// -// @param gvr Pointer to the gvr_context instance. -// @param surface_size_pixels The size in pixels of the display surface. If -// non-empty, this will be used in conjunction with the current display to -// perform properly scaled distortion. If empty, it is assumed that the -// rendering surface dimensions match that of the active display. -void gvr_set_surface_size(gvr_context* gvr, gvr_sizei surface_size_pixels); - -/// Performs postprocessing, including lens distortion, on the contents of the -/// passed texture and shows the result on the screen. Lens distortion is -/// determined by the parameters of the viewer encoded in its QR code. The -/// passed texture is not modified. -/// -/// If the application does not call gvr_initialize_gl() before calling this -/// function, the results are undefined. -/// -/// @deprecated This function exists only to support legacy rendering pathways -/// for Cardboard devices. It is incompatible with the low-latency -/// experiences supported by async reprojection. Use the swap chain API -/// instead. -/// -/// @param gvr Pointer to the gvr instance which will do the distortion. -/// @param texture_id The OpenGL ID of the texture that contains the next frame -/// to be displayed. -/// @param viewport_list Rendering parameters. -/// @param head_space_from_start_space This parameter is ignored. -/// @param target_presentation_time This parameter is ignored. -void gvr_distort_to_screen(gvr_context* gvr, int32_t texture_id, - const gvr_buffer_viewport_list* viewport_list, - gvr_mat4f head_space_from_start_space, - gvr_clock_time_point target_presentation_time); - -/// Queries whether a particular GVR feature is supported by the underlying -/// platform. -/// -/// @param gvr The context to query against. -/// @param feature The gvr_feature type being queried. -/// @return true if feature is supported, false otherwise. -bool gvr_is_feature_supported(const gvr_context* gvr, int32_t feature); - -/// @} - -///////////////////////////////////////////////////////////////////////////// -// Viewports and viewport lists -///////////////////////////////////////////////////////////////////////////// -/// @defgroup viewport Viewports and viewport lists -/// @brief Objects to define the mapping between the application's rendering -/// output and the user's field of view. -/// @{ - -/// Creates a gvr_buffer_viewport instance. -gvr_buffer_viewport* gvr_buffer_viewport_create(gvr_context* gvr); - -/// Frees a gvr_buffer_viewport instance and clears the pointer. -void gvr_buffer_viewport_destroy(gvr_buffer_viewport** viewport); - -/// Gets the UV coordinates specifying where the output buffer is sampled. -/// -/// @param viewport The buffer viewport. -/// @return UV coordinates as a rectangle. -gvr_rectf gvr_buffer_viewport_get_source_uv( - const gvr_buffer_viewport* viewport); - -/// Sets the UV coordinates specifying where the output buffer should be -/// sampled when compositing the final distorted image. -/// -/// @param viewport The buffer viewport. -/// @param uv The new UV coordinates for sampling. The coordinates must be -/// valid, that is, left <= right and bottom <= top. Otherwise an empty -/// source region is set, which will result in no output for this viewport. -void gvr_buffer_viewport_set_source_uv(gvr_buffer_viewport* viewport, - gvr_rectf uv); - -/// Retrieves the field of view for the referenced buffer region. -/// -/// This is a helper that converts the stored projection matrix to a field of -/// view. Note that if the previously set projection matrix cannot be expressed -/// as a view frustum aligned with the eye's optical axis, the result will be -/// incorrect. -/// -/// @param viewport The buffer viewport. -/// @return The field of view of the rendered image, in degrees. -gvr_rectf gvr_buffer_viewport_get_source_fov( - const gvr_buffer_viewport* viewport); - -/// Sets the field of view for the viewport contents. -/// -/// This is a helper that sets the projection matrix in such a way that the -/// viewport's contents fill the specified FOV around the eye's optical axis. -/// -/// @param viewport The buffer viewport. -/// @param fov The field of view to use when compositing the rendered image, -/// in degrees. -void gvr_buffer_viewport_set_source_fov(gvr_buffer_viewport* viewport, - gvr_rectf fov); - -/// Gets the matrix that positions the viewport in eye space. -/// -/// @param viewport The buffer viewport. -/// @return Matrix that transforms a quad with vertices (-1, -1, 0), (1, -1, 0), -/// (-1, 1, 0), (1, 1, 0) representing the viewport contents to its desired -/// eye space position for the target eye. -gvr_mat4f gvr_buffer_viewport_get_transform( - const gvr_buffer_viewport* viewport); - -/// Sets the matrix that positions the viewport in eye space. -/// -/// @param viewport The buffer viewport. -/// @param transform Matrix that transforms a quad with vertices (-1, -1, 0), -/// (1, -1, 0), (-1, 1, 0), (1, 1, 0) representing the viewport contents to -/// its desired eye space position for the target eye. -void gvr_buffer_viewport_set_transform(gvr_buffer_viewport* viewport, - gvr_mat4f transform); - -/// Gets the target logical eye for the specified viewport. -/// -/// @param viewport The buffer viewport. -/// @return Index of the target logical eye for this viewport. -int32_t gvr_buffer_viewport_get_target_eye(const gvr_buffer_viewport* viewport); - -/// Sets the target logical eye for the specified viewport. -/// -/// @param viewport The buffer viewport. -/// @param index Index of the target logical eye. -void gvr_buffer_viewport_set_target_eye(gvr_buffer_viewport* viewport, - int32_t index); - -/// Gets the index of the source buffer from which the viewport reads its -/// undistorted pixels. -/// -/// @param viewport The buffer viewport. -/// @return Index of the source buffer. This corresponds to the index in the -/// list of buffer specs that was passed to gvr_swap_chain_create(). -int32_t gvr_buffer_viewport_get_source_buffer_index( - const gvr_buffer_viewport* viewport); - -/// Sets the buffer from which the viewport reads its undistorted pixels. -/// -/// To use the contents of the external surface as buffer contents, associate an -/// external surface with the viewport by calling -/// gvr_buffer_viewport_set_external_surface_id(), then call this function and -/// pass GVR_BUFFER_INDEX_EXTERNAL_SURFACE. -/// -/// @param viewport The buffer viewport. -/// @param buffer_index The index of the source buffer. This is either an index -/// in the list of buffer specs that was passed to -/// gvr_swap_chain_create(), or GVR_BUFFER_INDEX_EXTERNAL_SURFACE. -void gvr_buffer_viewport_set_source_buffer_index( - gvr_buffer_viewport* viewport, int32_t buffer_index); - -/// Gets the ID of the externally-managed Surface texture from which this -/// viewport reads undistored pixels. -/// -/// @param viewport The buffer viewport. -/// @return ID of the externally-managed Surface of undistorted pixels. -int32_t gvr_buffer_viewport_get_external_surface_id( - const gvr_buffer_viewport* viewport); - -/// Sets the ID of the externally-managed Surface texture from which this -/// viewport reads. The ID is issued by GvrLayout. -/// -/// @param viewport The buffer viewport. -/// @param external_surface_id The ID of the surface to read from. -void gvr_buffer_viewport_set_external_surface_id( - gvr_buffer_viewport* viewport, int32_t external_surface_id); - -/// Gets the type of reprojection to perform on the specified viewport. -/// -/// @param viewport The buffer viewport. -/// @return Type of reprojection that is applied to the viewport. -int32_t gvr_buffer_viewport_get_reprojection( - const gvr_buffer_viewport* viewport); - -/// Sets the type of reprojection to perform on the specified viewport. -/// Viewports that display world content should use full reprojection. -/// Viewports that display head-locked UI should disable reprojection to avoid -/// excessive judder. The default is to perform full reprojection. -/// -/// @param viewport The buffer viewport. -/// @param reprojection Type of reprojection that will be applied to the passed -/// viewport. -void gvr_buffer_viewport_set_reprojection(gvr_buffer_viewport* viewport, - int32_t reprojection); - -/// Compares two gvr_buffer_viewport instances and returns true if they specify -/// the same view mapping. -/// -/// @param a Instance of a buffer viewport. -/// @param b Another instance of a buffer viewport. -/// @return True if the passed viewports are the same. -bool gvr_buffer_viewport_equal(const gvr_buffer_viewport* a, - const gvr_buffer_viewport* b); - -/// Creates a new, empty list of viewports. The viewport list defines how the -/// application's rendering output should be transformed into the stabilized, -/// lens-distorted image that is sent to the screen. -/// -/// The caller should populate the returned viewport using one of: -/// - gvr_get_recommended_buffer_viewports() -/// - gvr_get_screen_buffer_viewports() -/// - gvr_buffer_viewport_list_set_item() -/// -/// @param gvr Pointer the gvr instance from which to allocate the viewport -/// list. -/// @return Pointer to an allocated gvr_buffer_viewport_list object. The caller -// is responsible for calling gvr_buffer_viewport_list_destroy() on the -/// returned object when it is no longer needed. -gvr_buffer_viewport_list* gvr_buffer_viewport_list_create( - const gvr_context* gvr); - -/// Destroys a gvr_buffer_viewport_list instance. The parameter will be nulled -/// by this operation. -/// -/// @param viewport_list Pointer to a pointer to the viewport list instance to -/// be destroyed and nulled. -void gvr_buffer_viewport_list_destroy(gvr_buffer_viewport_list** viewport_list); - -/// Returns the size of the given viewport list. -/// -/// @param viewport_list Pointer to a viewport list. -/// @return The number of entries in the viewport list. -size_t gvr_buffer_viewport_list_get_size( - const gvr_buffer_viewport_list* viewport_list); - -/// Retrieve a buffer viewport entry from a list. -/// -/// @param viewport_list Pointer to the previously allocated viewport list. -/// @param index Zero-based index of the viewport entry to query. Must be -/// smaller than the list size. -/// @param viewport The buffer viewport structure that will be populated with -/// retrieved data. -void gvr_buffer_viewport_list_get_item( - const gvr_buffer_viewport_list* viewport_list, size_t index, - gvr_buffer_viewport* viewport); - -/// Update an element of the viewport list or append a new one at the end. -/// -/// @param viewport_list Pointer to a previously allocated viewport list. -/// @param index Index of the buffer viewport entry to update. If the -/// `viewport_list` size is equal to the index, a new viewport entry will be -/// added. The `viewport_list` size must *not* be less than the index value. -/// @param viewport A pointer to the buffer viewport object. -void gvr_buffer_viewport_list_set_item(gvr_buffer_viewport_list* viewport_list, - size_t index, - const gvr_buffer_viewport* viewport); - -/// @} - -///////////////////////////////////////////////////////////////////////////// -// Swapchains and frames -///////////////////////////////////////////////////////////////////////////// -/// @defgroup swap_chain Swap chains and frames -/// @brief Functions to create a swap chain, manipulate it and submit frames -/// for lens distortion and presentation on the screen. -/// @{ - -/// Creates a default buffer specification. -gvr_buffer_spec* gvr_buffer_spec_create(gvr_context* gvr); - -/// Destroy the buffer specification and null the pointer. -void gvr_buffer_spec_destroy(gvr_buffer_spec** spec); - -/// Gets the size of the buffer to be created. -/// -/// @param spec Buffer specification. -/// @return Size of the pixel buffer. The default is equal to the recommended -/// render target size at the time when the specification was created. -gvr_sizei gvr_buffer_spec_get_size(const gvr_buffer_spec* spec); - -/// Sets the size of the buffer to be created. -/// -/// @param spec Buffer specification. -/// @param size The size. Width and height must both be greater than zero. -/// Otherwise, the application is aborted. -void gvr_buffer_spec_set_size(gvr_buffer_spec* spec, gvr_sizei size); - -/// Gets the number of samples per pixel in the buffer to be created. -/// -/// @param spec Buffer specification. -/// @return Value >= 1 giving the number of samples. 1 means multisampling is -/// disabled. Negative values and 0 are never returned. -int32_t gvr_buffer_spec_get_samples(const gvr_buffer_spec* spec); - -/// Sets the number of samples per pixel in the buffer to be created. -/// -/// @param spec Buffer specification. -/// @param num_samples The number of samples. Negative values are an error. -/// The values 0 and 1 are treated identically and indicate that -// multisampling should be disabled. -void gvr_buffer_spec_set_samples(gvr_buffer_spec* spec, int32_t num_samples); - -/// Sets the color format for the buffer to be created. Default format is -/// GVR_COLOR_FORMAT_RGBA_8888. -/// -/// @param spec Buffer specification. -/// @param color_format The color format for the buffer. Valid formats are in -/// the gvr_color_format_type enum. -void gvr_buffer_spec_set_color_format(gvr_buffer_spec* spec, - int32_t color_format); - -/// Sets the depth and stencil format for the buffer to be created. Currently, -/// only packed stencil formats are supported. Default format is -/// GVR_DEPTH_STENCIL_FORMAT_DEPTH_16. -/// -/// @param spec Buffer specification. -/// @param depth_stencil_format The depth and stencil format for the buffer. -/// Valid formats are in the gvr_depth_stencil_format_type enum. -void gvr_buffer_spec_set_depth_stencil_format(gvr_buffer_spec* spec, - int32_t depth_stencil_format); - -/// Creates a swap chain from the given buffer specifications. -/// This is a potentially time-consuming operation. All frames within the -/// swapchain will be allocated. Once rendering is stopped, call -/// gvr_swap_chain_destroy() to free GPU resources. The passed gvr_context must -/// not be destroyed until then. -/// -/// Swap chains can have no buffers. This is useful when only displaying -/// external surfaces. When `count` is zero, `buffers` must be null. -/// -/// @param gvr GVR instance for which a swap chain will be created. -/// @param buffers Array of pixel buffer specifications. Each frame in the -/// swap chain will be composed of these buffers. -/// @param count Number of buffer specifications in the array. -/// @return Opaque handle to the newly created swap chain. -gvr_swap_chain* gvr_swap_chain_create(gvr_context* gvr, - const gvr_buffer_spec** buffers, - int32_t count); - -/// Destroys the swap chain and nulls the pointer. -void gvr_swap_chain_destroy(gvr_swap_chain** swap_chain); - -/// Gets the number of buffers in each frame of the swap chain. -int32_t gvr_swap_chain_get_buffer_count(const gvr_swap_chain* swap_chain); - -/// Retrieves the size of the specified pixel buffer. Note that if the buffer -/// was resized while the current frame was acquired, the return value will be -/// different than the value obtained from the equivalent function for the -/// current frame. -/// -/// @param swap_chain The swap chain. -/// @param index Index of the pixel buffer. -/// @return Size of the specified pixel buffer in frames that will be returned -/// from gvr_swap_chain_acquire_frame(). -gvr_sizei gvr_swap_chain_get_buffer_size(gvr_swap_chain* swap_chain, - int32_t index); - -/// Resizes the specified pixel buffer to the given size. The frames are resized -/// when they are unused, so the currently acquired frame will not be resized -/// immediately. -/// -/// @param swap_chain The swap chain. -/// @param index Index of the pixel buffer to resize. -/// @param size New size for the specified pixel buffer. -void gvr_swap_chain_resize_buffer(gvr_swap_chain* swap_chain, int32_t index, - gvr_sizei size); - -/// Acquires a frame from the swap chain for rendering. Buffers that are part of -/// the frame can then be bound with gvr_frame_bind_buffer(). Once the frame -/// is finished and all its constituent buffers are ready, call -/// gvr_frame_submit() to display it while applying lens distortion. -/// -/// @param swap_chain The swap chain. -/// @return Handle to the acquired frame. NULL if the swap chain is invalid, -/// or if acquire has already been called on this swap chain. -gvr_frame* gvr_swap_chain_acquire_frame(gvr_swap_chain* swap_chain); - -/// Binds a pixel buffer that is part of the frame to the OpenGL framebuffer. -/// -/// @param frame Frame handle acquired from the swap chain. -/// @param index Index of the pixel buffer to bind. This corresponds to the -/// index in the buffer spec list that was passed to -/// gvr_swap_chain_create(). -void gvr_frame_bind_buffer(gvr_frame* frame, int32_t index); - -/// Unbinds any buffers bound from this frame and binds the default OpenGL -/// framebuffer. -void gvr_frame_unbind(gvr_frame* frame); - -/// Returns the dimensions of the pixel buffer with the specified index. Note -/// that a frame that was acquired before resizing a swap chain buffer will not -/// be resized until it is submitted to the swap chain. -/// -/// @param frame Frame handle. -/// @param index Index of the pixel buffer to inspect. -/// @return Dimensions of the specified pixel buffer. -gvr_sizei gvr_frame_get_buffer_size(const gvr_frame* frame, int32_t index); - -/// Gets the name (ID) of the framebuffer object associated with the specified -/// buffer. The OpenGL state is not modified. -/// -/// @param frame Frame handle. -/// @param index Index of a pixel buffer. -/// @return OpenGL object name (ID) of a framebuffer object which can be used -/// to render into the buffer. The ID is valid only until the frame is -/// submitted. -int32_t gvr_frame_get_framebuffer_object(const gvr_frame* frame, int32_t index); - -/// Submits the frame for distortion and display on the screen. The passed -/// pointer is nulled to prevent reuse. -/// -/// @param frame The frame to submit. -/// @param list Buffer view configuration to be used for this frame. -/// @param head_space_from_start_space Transform from start space (space with -/// head at the origin at last tracking reset) to head space (space with -/// head at the origin and axes aligned to the view vector). -void gvr_frame_submit(gvr_frame** frame, const gvr_buffer_viewport_list* list, - gvr_mat4f head_space_from_start_space); - -/// Resets the OpenGL framebuffer binding to what it was at the time the -/// passed gvr_context was created. -void gvr_bind_default_framebuffer(gvr_context* gvr); - -/// @} - -///////////////////////////////////////////////////////////////////////////// -// Head tracking -///////////////////////////////////////////////////////////////////////////// -/// @defgroup Headtracking Head tracking -/// @brief Functions for managing head tracking. -/// @{ - -/// Gets the current monotonic system time. -/// -/// @return The current monotonic system time. -gvr_clock_time_point gvr_get_time_point_now(); - -/// Gets the rotation from start space to head space. The head space is a -/// space where the head is at the origin and faces the -Z direction. -/// -/// @param gvr Pointer to the gvr instance from which to get the pose. -/// @param time The time at which to get the head pose. The time should be in -/// the future. If the time is not in the future, it will be clamped to now. -/// @return A matrix representation of the rotation from start space (the space -/// where the head was last reset) to head space (the space with the head -/// at the origin, and the axes aligned to the view vector). -gvr_mat4f gvr_get_head_space_from_start_space_rotation( - const gvr_context* gvr, const gvr_clock_time_point time); - -/// Applies a simple neck model translation based on the rotation of the -/// provided head pose. -/// -/// Note: Neck model application may not be appropriate for all tracking -/// scenarios, e.g., when tracking is non-biological. -/// -/// @param gvr Pointer to the context instance from which the pose was obtained. -/// @param head_space_from_start_space_rotation The head rotation as returned by -/// gvr_get_head_space_from_start_space_rotation(). -/// @param factor A scaling factor for the neck model offset, clamped from 0 to -/// 1. This should be 1 for most scenarios, while 0 will effectively disable -/// neck model application. This value can be animated to smoothly -/// interpolate between alternative (client-defined) neck models. -/// @return The new head pose with the neck model applied. -gvr_mat4f gvr_apply_neck_model(const gvr_context* gvr, - gvr_mat4f head_space_from_start_space_rotation, - float factor); - -/// Pauses head tracking, disables all sensors (to save power). -/// -/// @param gvr Pointer to the gvr instance for which tracking will be paused and -/// sensors disabled. -void gvr_pause_tracking(gvr_context* gvr); - -/// Resumes head tracking, re-enables all sensors. -/// -/// @param gvr Pointer to the gvr instance for which tracking will be resumed. -void gvr_resume_tracking(gvr_context* gvr); - -/// Resets head tracking. -/// -/// This API call is deprecated. Use gvr_recenter_tracking instead, which -/// accomplishes the same effects but avoids the undesirable side-effects of -/// a full reset (temporary loss of tracking quality). -/// -/// Only to be used by Cardboard apps. Daydream apps must not call this. On the -/// Daydream platform, recentering is handled automatically and should never -/// be triggered programatically by applications. Hybrid apps that support both -/// Cardboard and Daydream must only call this function when in Cardboard mode -/// (that is, when the phone is paired with a Cardboard viewer), never in -/// Daydream mode. -/// -/// @param gvr Pointer to the gvr instance for which tracking will be reseted. -/// @deprecated Calls to this method can be safely replaced by calls to -// gvr_recenter_tracking. -void gvr_reset_tracking(gvr_context* gvr); - -/// Recenters the head orientation (resets the yaw to zero, leaving pitch and -/// roll unmodified). -/// -/// Only to be used by Cardboard apps. Daydream apps must not call this. On the -/// Daydream platform, recentering is handled automatically and should never -/// be triggered programatically by applications. Hybrid apps that support both -/// Cardboard and Daydream must only call this function when in Cardboard mode -/// (that is, when the phone is paired with a Cardboard viewer), never in -/// Daydream mode. -/// -/// @param gvr Pointer to the gvr instance for which tracking will be -/// recentered. -void gvr_recenter_tracking(gvr_context* gvr); - -/// @} - - -///////////////////////////////////////////////////////////////////////////// -// Head mounted display. -///////////////////////////////////////////////////////////////////////////// -/// @defgroup HMD Head Mounted Display -/// @brief Functions for managing viewer information. -/// @{ - -/// Sets the default viewer profile specified by viewer_profile_uri. -/// The viewer_profile_uri that is passed in will be ignored if a valid -/// viewer profile has already been stored on the device that the app -/// is running on. -/// -/// Note: This function has the potential of blocking for up to 30 seconds for -/// each redirect if a shortened URI is passed in as argument. It will try to -/// unroll the shortened URI for a maximum number of 5 times if the redirect -/// continues. In that case, it is recommended to create a separate thread to -/// call this function so that other tasks like rendering will not be blocked -/// on this. The blocking can be avoided if a standard URI is passed in. -/// -/// @param gvr Pointer to the gvr instance which to set the profile on. -/// @param viewer_profile_uri A string that contains either the shortened URI or -/// the standard URI representing the viewer profile that the app should be -/// using. If the valid viewer profile can be found on the device, the URI -/// that is passed in will be ignored and nothing will happen. Otherwise, -/// gvr will look for the viewer profile specified by viewer_profile_uri, -/// and it will be stored if found. Also, the values will be applied to gvr. -/// A valid standard URI can be generated from this page: -/// https://www.google.com/get/cardboard/viewerprofilegenerator/ -/// @return True if the viewer profile specified by viewer_profile_uri was -/// successfully stored and applied, false otherwise. -bool gvr_set_default_viewer_profile(gvr_context* gvr, - const char* viewer_profile_uri); - -/// Refreshes gvr_context with the viewer profile that is stored on the device. -/// If it can not find the viewer profile, nothing will happen. -/// -/// @param gvr Pointer to the gvr instance to refresh the profile on. -void gvr_refresh_viewer_profile(gvr_context* gvr); - -/// Gets the name of the viewer vendor. -/// -/// @param gvr Pointer to the gvr instance from which to get the vendor. -/// @return A pointer to the vendor name. May be NULL if no viewer is paired. -/// WARNING: This method guarantees the validity of the returned pointer -/// only until the next use of the `gvr` context. The string should be -/// copied immediately if persistence is required. -const char* gvr_get_viewer_vendor(const gvr_context* gvr); - -/// Gets the name of the viewer model. -/// -/// @param gvr Pointer to the gvr instance from which to get the name. -/// @return A pointer to the model name. May be NULL if no viewer is paired. -/// WARNING: This method guarantees the validity of the returned pointer -/// only until the next use of the `gvr` context. The string should be -/// copied immediately if persistence is required. -const char* gvr_get_viewer_model(const gvr_context* gvr); - -/// Gets the type of the viewer, as defined by gvr_viewer_type. -/// -/// @param gvr Pointer to the gvr instance from which to get the viewer type. -/// @return The gvr_viewer_type of the currently paired viewer. -int32_t gvr_get_viewer_type(const gvr_context* gvr); - -/// Gets the transformation matrix to convert from Head Space to Eye Space for -/// the given eye. -/// -/// @param gvr Pointer to the gvr instance from which to get the matrix. -/// @param eye Selected gvr_eye type. -/// @return Transformation matrix from Head Space to selected Eye Space. -gvr_mat4f gvr_get_eye_from_head_matrix(const gvr_context* gvr, - const int32_t eye); - -/// Gets the window bounds. -/// -/// @param gvr Pointer to the gvr instance from which to get the bounds. -/// -/// @return Window bounds in physical pixels. -gvr_recti gvr_get_window_bounds(const gvr_context* gvr); - -/// Computes the distorted point for a given point in a given eye. The -/// distortion inverts the optical distortion caused by the lens for the eye. -/// Due to chromatic aberration, the distortion is different for each -/// color channel. -/// -/// @param gvr Pointer to the gvr instance which will do the computing. -/// @param eye The gvr_eye type (left or right). -/// @param uv_in A point in screen eye Viewport Space in [0,1]^2 with (0, 0) -/// in the lower left corner of the eye's viewport and (1, 1) in the -/// upper right corner of the eye's viewport. -/// @param uv_out A pointer to an array of (at least) 3 elements, with each -/// element being a Point2f representing a point in render texture eye -/// Viewport Space in [0,1]^2 with (0, 0) in the lower left corner of the -/// eye's viewport and (1, 1) in the upper right corner of the eye's -/// viewport. -/// `uv_out[0]` is the corrected position of `uv_in` for the red channel -/// `uv_out[1]` is the corrected position of `uv_in` for the green channel -/// `uv_out[2]` is the corrected position of `uv_in` for the blue channel -void gvr_compute_distorted_point(const gvr_context* gvr, const int32_t eye, - const gvr_vec2f uv_in, gvr_vec2f uv_out[3]); - -/// @} - -#ifdef __cplusplus -} // extern "C" -#endif - -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) -namespace gvr { - -/// Convenience C++ wrapper for gvr_user_prefs. -class UserPrefs { - public: - /// Creates a C++ wrapper for a gvr_user_prefs object. Note that unlike most - /// of the C++ wrappers in the API, this does not take ownership, as the - /// gvr_user_prefs will remain valid for the lifetime of the GVR context. - explicit UserPrefs(const gvr_user_prefs* user_prefs) - : user_prefs_(user_prefs) {} - - UserPrefs(UserPrefs&& other) : user_prefs_(nullptr) { - std::swap(user_prefs_, other.user_prefs_); - } - - UserPrefs& operator=(UserPrefs&& other) { - std::swap(user_prefs_, other.user_prefs_); - return *this; - } - - /// For more information, see gvr_user_prefs_get_controller_handedness(). - ControllerHandedness GetControllerHandedness() const { - return static_cast<ControllerHandedness>( - gvr_user_prefs_get_controller_handedness(user_prefs_)); - } - - /// Returns the wrapped C object. Does not affect ownership. - const gvr_user_prefs* cobj() const { return user_prefs_; } - - private: - const gvr_user_prefs* user_prefs_; - - // Disallow copy and assign. - UserPrefs(const UserPrefs&); - void operator=(const UserPrefs&); -}; - -/// Convenience C++ wrapper for the opaque gvr_buffer_viewport type. -/// The constructor allocates memory, so when used in tight loops, instances -/// should be reused. -class BufferViewport { - public: - BufferViewport(BufferViewport&& other) - : viewport_(nullptr) { - std::swap(viewport_, other.viewport_); - } - - BufferViewport& operator=(BufferViewport&& other) { - std::swap(viewport_, other.viewport_); - return *this; - } - - ~BufferViewport() { - if (viewport_) gvr_buffer_viewport_destroy(&viewport_); - } - - /// For more information, see gvr_buffer_viewport_get_source_fov(). - Rectf GetSourceFov() const { - return gvr_buffer_viewport_get_source_fov(viewport_); - } - - /// For more information, see gvr_buffer_viewport_set_source_fov(). - void SetSourceFov(const Rectf& fov) { - gvr_buffer_viewport_set_source_fov(viewport_, fov); - } - - /// For more information, see gvr_buffer_viewport_get_transform(). - Mat4f GetTransform() const { - return gvr_buffer_viewport_get_transform(viewport_); - } - - /// For more information, see gvr_buffer_viewport_set_transform(). - void SetTransform(const Mat4f& transform) { - gvr_buffer_viewport_set_transform(viewport_, transform); - } - - /// For more information, see gvr_buffer_viewport_get_source_uv(). - Rectf GetSourceUv() const { - return gvr_buffer_viewport_get_source_uv(viewport_); - } - - /// For more information, see gvr_buffer_viewport_set_source_uv(). - void SetSourceUv(const Rectf& uv) { - gvr_buffer_viewport_set_source_uv(viewport_, uv); - } - - /// For more information, see gvr_buffer_viewport_get_target_eye(). - Eye GetTargetEye() const { - return static_cast<Eye>(gvr_buffer_viewport_get_target_eye(viewport_)); - } - - /// For more information, see gvr_buffer_viewport_set_target_eye(). - void SetTargetEye(Eye eye) { - gvr_buffer_viewport_set_target_eye(viewport_, eye); - } - - /// For more information, see gvr_buffer_viewport_get_source_buffer_index(). - int32_t GetSourceBufferIndex() const { - return gvr_buffer_viewport_get_source_buffer_index(viewport_); - } - - /// For more information, see gvr_buffer_viewport_set_source_buffer_index(). - void SetSourceBufferIndex(int32_t buffer_index) { - gvr_buffer_viewport_set_source_buffer_index(viewport_, buffer_index); - } - - /// For more information, see gvr_buffer_viewport_get_external_surface_id(). - int32_t GetExternalSurfaceId() const { - return gvr_buffer_viewport_get_external_surface_id(viewport_); - } - - /// For more information, see gvr_buffer_viewport_set_external_surface_id(). - void SetExternalSurfaceId(const int32_t external_surface_id) { - gvr_buffer_viewport_set_external_surface_id(viewport_, external_surface_id); - } - - /// For more information, see gvr_buffer_viewport_get_reprojection(). - gvr_reprojection GetReprojection() const { - return static_cast<gvr_reprojection>( - gvr_buffer_viewport_get_reprojection(viewport_)); - } - /// For more information, see gvr_buffer_viewport_set_reprojection(). - void SetReprojection(gvr_reprojection reprojection) { - gvr_buffer_viewport_set_reprojection(viewport_, reprojection); - } - - /// For more information, see gvr_buffer_viewport_equal(). - bool operator==(const BufferViewport& other) const { - return gvr_buffer_viewport_equal(viewport_, other.viewport_) ? true : false; - } - bool operator!=(const BufferViewport& other) const { - return !(*this == other); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit BufferViewport(gvr_buffer_viewport* viewport) - : viewport_(viewport) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_buffer_viewport* cobj() { return viewport_; } - const gvr_buffer_viewport* cobj() const { return viewport_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_buffer_viewport* release() { - auto result = viewport_; - viewport_ = nullptr; - return result; - } - /// @} - - private: - friend class GvrApi; - friend class BufferViewportList; - - explicit BufferViewport(gvr_context* gvr) - : viewport_(gvr_buffer_viewport_create(gvr)) {} - - gvr_buffer_viewport* viewport_; -}; - -/// Convenience C++ wrapper for the opaque gvr_buffer_viewport_list type. This -/// class will automatically release the wrapped gvr_buffer_viewport_list upon -/// destruction. It can only be created via a `GvrApi` instance, and its -/// validity is tied to the lifetime of that instance. -class BufferViewportList { - public: - BufferViewportList(BufferViewportList&& other) - : context_(nullptr), viewport_list_(nullptr) { - std::swap(context_, other.context_); - std::swap(viewport_list_, other.viewport_list_); - } - - BufferViewportList& operator=(BufferViewportList&& other) { - std::swap(context_, other.context_); - std::swap(viewport_list_, other.viewport_list_); - return *this; - } - - ~BufferViewportList() { - if (viewport_list_) { - gvr_buffer_viewport_list_destroy(&viewport_list_); - } - } - - /// For more information, see gvr_get_recommended_buffer_viewports(). - void SetToRecommendedBufferViewports() { - gvr_get_recommended_buffer_viewports(context_, viewport_list_); - } - - /// For more information, see gvr_get_screen_buffer_viewports(). - void SetToScreenBufferViewports() { - gvr_get_screen_buffer_viewports(context_, viewport_list_); - } - - /// For more information, see gvr_buffer_viewport_list_set_item(). - void SetBufferViewport(size_t index, const BufferViewport& viewport) { - gvr_buffer_viewport_list_set_item(viewport_list_, index, - viewport.viewport_); - } - - /// For more information, see gvr_buffer_viewport_list_get_item(). - void GetBufferViewport(size_t index, BufferViewport* viewport) const { - gvr_buffer_viewport_list_get_item(viewport_list_, index, - viewport->viewport_); - } - - /// For more information, see gvr_buffer_viewport_list_get_size(). - size_t GetSize() const { - return gvr_buffer_viewport_list_get_size(viewport_list_); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - BufferViewportList(gvr_buffer_viewport_list* viewport_list, - gvr_context* context) - : context_(context), - viewport_list_(viewport_list) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_buffer_viewport_list* cobj() { return viewport_list_; } - const gvr_buffer_viewport_list* cobj() const { return viewport_list_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_buffer_viewport_list* release() { - auto result = viewport_list_; - viewport_list_ = nullptr; - return result; - } - /// @} - - private: - friend class Frame; - friend class GvrApi; - friend class SwapChain; - - explicit BufferViewportList(gvr_context* context) - : context_(context), - viewport_list_(gvr_buffer_viewport_list_create(context)) {} - - const gvr_context* context_; - gvr_buffer_viewport_list* viewport_list_; - - // Disallow copy and assign. - BufferViewportList(const BufferViewportList&) = delete; - void operator=(const BufferViewportList&) = delete; -}; - -/// Convenience C++ wrapper for gvr_buffer_spec, an opaque pixel buffer -/// specification. Frees the underlying gvr_buffer_spec on destruction. -class BufferSpec { - public: - BufferSpec(BufferSpec&& other) - : spec_(nullptr) { - std::swap(spec_, other.spec_); - } - - BufferSpec& operator=(BufferSpec&& other) { - std::swap(spec_, other.spec_); - return *this; - } - - ~BufferSpec() { - if (spec_) gvr_buffer_spec_destroy(&spec_); - } - - /// Gets the buffer's size. The default value is the recommended render - /// target size. For more information, see gvr_buffer_spec_get_size(). - Sizei GetSize() const { - return gvr_buffer_spec_get_size(spec_); - } - - /// Sets the buffer's size. For more information, see - /// gvr_buffer_spec_set_size(). - void SetSize(const Sizei& size) { - gvr_buffer_spec_set_size(spec_, size); - } - - /// Sets the buffer's size to the passed width and height. For more - /// information, see gvr_buffer_spec_set_size(). - /// - /// @param width The width in pixels. Must be greater than 0. - /// @param height The height in pixels. Must be greater than 0. - void SetSize(int32_t width, int32_t height) { - gvr_sizei size{width, height}; - gvr_buffer_spec_set_size(spec_, size); - } - - /// Gets the number of samples per pixel in the buffer. For more - /// information, see gvr_buffer_spec_get_samples(). - int32_t GetSamples() const { return gvr_buffer_spec_get_samples(spec_); } - - /// Sets the number of samples per pixel. For more information, see - /// gvr_buffer_spec_set_samples(). - void SetSamples(int32_t num_samples) { - gvr_buffer_spec_set_samples(spec_, num_samples); - } - - /// Sets the color format for this buffer. For more information, see - /// gvr_buffer_spec_set_color_format(). - void SetColorFormat(ColorFormat color_format) { - gvr_buffer_spec_set_color_format(spec_, color_format); - } - - /// Sets the depth and stencil format for this buffer. For more - /// information, see gvr_buffer_spec_set_depth_stencil_format(). - void SetDepthStencilFormat(DepthStencilFormat depth_stencil_format) { - gvr_buffer_spec_set_depth_stencil_format(spec_, depth_stencil_format); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit BufferSpec(gvr_buffer_spec* spec) : spec_(spec) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_buffer_spec* cobj() { return spec_; } - const gvr_buffer_spec* cobj() const { return spec_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_buffer_spec* release() { - auto result = spec_; - spec_ = nullptr; - return result; - } - /// @} - - private: - friend class GvrApi; - friend class SwapChain; - - explicit BufferSpec(gvr_context* gvr) { - spec_ = gvr_buffer_spec_create(gvr); - } - - gvr_buffer_spec* spec_; -}; - -/// Convenience C++ wrapper for gvr_frame, which represents a single frame -/// acquired for rendering from the swap chain. -class Frame { - public: - Frame(Frame&& other) : frame_(nullptr) { - std::swap(frame_, other.frame_); - } - - Frame& operator=(Frame&& other) { - std::swap(frame_, other.frame_); - return *this; - } - - ~Frame() { - // The swap chain owns the frame, so no clean-up is required. - } - - /// For more information, see gvr_frame_get_buffer_size(). - Sizei GetBufferSize(int32_t index) const { - return gvr_frame_get_buffer_size(frame_, index); - } - - /// For more information, see gvr_frame_bind_buffer(). - void BindBuffer(int32_t index) { - gvr_frame_bind_buffer(frame_, index); - } - - /// For more information, see gvr_frame_unbind(). - void Unbind() { - gvr_frame_unbind(frame_); - } - - /// For more information, see gvr_frame_get_framebuffer_object(). - int32_t GetFramebufferObject(int32_t index) { - return gvr_frame_get_framebuffer_object(frame_, index); - } - - /// For more information, see gvr_frame_submit(). - void Submit(const BufferViewportList& viewport_list, - const Mat4f& head_space_from_start_space) { - gvr_frame_submit(&frame_, viewport_list.viewport_list_, - head_space_from_start_space); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit Frame(gvr_frame* frame) : frame_(frame) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_frame* cobj() { return frame_; } - const gvr_frame* cobj() const { return frame_; } - - /// Returns whether the wrapped gvr_frame reference is valid. - bool is_valid() const { return frame_ != nullptr; } - explicit operator bool const() { return is_valid(); } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_frame* release() { - auto result = frame_; - frame_ = nullptr; - return result; - } - /// @} - - private: - friend class SwapChain; - - gvr_frame* frame_; -}; - -/// Convenience C++ wrapper for gvr_swap_chain, which represents a queue of -/// frames. The GvrApi object must outlive any SwapChain objects created from -/// it. -class SwapChain { - public: - SwapChain(SwapChain&& other) - : swap_chain_(nullptr) { - std::swap(swap_chain_, other.swap_chain_); - } - - SwapChain& operator=(SwapChain&& other) { - std::swap(swap_chain_, other.swap_chain_); - return *this; - } - - ~SwapChain() { - if (swap_chain_) gvr_swap_chain_destroy(&swap_chain_); - } - - /// For more information, see gvr_swap_chain_get_buffer_count(). - int32_t GetBufferCount() const { - return gvr_swap_chain_get_buffer_count(swap_chain_); - } - - /// For more information, see gvr_swap_chain_get_buffer_size(). - Sizei GetBufferSize(int32_t index) const { - return gvr_swap_chain_get_buffer_size(swap_chain_, index); - } - - /// For more information, see gvr_swap_chain_resize_buffer(). - void ResizeBuffer(int32_t index, Sizei size) { - gvr_swap_chain_resize_buffer(swap_chain_, index, size); - } - - /// For more information, see gvr_swap_chain_acquire_frame(). - /// Note that if Frame acquisition fails, the returned Frame may not be valid. - /// The caller should inspect the returned Frame's validity before using, - /// and reschedule frame acquisition upon failure. - Frame AcquireFrame() { - Frame result(gvr_swap_chain_acquire_frame(swap_chain_)); - return result; - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit SwapChain(gvr_swap_chain* swap_chain) : swap_chain_(swap_chain) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_swap_chain* cobj() { return swap_chain_; } - const gvr_swap_chain* cobj() const { return swap_chain_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_swap_chain* release() { - auto result = swap_chain_; - swap_chain_ = nullptr; - return result; - } - /// @} - - private: - friend class GvrApi; - - SwapChain(gvr_context* gvr, const std::vector<BufferSpec>& specs) { - std::vector<const gvr_buffer_spec*> c_specs; - for (const auto& spec : specs) - c_specs.push_back(spec.spec_); - swap_chain_ = gvr_swap_chain_create(gvr, c_specs.data(), - static_cast<int32_t>(c_specs.size())); - } - - gvr_swap_chain* swap_chain_; - - // Disallow copy and assign. - SwapChain(const SwapChain&); - void operator=(const SwapChain&); -}; - -/// This is a convenience C++ wrapper for the Google VR C API. -/// -/// This wrapper strategy prevents ABI compatibility issues between compilers -/// by ensuring that the interface between client code and the implementation -/// code in libgvr.so is a pure C interface. The translation from C++ calls -/// to C calls provided by this wrapper runs entirely in the client's binary -/// and is compiled by the client's compiler. -/// -/// Methods in this class are only documented insofar as the C++ wrapping logic -/// is concerned; for information about the method itself, please refer to the -/// corresponding function in the C API. -/// -/// Example API usage: -/// -/// // Functionality supplied by the application in the example below has -/// // the "app-" prefix. -/// #ifdef __ANDROID__ -/// // On Android, the gvr_context should almost always be obtained from the -/// // Java GvrLayout object via -/// // GvrLayout.getGvrApi().getNativeGvrContext(). -/// std::unique_ptr<GvrApi> gvr = GvrApi::WrapNonOwned(gvr_context); -/// #else -/// std::unique_ptr<GvrApi> gvr = GvrApi::Create(); -/// #endif -/// -/// gvr->InitializeGl(); -/// -/// gvr::BufferViewportList viewport_list = -/// gvr->CreateEmptyBufferViewportList(); -/// gvr->GetRecommendedBufferViewports(&viewport_list); -/// gvr::BufferViewport left_eye_viewport = gvr->CreateBufferViewport(); -/// gvr::BufferViewport right_eye_viewport = gvr->CreateBufferViewport(); -/// viewport_list.Get(0, &left_eye_view); -/// viewport_list.Get(1, &right_eye_view); -/// -/// std::vector<gvr::BufferSpec> specs; -/// specs.push_back(gvr->CreateBufferSpec()); -/// specs[0].SetSamples(app_samples); -/// gvr::SwapChain swap_chain = gvr->CreateSwapChain(specs); -/// -/// while (client_app_should_render) { -/// // A client app should be ready for the render target size to change -/// // whenever a new QR code is scanned, or a new viewer is paired. -/// gvr::Sizei render_target_size = -/// gvr->GetRecommendedRenderTargetSize(); -/// swap_chain.ResizeBuffer(0, render_target_size); -/// gvr::Frame frame = swap_chain.AcquireFrame(); -/// while (!frame) { -/// std::this_thread::sleep_for(2ms); -/// frame = swap_chain.AcquireFrame(); -/// } -/// -/// // This function will depend on your render loop's implementation. -/// gvr::ClockTimePoint next_vsync = AppGetNextVsyncTime(); -/// -/// const gvr::Mat4f head_view = -/// gvr->GetHeadSpaceFromStartSpaceRotation(next_vsync); -/// const gvr::Mat4f left_eye_view = MatrixMultiply( -/// gvr->GetEyeFromHeadMatrix(kLeftEye), head_view); -/// const gvr::Mat4f right_eye_view = MatrixMultiply( -/// gvr->GetEyeFromHeadMatrix(kRightEye), head_view); -/// -/// frame.BindBuffer(0); -/// // App does its rendering to the current framebuffer here. -/// AppDoSomeRenderingForEye( -/// left_eye_viewport.GetSourceUv(), left_eye_view); -/// AppDoSomeRenderingForEye( -/// right_eye_viewport.GetSourceUv(), right_eye_view); -/// frame.Unbind(); -/// frame.Submit(viewport_list, head_matrix); -/// } -/// -class GvrApi { - public: -#ifdef __ANDROID__ - /// Instantiates and returns a GvrApi instance that owns a gvr_context. - /// - /// @param env The JNIEnv associated with the current thread. - /// @param app_context The Android application context. This must be the - /// application context, NOT an Activity context (Note: from any Android - /// Activity in your app, you can call getApplicationContext() to - /// retrieve the application context). - /// @param class_loader The class loader to use when loading Java classes. - /// This must be your app's main class loader (usually accessible through - /// activity.getClassLoader() on any of your Activities). - /// @return unique_ptr to the created GvrApi instance, nullptr on failure. - static std::unique_ptr<GvrApi> Create(JNIEnv* env, jobject app_context, - jobject class_loader) { - gvr_context* context = gvr_create(env, app_context, class_loader); - if (!context) { - return nullptr; - } - return std::unique_ptr<GvrApi>(new GvrApi(context, true /* owned */)); - } -#else - /// Instantiates and returns a GvrApi instance that owns a gvr_context. - /// - /// @return unique_ptr to the created GvrApi instance, nullptr on failure. - static std::unique_ptr<GvrApi> Create() { - gvr_context* context = gvr_create(); - if (!context) { - return nullptr; - } - return std::unique_ptr<GvrApi>(new GvrApi(context, true /* owned */)); - } -#endif // #ifdef __ANDROID__ - - ~GvrApi() { - if (context_ && owned_) { - gvr_destroy(&context_); - } - } - - /// @name Error handling - /// @{ - - /// For more information, see gvr_get_error(). - Error GetError() { return static_cast<Error>(gvr_get_error(context_)); } - - /// For more information, see gvr_clear_error(). - Error ClearError() { return static_cast<Error>(gvr_clear_error(context_)); } - - /// For more information, see gvr_get_error_string(). - static const char* GetErrorString(Error error_code) { - return gvr_get_error_string(error_code); - } - - /// For more information, see gvr_get_user_prefs(). - UserPrefs GetUserPrefs() { return UserPrefs(gvr_get_user_prefs(context_)); } - - /// @} - - /// @name Rendering - /// @{ - - /// For more information, see gvr_initialize_gl(). - void InitializeGl() { gvr_initialize_gl(context_); } - - /// For more information, see gvr_get_async_reprojection_enabled(). - bool GetAsyncReprojectionEnabled() const { - return gvr_get_async_reprojection_enabled(context_); - } - - /// Constructs a C++ wrapper for a gvr_buffer_viewport object. For more - /// information, see gvr_buffer_viewport_create(). - /// - /// @return A new BufferViewport instance with memory allocated for an - /// underlying gvr_buffer_viewport. - BufferViewport CreateBufferViewport() const { - return BufferViewport(context_); - } - - /// Constructs a C++ wrapper for a gvr_buffer_viewport_list object. - /// For more information, see gvr_buffer_viewport_list_create(). - /// - /// @return A new, empty BufferViewportList instance. - /// Note: The validity of the returned object is closely tied to the - /// lifetime of the member gvr_context. The caller is responsible for - /// ensuring correct usage accordingly. - BufferViewportList CreateEmptyBufferViewportList() const { - return BufferViewportList(context_); - } - - /// For more information, see gvr_get_maximum_effective_render_target_size(). - Sizei GetMaximumEffectiveRenderTargetSize() const { - return gvr_get_maximum_effective_render_target_size(context_); - } - - /// For more information, see gvr_get_screen_target_size(). - Sizei GetScreenTargetSize() const { - return gvr_get_screen_target_size(context_); - } - - /// For more information, see gvr_set_surface_size(). - void SetSurfaceSize(Sizei surface_size_pixels) { - gvr_set_surface_size(context_, surface_size_pixels); - } - - /// For more information, see gvr_distort_to_screen(). - void DistortToScreen(int32_t texture_id, - const BufferViewportList& viewport_list, - const Mat4f& rendered_head_pose_in_start_space_matrix, - const ClockTimePoint& texture_presentation_time) { - gvr_distort_to_screen(context_, texture_id, viewport_list.viewport_list_, - rendered_head_pose_in_start_space_matrix, - texture_presentation_time); - } - - /// For more information, see gvr_is_feature_supported(). - bool IsFeatureSupported(int32_t feature) { - return gvr_is_feature_supported(context_, feature); - } - - /// For more information, see gvr_buffer_spec_create(). - BufferSpec CreateBufferSpec() { - return BufferSpec(context_); - } - - /// For more information, see gvr_swap_chain_create(). - SwapChain CreateSwapChain(const std::vector<BufferSpec>& specs) { - return SwapChain(context_, specs); - } - - /// For more information, see gvr_bind_default_framebuffer(). - void BindDefaultFramebuffer() { - gvr_bind_default_framebuffer(context_); - } - /// @} - - /// @name Head tracking - /// @{ - - /// For more information see gvr_get_head_space_from_start_space_rotation. - /// - /// @param time_point The time at which to calculate the head pose in start - /// space. - /// @return The matrix representation of the rotation from start space - /// (the space with the head pose at the last tracking reset at origin) to - /// head space (the space with the head at origin and axes aligned to the - /// view vector). - Mat4f GetHeadSpaceFromStartSpaceRotation(const ClockTimePoint& time_point) { - return gvr_get_head_space_from_start_space_rotation(context_, time_point); - } - - /// For more information, see gvr_apply_neck_model(). - Mat4f ApplyNeckModel(const Mat4f& head_pose_in_start_space, float factor) { - return gvr_apply_neck_model(context_, head_pose_in_start_space, factor); - } - - /// For more information, see gvr_pause_tracking(). - void PauseTracking() { gvr_pause_tracking(context_); } - - /// For more information, see gvr_resume_tracking(). - void ResumeTracking() { gvr_resume_tracking(context_); } - - /// For more information, see gvr_reset_tracking(). - void ResetTracking() { gvr_reset_tracking(context_); } - - // For more information, see gvr_recenter_tracking(). - void RecenterTracking() { gvr_recenter_tracking(context_); } - - /// For more information, see gvr_get_time_point_now(). - static ClockTimePoint GetTimePointNow() { return gvr_get_time_point_now(); } - /// @} - - /// @name Viewer parameters - /// @{ - - /// For more information, see gvr_set_default_viewer_profile(). - bool SetDefaultViewerProfile(const char* viewer_profile_uri) { - return gvr_set_default_viewer_profile(context_, viewer_profile_uri); - } - - /// For more information, see gvr_refresh_viewer_profile(). - void RefreshViewerProfile() { gvr_refresh_viewer_profile(context_); } - - /// For more information, see gvr_get_viewer_vendor(). - const char* GetViewerVendor() const { - return gvr_get_viewer_vendor(context_); - } - - /// For more information, see gvr_get_viewer_model(). - const char* GetViewerModel() const { return gvr_get_viewer_model(context_); } - - /// For more information, see gvr_get_viewer_type(). - ViewerType GetViewerType() const { - return static_cast<ViewerType>(gvr_get_viewer_type(context_)); - } - - /// For more information, see gvr_get_eye_from_head_matrix(). - Mat4f GetEyeFromHeadMatrix(Eye eye) const { - return gvr_get_eye_from_head_matrix(context_, eye); - } - - /// For more information, see gvr_get_window_bounds(). - Recti GetWindowBounds() const { return gvr_get_window_bounds(context_); } - - /// For more information, see gvr_compute_distorted_point(). - std::array<Vec2f, 3> ComputeDistortedPoint(Eye eye, const Vec2f& uv_in) { - std::array<Vec2f, 3> uv_out = {{{}}}; - gvr_compute_distorted_point(context_, eye, uv_in, uv_out.data()); - return uv_out; - } - /// @} - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and optionally takes ownership. - /// - /// @param context C object to wrap. - /// @param owned Whether the wrapper will own the underlying C object. - explicit GvrApi(gvr_context* context, bool owned = true) - : context_(context), owned_(owned) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_context* cobj() { return context_; } - const gvr_context* cobj() const { return context_; } - - /// @deprecated Use cobj() instead. - gvr_context* GetContext() { return context_; } - /// @deprecated Use cobj() instead. - const gvr_context* GetContext() const { return context_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_context* release() { - auto result = context_; - context_ = nullptr; - return result; - } - - /// Instantiates a GvrApi instance that wraps a *non-owned* gvr_context. - /// - /// Ownership of the provided `context` remains with the caller, and they - /// are responsible for ensuring proper disposal of the context. - /// - /// @param context Pointer to a non-null, non-owned gvr_context instance. - /// @return unique_ptr to the created GvrApi instance. Never null. - static std::unique_ptr<GvrApi> WrapNonOwned(gvr_context* context) { - return std::unique_ptr<GvrApi>(new GvrApi(context, false /* owned */)); - } - /// @} - - private: - gvr_context* context_; - - // Whether context_ is owned by the GvrApi instance. If owned, the context - // will be released upon destruction. - const bool owned_; - - // Disallow copy and assign. - GvrApi(const GvrApi&); - void operator=(const GvrApi&); -}; - -} // namespace gvr -#endif // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#endif // VR_GVR_CAPI_INCLUDE_GVR_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h deleted file mode 100644 index d34c84d0f3..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h +++ /dev/null @@ -1,852 +0,0 @@ -/* Copyright 2016 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_ - -#if __ANDROID__ -#include <jni.h> -#endif // __ANDROID__ - -#include <stdint.h> - -#include "vr/gvr/capi/include/gvr.h" -#include "vr/gvr/capi/include/gvr_types.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/// @defgroup Audio Spatial Audio API -/// @brief This is the GVR Audio C API, a spatial audio rendering engine, -/// optimized for mobile VR. -/// -/// It allows the user to spatialize sound sources in 3D space, including -/// distance and elevation cues. Specifically, the API is capable of playing -/// back spatial sound in three ways: -/// -/// - **Sound object rendering**: This allows the user to create a virtual sound -/// source in 3D space. These sources, while spatialized, are fed with mono -/// audio data. -/// -/// - **Ambisonic soundfields**: Ambisonic recordings are multi-channel audio -/// files which are spatialized all around the listener in 360 degrees. These -/// can be thought of as recorded or pre-baked soundfields. They can be of -/// great use for background effects which sound perfectly spatial. Examples -/// include rain noise, crowd noise or even the sound of the ocean off to one -/// side. -/// -/// - **Stereo Sounds**: This allows the user to directly play back -/// non-spatialized mono or stereo audio files. This is useful for music and -/// other such audio. -/// -/// **Initialization** -/// -/// gvr_audio_context* gvr_audio_create(int32_t rendering_mode); -/// -/// The rendering_mode argument corresponds to a `gvr_audio_rendering_mode` enum -/// value, which specifies a rendering configuration setting: -/// -/// - `GVR_AUDIO_RENDERING_STEREO_PANNING`: -/// Stereo panning of all sound objects. This disables HRTF-based rendering. -/// - `GVR_AUDIO_RENDERING_BINAURAL_LOW_QUALITY`: -/// This renders sound objects over a virtual array of 8 loudspeakers arranged -/// in a cube configuration around the listener’s head. HRTF-based rendering -/// is enabled. -/// - `GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY`: -/// This renders sound objects over a virtual array of 16 loudspeakers -/// arranged in an approximate equidistribution about the listener’s -/// head. HRTF-based rendering is enabled. -/// -/// For most modern phones, the high quality mode offers a good balance between -/// performance and audio quality. To optimize the rendering performance for -/// headphones *and* speaker playback, the stereo speaker mode can be enabled -/// which automatically switches to stereo panning when no headphone is plugin. -/// Note that this can lead to varying CPU usage based on headphone and speaker -/// playback. -/// -/// **Sound engine control** -/// -/// Audio playback on the default audio device can be started and stopped by -/// calling the following two methods: -/// -/// void gvr_audio_pause(gvr_audio_context* api); -/// void gvr_audio_resume(gvr_audio_context* api); -/// -/// Note that: -/// -/// void gvr_audio_update(gvr_audio_context* api); -/// -/// must be called from the main thread at a regular rate. It is used to execute -/// background operations outside of the audio thread. -/// -/// **Listener position and rotation** -/// -/// To ensure that the audio in your application reacts to listener head -/// movement, it is important to update the listener's head orientation in the -/// graphics callback using the head orientation matrix. -/// -/// The following methods can be used to control the listener’s head position -/// and orientation with the audio engine: -/// -/// void gvr_audio_set_head_position(gvr_audio_context* api, float x, -/// float y, float z); -/// or -/// -/// void gvr_audio_set_head_position_gvr(gvr_audio_context* api, -/// const gvr_vec3f& position); -/// -/// and -/// -/// void gvr_audio_set_head_rotation(gvr_audio_context* api, -/// float x, float y, float z, float w); -/// or -/// -/// void gvr_audio_set_head_rotation_gvr(gvr_audio_context* api, -/// const gvr_quatf& rotation); -/// -/// **Preloading Sounds** -/// -/// Both mono sound files for use with Sound Objects and multi-channel Ambisonic -/// soundfield files can be preloaded into memory before playback or -/// alternatively streamed during playback. Preloading can be useful to reduce -/// CPU usage especially if the same audio clip is likely to be played back many -/// times. In this case playback latency is also reduced. -/// -/// Sound files can be preloaded into memory by calling: -/// -/// bool gvr_audio_preload_soundfile(gvr_audio_context* api, -/// const char* filename); -/// -/// Unused sound files can be unloaded with a call to: -/// -/// void gvr_audio_unload_soundfile(gvr_audio_context* api, -/// const char* filename); -/// -/// NOTE: If a sound object, soundfield or stereo sound is created with a file -/// that has not been preloaded, that audio will be streamed. -/// -/// **Spatializtion of sound objects** -/// -/// The GVR Audio System allows the user to create virtual sound objects which -/// can be placed anywhere in space around the listener. -/// -/// To create a new sound object, call: -/// -/// gvr_audio_source_id -/// gvr_audio_create_sound_object(gvr_audio_context* api, -/// const char* filename); -/// -/// This returns a handle that can be used to set properties such as the -/// position and the volume of the sound object via calls to the following two -/// functions: -/// -/// void -/// gvr_audio_set_sound_object_position(gvr_audio_context* api, -/// gvr_audio_source_id sound_object_id, -/// float x, float y, float z); -/// -/// void -/// gvr_audio_set_sound_volume(gvr_audio_context* api, -/// gvr_audio_source_id source_id, float volume); -/// -/// The behavior of Sound Objects with respect to their distance from the -/// listener can be controlled via calls to the following method: -/// -/// void gvr_audio_set_sound_object_distance_rolloff_model( -/// gvr_audio_context* api, gvr_audio_source_id sound_object_id, -/// int32_t rolloff_model, float min_distance, float max_distance); -/// -/// This enables a user to choose between logarithmic and linear distance -/// rolloff methods, or to completely disable distance rolloff effects. -/// -/// -/// The spatialized playback of a sound object can be triggered with a call to: -/// -/// void gvr_audio_play_sound(gvr_audio_context* api, -/// gvr_audio_source_id source_id, -/// bool looping_enabled); -/// -/// and stopped with a call to: -/// -/// void gvr_audio_stop_sound(gvr_audio_context* api, -/// gvr_audio_source_id source_id); -/// -/// Note that the sound object handle destroys itself at the moment the sound -/// playback has stopped. This way, no clean up of sound object handles is -/// needed. On subsequent calls to this function the corresponding -/// gvr_audio_source_id no longer refers to a valid sound object. -/// -/// The following function can be used to check if a sound object is currently -/// active: -/// -/// bool gvr_audio_is_sound_playing(const gvr_audio_context* api, -/// gvr_audio_source_id source_id); -/// -/// **Rendering of ambisonic soundfields** -/// -/// The GVR Audio System also provides the user with the ability to play back -/// ambisonic soundfields. Ambisonic soundfields are captured or pre-rendered -/// 360 degree recordings. It is best to think of them as equivalent to 360 -/// degree video. While they envelop and surround the listener, they only react -/// to the listener's rotational movement. That is, one cannot walk towards -/// features in the soundfield. Soundfields are ideal for accompanying 360 -/// degree video playback, for introducing background and environmental effects -/// such as rain or crowd noise, or even for pre baking 3D audio to reduce -/// rendering costs. The GVR Audio System supports full 3D First Order -/// Ambisonic recordings using ACN channel ordering and SN3D normalization. For -/// more information please see our Spatial Audio specification at: -/// https://github.com/google/spatial-media/blob/master/docs/spatial-audio-rfc.md#semantics -/// -/// Note that Soundfield playback is directly streamed from the sound file and -/// no sound file preloading is needed. -/// -/// To obtain a soundfield handler, call: -/// -/// gvr_audio_source_id gvr_audio_create_soundfield(gvr_audio_context* api, -/// const char* filename); -/// -/// This returns a gvr_audio_source_id handle that allows the user to begin -/// playback of the soundfield, to alter the soundfield’s volume or to stop -/// soundfield playback and as such destroy the object. These actions can be -/// achieved with calls to the following functions: -/// -/// void gvr_audio_play_sound(gvr_audio_context* api, -/// gvr_audio_source_id source_id, -/// bool looping_enabled); -/// -/// void gvr_audio_set_sound_volume(gvr_audio_context* api, -/// gvr_audio_source_id source_id, -/// float volume); -/// -/// void gvr_audio_stop_sound(gvr_audio_context* api, -/// gvr_audio_source_id source_id); -/// -/// Ambisonic soundfields can also be rotated about the listener's head in order -/// to align the components of the soundfield with the visuals of the game/app. -/// -/// void gvr_audio_set_soundfield_rotation(gvr_audio_context* api, -/// gvr_audio_source_id soundfield_id, -/// const gvr_quatf& -/// soundfield_rotation); -/// -/// **Direct Playback of Stereo or Mono Sounds** -/// -/// The GVR Audio System allows the direct non-spatialized playback of both -/// stereo and mono audio. Such audio is often used for music or sound effects -/// that should not be spatialized. -/// -/// A stereo sound can be created with a call to: -/// -/// gvr_audio_source_id gvr_audio_create_stereo_sound(gvr_audio_context* api, -/// const char* filename); -/// -/// **Paused Sounds and Stopped Sounds** -/// -/// When using sound sources of any of the above types, the user can ensure that -/// the given source is currently playing before calling. -/// -/// bool gvr_audio_is_sound_playing(gvr_audio_source_id source_id); -/// -/// This method will return false if the source has been either paused or -/// stopped, and true if the source is currently playing. -/// -/// Once one is finished with a Sound Object and wish to remove it, a call can -/// be placed to: -/// -/// void gvr_audio_stop_sound(gvr_audio_source_id source_id); -/// -/// Once a source has been stopped it is destroyed and the corresponding -/// gvr_audio_source_id will be invalid. Sources which have been played with the -/// |looping_enabled| parameter disabled will also be destroyed once playback -/// of the full audio clip has completed. -/// -/// To check whether a given gvr_audio_source_id corresponds to a valid source -/// which exists and is in a playable state, a call can be made to: -/// -/// bool gvr_audio_is_source_id_valid(gvr_audio_source_id source_id); -/// -/// By using this pair of methods a user can differentiate between sources which -/// have been paused and those which have ceased. -/// -/// **Room effects** -/// -/// The GVR Audio System provides a powerful reverb engine which can be used to -/// create customized room effects by specifying the size of a room and a -/// material for each surface of the room from the gvr_audio_material_name enum. -/// Each of these surface materials has unique absorption properties which -/// differ with frequency. The room created will be centered around the -/// listener. Note that the Google VR Audio System uses meters as the unit of -/// distance throughout. -/// -/// The following methods are used to control room effects: -/// -/// void gvr_audio_enable_room(gvr_audio_context* api, bool enable); -/// -/// enables or disables room effects with smooth transitions. -/// -/// and -/// -/// void -/// gvr_audio_set_room_properties(gvr_audio_context* api, float size_x, -/// float size_y, float size_z, -/// gvr_audio_material_name wall_material, -/// gvr_audio_material_name ceiling_material, -/// gvr_audio_material_name floor_material); -/// -/// allows the user to describe the room based on its dimensions and its surface -/// properties. For example, one can expect very large rooms to be more -/// reverberant than smaller rooms, and a room with with hard surface materials -/// such as brick to be more reverberant than one with soft absorbent materials -/// such as heavy curtains on every surface. -/// -/// Note that when a sound source is located outside of the listener's room, -/// it will sound different from sources located within the room due to -/// attenuation of both the direct sound and the reverb on that source. Sources -/// located far outside of the listener's room will not be audible to the -/// listener. -/// -/// The following method can be used to subtly adjust the reverb in a room by -/// changing the gain/attenuation on the reverb, setting a multiplier on the -/// reverberation time to control the reverb's length, or adjusting the balance -/// between the low and high frequency components of the reverb. -/// -/// void gvr_audio_set_room_reverb_adjustments(gvr_audio_context* api, -/// float gain, -/// float time_adjust, -/// float brightness_adjust); -/// -/// If you are writing C++ code, you might prefer to use the C++ wrapper -/// rather than implement this C API directly. -/// -/// **Example usage (C++ API)** -/// -/// Construction: -/// -/// std::unique_ptr<gvr::AudioApi> gvr_audio_api(new gvr::AudioApi); -/// gvr_audio_api->Init(GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY); -/// -/// Update head rotation in DrawFrame(): -/// -/// head_pose_ = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time); -/// gvr_audio_api_->SetHeadPose(head_pose_); -/// gvr_audio_api_->Update(); -/// -/// Preload sound file, create sound handle and start playback: -/// -/// gvr_audio_api->PreloadSoundfile(kSoundFile); -/// AudioSourceId source_id = -/// gvr_audio_api_->CreateSoundObject("sound.wav"); -/// gvr_audio_api->SetSoundObjectPosition(source_id, -/// position_x, -/// position_y, -/// position_z); -/// gvr_audio_api->PlaySound(source_id, true /* looped playback */); -/// - -/// @{ - -typedef struct gvr_audio_context_ gvr_audio_context; - -/// Creates and initializes a gvr_audio_context. This call also initializes -/// the audio interface and starts the audio engine. Note that the returned -/// instance must be deleted with gvr_audio_destroy. -/// -#ifdef __ANDROID__ -/// @param env The JNI Env associated with the current thread. -/// @param android_context The Android application context. This must be the -/// application context, NOT an Activity context (Note: from any Android -/// Activity in your app, you can call getApplicationContext() to -/// retrieve the application context). -/// @param class_loader The class loader to use when loading Java -/// classes. This must be your app's main class loader (usually -/// accessible through activity.getClassLoader() on any of your Activities). -/// @param rendering_mode The gvr_audio_rendering_mode value which determines -/// the rendering configuration preset. This is passed as an int32_t to -/// ensure API compatibility. -/// @return gvr_audio_context instance. -gvr_audio_context* gvr_audio_create(JNIEnv* env, jobject android_context, - jobject class_loader, - int32_t rendering_mode); -#else -/// @param rendering_mode The gvr_audio_rendering_mode value which determines -/// the rendering configuration preset. This is passed as an int32_t to -/// ensure API compatibility. -/// @return gvr_audio_context instance. -gvr_audio_context* gvr_audio_create(int32_t rendering_mode); -#endif // #ifdef __ANDROID__ - -/// Destroys a gvr_audio_context that was previously created with -/// gvr_audio_create or gvr_audio_create_android. -/// -/// @param api Pointer to a pointer to a gvr_audio_context. The pointer -/// will be set to NULL after destruction. -void gvr_audio_destroy(gvr_audio_context** api); - -/// Resumes the VR Audio system. -/// Call this when your app/game loses focus. -/// Calling this when not paused is a no-op. -/// Thread-safe (call from any thread). -/// -/// @param api Pointer to a gvr_audio_context. -void gvr_audio_resume(gvr_audio_context* api); - -/// Pauses the VR Audio system. -/// Calling this when already paused is a no-op. -/// Thread-safe (call from any thread). -/// -/// @param api Pointer to a gvr_audio_context. -void gvr_audio_pause(gvr_audio_context* api); - -/// This method must be called from the main thread at a regular rate. It is -/// used to execute background operations outside of the audio thread. -/// -/// @param api Pointer to a gvr_audio_context. -void gvr_audio_update(gvr_audio_context* api); - -/// Preloads a local sound file. Note that the local file access method -/// depends on the target platform. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param filename Name of the file, used as identifier. -/// @return True on success or if file has already been preloaded. -bool gvr_audio_preload_soundfile(gvr_audio_context* api, const char* filename); - -/// Unloads a previously preloaded sample from memory. Note that if the sample -/// is currently used, the memory is freed at the moment playback stops. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param filename Name of the file, used as identifier. -void gvr_audio_unload_soundfile(gvr_audio_context* api, const char* filename); - -/// Returns a new sound object. Note that the sample should only contain a -/// single audio channel (stereo sources are automatically downmixed to mono). -/// The handle automatically destroys itself at the moment the sound playback -/// has stopped. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param filename The path/name of the file to be played. -/// @return Id of new sound object. Returns kInvalidId if the sound file has not -/// been preloaded or if the number of input channels is > 1. -gvr_audio_source_id gvr_audio_create_sound_object(gvr_audio_context* api, - const char* filename); - -/// Returns a new ambisonic sound field. Note that the sample needs to be -/// preloaded and must have 4 separate audio channels. The handle automatically -/// destroys itself at the moment the sound playback has stopped. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param filename The path/name of the file to be played. -/// @return Id of new soundfield. Returns kInvalidId if the sound file has not -/// been preloaded or if the number of input channels does not match that -/// required. -gvr_audio_source_id gvr_audio_create_soundfield(gvr_audio_context* api, - const char* filename); - -/// Returns a new stereo non-spatialized source, which directly plays back mono -/// or stereo audio. Note the sample needs to be preloaded and may contain only -/// one (mono) or two (stereo) audio channels. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param filename The path/name of the file to be played.. -/// @return Id of new stereo non-spatialized source. Returns kInvalidId if the -/// sound file has not been preloaded or if the number of input channels is -/// > 2; -gvr_audio_source_id gvr_audio_create_stereo_sound(gvr_audio_context* api, - const char* filename); - -/// Starts the playback of a sound. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be stopped. -/// @param looping_enabled Enables looped audio playback. -void gvr_audio_play_sound(gvr_audio_context* api, gvr_audio_source_id source_id, - bool looping_enabled); - -/// Pauses the playback of a sound. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be paused. -void gvr_audio_pause_sound(gvr_audio_context* api, - gvr_audio_source_id source_id); - -/// Resumes the playback of a sound. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be resumed. -void gvr_audio_resume_sound(gvr_audio_context* api, - gvr_audio_source_id source_id); - -/// Stops the playback of a sound and destroys the corresponding sound object -/// or Soundfield. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be stopped. -void gvr_audio_stop_sound(gvr_audio_context* api, - gvr_audio_source_id source_id); - -/// Checks if a sound is playing. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be checked. -/// @return True if the sound is being played. -bool gvr_audio_is_sound_playing(const gvr_audio_context* api, - gvr_audio_source_id source_id); - -/// Checks if a |source_id| is valid, and that the corresponding source is in a -/// playable state. Sources that have been stopped will be reported as invalid. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be checked. -/// @return True if the source exists and is in a playable state. -bool gvr_audio_is_source_id_valid(const gvr_audio_context* api, - gvr_audio_source_id source_id); - -/// Repositions an existing sound object. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param sound_object_id Id of the sound object to be moved. -/// @param x X coordinate the sound will be placed at. -/// @param y Y coordinate the sound will be placed at. -/// @param z Z coordinate the sound will be placed at. -void gvr_audio_set_sound_object_position(gvr_audio_context* api, - gvr_audio_source_id sound_object_id, - float x, float y, float z); - -/// Sets the given ambisonic soundfields's rotation. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param soundfield_id Id of the soundfield source to be rotated. -/// @param soundfield_rotation Quaternion representing the soundfield rotation. -void gvr_audio_set_soundfield_rotation(gvr_audio_context* api, - gvr_audio_source_id soundfield_id, - const gvr_quatf& soundfield_rotation); - -/// Sets the given sound object source's distance attenuation method with -/// minimum and maximum distances. Maximum distance must be greater than the -/// minimum distance for the method to be set. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param sound_object_id Id of sound object source. -/// @param rolloff_model Linear or logarithmic distance rolloff models. Note -/// setting the rolloff model to |GVR_AUDIO_ROLLOFF_NONE| will allow -/// distance attenuation values to be set manually. -/// @param min_distance Minimum distance to apply distance attenuation method. -/// @param max_distance Maximum distance to apply distance attenuation method. -void gvr_audio_set_sound_object_distance_rolloff_model( - gvr_audio_context* api, gvr_audio_source_id sound_object_id, - int32_t rolloff_model, float min_distance, float max_distance); - -/// Changes the master volume. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param volume Volume value. Should range from 0 (mute) to 1 (max). -void gvr_audio_set_master_volume(gvr_audio_context* api, float volume); - -/// Changes the volume of an existing sound. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param source_id Id of the audio source to be modified. -/// @param volume Volume value. Should range from 0 (mute) to 1 (max). -void gvr_audio_set_sound_volume(gvr_audio_context* api, - gvr_audio_source_id source_id, float volume); - -/// Sets the head pose from a matrix representation of the same. -/// -/// @param api Pointer to a gvr_audio_context on which to set the pose. -/// @param head_pose_matrix Matrix representing the head transform to be set. -void gvr_audio_set_head_pose(gvr_audio_context* api, - const gvr_mat4f& head_pose_matrix); - -/// Turns on/off the room reverberation effect. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param enable True to enable room effect. -void gvr_audio_enable_room(gvr_audio_context* api, bool enable); - -/// Sets the room properties describing the dimensions and surface materials of -/// a given room. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param size_x Dimension along X axis. -/// @param size_y Dimension along Y axis. -/// @param size_z Dimension along Z axis. -/// @param wall_material Surface gvr_audio_material_type for the four walls. -/// @param ceiling_material Surface gvr_audio_material_type for the ceiling. -/// @param floor_material Surface gvr_audio_material_type for the floor. -void gvr_audio_set_room_properties(gvr_audio_context* api, float size_x, - float size_y, float size_z, - int32_t wall_material, - int32_t ceiling_material, - int32_t floor_material); - -/// Adjusts the properties of the current reverb, allowing changes to the -/// reverb's gain, duration and low/high frequency balance. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param gain Reverb volume (linear) adjustment in range [0, 1] for -/// attenuation, range [1, inf) for gain boost. -/// @param time_adjust Reverb time adjustment multiplier to scale the -/// reverberation tail length. This value should be >= 0. -/// @param brightness_adjust Reverb brightness adjustment that controls the -/// reverberation ratio across low and high frequency bands. -void gvr_audio_set_room_reverb_adjustments(gvr_audio_context* api, float gain, - float time_adjust, - float brightness_adjust); - -/// Enables the stereo speaker mode. It enforces stereo-panning when headphones -/// are *not* plugged into the phone. This helps to avoid HRTF-based coloring -/// effects and reduces computational complexity when speaker playback is -/// active. By default the stereo speaker mode optimization is disabled. -/// -/// @param api Pointer to a gvr_audio_context. -/// @param enable True to enable the stereo speaker mode. -void gvr_audio_enable_stereo_speaker_mode(gvr_audio_context* api, bool enable); - -/// @} - -#ifdef __cplusplus -} // extern "C" -#endif - -// Convenience C++ wrapper. -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#include <memory> -#include <string> - -namespace gvr { -/// This is a convenience C++ wrapper for the Audio C API. -/// -/// This wrapper strategy prevents ABI compatibility issues between compilers -/// by ensuring that the interface between client code and the implementation -/// code in libgvr.so is a pure C interface. The translation from C++ calls -/// to C calls provided by this wrapper runs entirely in the client's binary -/// and is compiled by the client's compiler. -/// -/// Methods in this class are only documented insofar as the C++ wrapping logic -/// is concerned; for information about the method itself, please refer to the -/// corresponding function in the C API. -/// -/// -/// THREADING: this class is thread-safe and reentrant after initialized -/// with Init(). -class AudioApi { - public: - /// Creates an (uninitialized) ControllerApi object. You must initialize - /// it by calling Init() before interacting with it. - AudioApi() : context_(nullptr) {} - - ~AudioApi() { - if (context_) { - gvr_audio_destroy(&context_); - } - } - -/// Creates and initializes a gvr_audio_context. -/// For more information, see gvr_audio_create(). -#ifdef __ANDROID__ - bool Init(JNIEnv* env, jobject android_context, jobject class_loader, - AudioRenderingMode rendering_mode) { - context_ = - gvr_audio_create(env, android_context, class_loader, rendering_mode); - return context_ != nullptr; - } -#else - bool Init(AudioRenderingMode rendering_mode) { - context_ = gvr_audio_create(rendering_mode); - return context_ != nullptr; - } -#endif // #ifdef __ANDROID__ - - /// Pauses the audio engine. - /// For more information, see gvr_audio_pause(). - void Pause() { gvr_audio_pause(context_); } - - /// Resumes the audio engine. - /// For more information, see gvr_audio_resume(). - void Resume() { gvr_audio_resume(context_); } - - /// For more information, see gvr_audio_update(). - void Update() { gvr_audio_update(context_); } - - /// Preloads a local sound file. - /// For more information, see gvr_audio_preload_soundfile(). - bool PreloadSoundfile(const std::string& filename) { - return gvr_audio_preload_soundfile(context_, filename.c_str()); - } - - /// Unloads a previously preloaded sample from memory. - /// For more information, see gvr_audio_preload_soundfile(). - void UnloadSoundfile(const std::string& filename) { - gvr_audio_unload_soundfile(context_, filename.c_str()); - } - - /// Returns a new sound object. - /// For more information, see gvr_audio_create_sound_object(). - AudioSourceId CreateSoundObject(const std::string& filename) { - return gvr_audio_create_sound_object(context_, filename.c_str()); - } - - /// Returns a new sound field. - /// For more information, see gvr_audio_create_soundfield(). - AudioSourceId CreateSoundfield(const std::string& filename) { - return gvr_audio_create_soundfield(context_, filename.c_str()); - } - - /// Returns a new stereo sound. - /// For more information, see gvr_audio_create_stereo_sound(). - AudioSourceId CreateStereoSound(const std::string& filename) { - return gvr_audio_create_stereo_sound(context_, filename.c_str()); - } - - /// Starts the playback of a sound. - /// For more information, see gvr_audio_play_sound(). - void PlaySound(AudioSourceId source_id, bool looping_enabled) { - gvr_audio_play_sound(context_, source_id, looping_enabled); - } - - /// Pauses the playback of a sound. - /// For more information, see gvr_audio_pause_sound(). - void PauseSound(AudioSourceId source_id) { - gvr_audio_pause_sound(context_, source_id); - } - - /// Resumes the playback of a sound. - /// For more information, see gvr_audio_resume_sound(). - void ResumeSound(AudioSourceId source_id) { - gvr_audio_resume_sound(context_, source_id); - } - - /// Stops the playback of a sound. - /// For more information, see gvr_audio_stop_sound(). - void StopSound(AudioSourceId source_id) { - gvr_audio_stop_sound(context_, source_id); - } - - /// Checks if a sound is playing. - /// For more information, see gvr_audio_is_sound_playing(). - bool IsSoundPlaying(AudioSourceId source_id) const { - return gvr_audio_is_sound_playing(context_, source_id); - } - - /// Checks if a source is in a valid playable state. - /// For more information, see gvr_audio_is_source_id_valid(). - bool IsSourceIdValid(AudioSourceId source_id) { - return gvr_audio_is_source_id_valid(context_, source_id); - } - - /// Repositions an existing sound object. - /// For more information, see gvr_audio_set_sound_object_position(). - void SetSoundObjectPosition(AudioSourceId sound_object_id, float x, float y, - float z) { - gvr_audio_set_sound_object_position(context_, sound_object_id, x, y, z); - } - - void SetSoundObjectDistanceRolloffModel( - AudioSourceId sound_object_id, - gvr_audio_distance_rolloff_type rolloff_model, float min_distance, - float max_distance) { - gvr_audio_set_sound_object_distance_rolloff_model( - context_, sound_object_id, rolloff_model, min_distance, max_distance); - } - - /// Rotates an existing soundfield. - /// For more information, see gvr_audio_set_soundfield_rotation(). - void SetSoundfieldRotation(AudioSourceId soundfield_id, - const Quatf& soundfield_rotation) { - gvr_audio_set_soundfield_rotation(context_, soundfield_id, - soundfield_rotation); - } - - /// Changes the master volume. - /// For more information, see gvr_audio_set_master_volume(). - void SetMasterVolume(float volume) { - gvr_audio_set_master_volume(context_, volume); - } - - /// Changes the volume of an existing sound. - /// For more information, see gvr_audio_set_sound_volume(). - void SetSoundVolume(AudioSourceId source_id, float volume) { - gvr_audio_set_sound_volume(context_, source_id, volume); - } - - /// Sets the head position from a matrix representation. - /// For more information, see gvr_audio_set_head_pose(). - void SetHeadPose(const Mat4f& head_pose_matrix) { - gvr_audio_set_head_pose(context_, head_pose_matrix); - } - - /// Turns on/off the room reverberation effect. - /// For more information, see gvr_audio_enable_room(). - void EnableRoom(bool enable) { gvr_audio_enable_room(context_, enable); } - - /// Sets the room properties describing the dimensions and surface materials - /// of a given room. For more information, see - /// gvr_audio_set_room_properties(). - void SetRoomProperties(float size_x, float size_y, float size_z, - gvr_audio_material_type wall_material, - gvr_audio_material_type ceiling_material, - gvr_audio_material_type floor_material) { - gvr_audio_set_room_properties(context_, size_x, size_y, size_z, - wall_material, ceiling_material, - floor_material); - } - - /// Adjusts the properties of the current reverb, allowing changes to the - /// reverb's gain, duration and low/high frequency balance. For more - /// information see gvr_audio_set_room_reverb_adjustments(). - void SetRoomReverbAdjustments(float gain, float time_adjust, - float brightness_adjust) { - gvr_audio_set_room_reverb_adjustments(context_, gain, time_adjust, - brightness_adjust); - } - - /// Enables the stereo speaker mode. For more information see - /// gvr_audio_enable_stereo_speaker_mode(). - void EnableStereoSpeakerMode(bool enable) { - gvr_audio_enable_stereo_speaker_mode(context_, enable); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit AudioApi(gvr_audio_context* context) : context_(context) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_audio_context* cobj() { return context_; } - const gvr_audio_context* cobj() const { return context_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_audio_context* Release() { - auto result = context_; - context_ = nullptr; - return result; - } - /// @} - - private: - gvr_audio_context* context_; - - // Disallow copy and assign: - AudioApi(const AudioApi&); - void operator=(const AudioApi&); -}; - -} // namespace gvr -#endif // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#endif // VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h deleted file mode 100644 index 834739301a..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h +++ /dev/null @@ -1,793 +0,0 @@ -/* Copyright 2016 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_ - -#ifdef __ANDROID__ -#include <jni.h> -#endif - -#include <stdint.h> - -#include "vr/gvr/capi/include/gvr.h" -#include "vr/gvr/capi/include/gvr_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// @defgroup Controller Controller API -/// @brief This is the Controller C API, which allows access to a VR controller. -/// -/// If you are writing C++ code, you might prefer to use the C++ wrapper rather -/// than implement this C API directly. -/// -/// Typical initialization example: -/// -/// // Get your gvr_context* pointer from GvrLayout: -/// gvr_context* gvr = ......; // (get from GvrLayout in Java) -/// -/// // Set up the API features: -/// int32_t options = gvr_controller_get_default_options(); -/// -/// // Enable non-default options, if needed: -/// options |= GVR_CONTROLLER_ENABLE_GYRO | GVR_CONTROLLER_ENABLE_ACCEL; -/// -/// // Create and init: -/// gvr_controller_context* context = -/// gvr_controller_create_and_init(options, gvr); -/// -/// // Check if init was successful. -/// if (!context) { -/// // Handle error. -/// return; -/// } -/// -/// gvr_controller_state* state = gvr_controller_state_create(); -/// -/// // Resume: -/// gvr_controller_resume(api); -/// -/// Usage: -/// -/// void DrawFrame() { -/// gvr_controller_state_update(context, 0, state); -/// // ... process controller state ... -/// } -/// -/// // When your application gets paused: -/// void OnPause() { -/// gvr_controller_pause(context); -/// } -/// -/// // When your application gets resumed: -/// void OnResume() { -/// gvr_controller_resume(context); -/// } -/// -/// To conserve battery, be sure to call gvr_controller_pause and -/// gvr_controller_resume when your app gets paused and resumed, respectively. -/// -/// THREADING: unless otherwise noted, all functions are thread-safe, so -/// you can operate on the same gvr_controller_context object from multiple -/// threads. -/// @{ - -/// Represents a Daydream Controller API object, used to invoke the -/// Daydream Controller API. -typedef struct gvr_controller_context_ gvr_controller_context; - -/// Returns the default features for the controller API. -/// -/// @return The set of default features, as bit flags (an OR'ed combination of -/// the GVR_CONTROLLER_ENABLE_* feature flags). -int32_t gvr_controller_get_default_options(); - -/// Creates and initializes a gvr_controller_context instance which can be used -/// to invoke the Daydream Controller API functions. Important: after creation -/// the API will be in the paused state (the controller will be inactive). -/// You must call gvr_controller_resume() explicitly (typically, in your Android -/// app's onResume() callback). -/// -/// @param options The API options. To get the defaults, use -/// gvr_controller_get_default_options(). -/// @param context The GVR Context object to sync with (optional). -/// This can be nullptr. If provided, the context's state will -/// be synchronized with the controller's state where possible. For -/// example, when the user recenters the controller, this will -/// automatically recenter head tracking as well. -/// WARNING: the caller is responsible for making sure the pointer -/// remains valid for the lifetime of this object. -/// @return A pointer to the initialized API, or NULL if an error occurs. -gvr_controller_context* gvr_controller_create_and_init( - int32_t options, gvr_context* context); - -#ifdef __ANDROID__ -/// Creates and initializes a gvr_controller_context instance with an explicit -/// Android context and class loader. -/// -/// @param env The JNI Env associated with the current thread. -/// @param android_context The Android application context. This must be the -/// application context, NOT an Activity context (Note: from any Android -/// Activity in your app, you can call getApplicationContext() to -/// retrieve the application context). -/// @param class_loader The class loader to use when loading Java -/// classes. This must be your app's main class loader (usually -/// accessible through activity.getClassLoader() on any of your Activities). -/// @param options The API options. To get the defaults, use -/// gvr_controller_get_default_options(). -/// @param context The GVR Context object to sync with (optional). -/// This can be nullptr. If provided, the context's state will -/// be synchronized with the controller's state where possible. For -/// example, when the user recenters the controller, this will -/// automatically recenter head tracking as well. -/// WARNING: the caller is responsible for making sure the pointer -/// remains valid for the lifetime of this object. -/// @return A pointer to the initialized API, or NULL if an error occurs. -gvr_controller_context* gvr_controller_create_and_init_android( - JNIEnv *env, jobject android_context, jobject class_loader, - int32_t options, gvr_context* context); -#endif // #ifdef __ANDROID__ - -/// Destroys a gvr_controller_context that was previously created with -/// gvr_controller_init. -/// -/// @param api Pointer to a pointer to a gvr_controller_context. The pointer -/// will be set to NULL after destruction. -void gvr_controller_destroy(gvr_controller_context** api); - -/// Pauses the controller, possibly releasing resources. -/// Call this when your app/game loses focus. -/// Calling this when already paused is a no-op. -/// Thread-safe (call from any thread). -/// -/// @param api Pointer to a pointer to a gvr_controller_context. -void gvr_controller_pause(gvr_controller_context* api); - -/// Resumes the controller. Call this when your app/game regains focus. -/// Calling this when already resumed is a no-op. -/// Thread-safe (call from any thread). -/// -/// @param api Pointer to a pointer to a gvr_controller_context. -void gvr_controller_resume(gvr_controller_context* api); - -/// Convenience to convert an API status code to string. The returned pointer -/// is static and valid throughout the lifetime of the application. -/// -/// @param status The gvr_controller_api_status to convert to string. -/// @return A pointer to a string that describes the value. -const char* gvr_controller_api_status_to_string(int32_t status); - -/// Convenience to convert an connection state to string. The returned pointer -/// is static and valid throughout the lifetime of the application. -/// -/// @param state The state to convert to string. -/// @return A pointer to a string that describes the value. -const char* gvr_controller_connection_state_to_string(int32_t state); - -/// Convenience to convert an connection state to string. The returned pointer -/// is static and valid throughout the lifetime of the application. -/// -/// @param button The gvr_controller_button to convert to string. -/// @return A pointer to a string that describes the value. -const char* gvr_controller_button_to_string(int32_t button); - -/// Creates a gvr_controller_state. -gvr_controller_state* gvr_controller_state_create(); - -/// Destroys a a gvr_controller_state that was previously created with -/// gvr_controller_state_create. -void gvr_controller_state_destroy(gvr_controller_state** state); - -/// Updates the controller state. Reading the controller state is not a -/// const getter: it has side-effects. In particular, some of the -/// gvr_controller_state fields (the ones documented as "transient") represent -/// one-time events and will be true for only one read operation, and false -/// in subsequente reads. -/// -/// @param api Pointer to a pointer to a gvr_controller_context. -/// @param flags Optional flags reserved for future use. A value of 0 should be -/// used until corresponding flag attributes are defined and documented. -/// @param out_state A pointer where the controller's state -/// is to be written. This must have been allocated with -/// gvr_controller_state_create(). -void gvr_controller_state_update(gvr_controller_context* api, int32_t flags, - gvr_controller_state* out_state); - -/// Gets the API status of the controller state. Returns one of the -/// gvr_controller_api_status variants, but returned as an int32_t for ABI -/// compatibility. -int32_t gvr_controller_state_get_api_status(const gvr_controller_state* state); - -/// Gets the connection state of the controller. Returns one of the -/// gvr_controller_connection_state variants, but returned as an int32_t for ABI -/// compatibility. -int32_t gvr_controller_state_get_connection_state( - const gvr_controller_state* state); - -/// Returns the current controller orientation, in Start Space. The Start Space -/// is the same space as the headset space and has these three axes -/// (right-handed): -/// -/// * The positive X axis points to the right. -/// * The positive Y axis points upwards. -/// * The positive Z axis points backwards. -/// -/// The definition of "backwards" and "to the right" are based on the position -/// of the controller when tracking started. For Daydream, this is when the -/// controller was first connected in the "Connect your Controller" screen -/// which is shown when the user enters VR. -/// -/// The definition of "upwards" is given by gravity (away from the pull of -/// gravity). This API may not work in environments without gravity, such -/// as space stations or near the center of the Earth. -/// -/// Since the coordinate system is right-handed, rotations are given by the -/// right-hand rule. For example, rotating the controller counter-clockwise -/// on a table top as seen from above means a positive rotation about the -/// Y axis, while clockwise would mean negative. -/// -/// Note that this is the Start Space for the *controller*, which initially -/// coincides with the Start Space for the headset, but they may diverge over -/// time due to controller/headset drift. A recentering operation will bring -/// the two spaces back into sync. -/// -/// Remember that a quaternion expresses a rotation. Given a rotation of theta -/// radians about the (x, y, z) axis, the corresponding quaternion (in -/// xyzw order) is: -/// -/// (x * sin(theta/2), y * sin(theta/2), z * sin(theta/2), cos(theta/2)) -/// -/// Here are some examples of orientations of the controller and their -/// corresponding quaternions, all given in xyzw order: -/// -/// * Initial pose, pointing forward and lying flat on a surface: identity -/// quaternion (0, 0, 0, 1). Corresponds to "no rotation". -/// -/// * Flat on table, rotated 90 degrees counter-clockwise: (0, 0.7071, 0, -/// 0.7071). Corresponds to a +90 degree rotation about the Y axis. -/// -/// * Flat on table, rotated 90 degrees clockwise: (0, -0.7071, 0, 0.7071). -/// Corresponds to a -90 degree rotation about the Y axis. -/// -/// * Flat on table, rotated 180 degrees (pointing backwards): (0, 1, 0, 0). -/// Corresponds to a 180 degree rotation about the Y axis. -/// -/// * Pointing straight up towards the sky: (0.7071, 0, 0, 0.7071). -/// Corresponds to a +90 degree rotation about the X axis. -/// -/// * Pointing straight down towards the ground: (-0.7071, 0, 0, 0.7071). -/// Corresponds to a -90 degree rotation about the X axis. -/// -/// * Banked 90 degrees to the left: (0, 0, 0.7071, 0.7071). Corresponds -/// to a +90 degree rotation about the Z axis. -/// -/// * Banked 90 degrees to the right: (0, 0, -0.7071, 0.7071). Corresponds -/// to a -90 degree rotation about the Z axis. -gvr_quatf gvr_controller_state_get_orientation( - const gvr_controller_state* state); - -/// Returns the current controller gyro reading, in Start Space. -/// -/// The gyro measures the controller's angular speed in radians per second. -/// Note that this is an angular *speed*, so it reflects how fast the -/// controller's orientation is changing with time. -/// In particular, if the controller is not being rotated, the angular speed -/// will be zero on all axes, regardless of the current pose. -/// -/// The axes are in the controller's device space. Specifically: -/// -/// * The X axis points to the right of the controller. -/// * The Y axis points upwards perpendicular to the top surface of the -/// controller. -/// * The Z axis points backwards along the body of the controller, -/// towards its rear, where the charging port is. -/// -/// As usual in a right-handed coordinate system, the sign of the angular -/// velocity is given by the right-hand rule. So, for example: -/// -/// * If the controller is flat on a table top spinning counter-clockwise -/// as seen from above, you will read a positive angular velocity -/// about the Y axis. Clockwise would be negative. -/// * If the controller is initially pointing forward and lying flat and -/// is then gradually angled up so that its tip points towards the sky, -/// it will report a positive angular velocity about the X axis during -/// that motion. Likewise, angling it down will report a negative angular -/// velocity about the X axis. -/// * If the controller is banked (rolled) to the right, this will -/// report a negative angular velocity about the Z axis during the -/// motion (remember the Z axis points backwards along the controller). -/// Banking to the left will report a positive angular velocity about -/// the Z axis. -gvr_vec3f gvr_controller_state_get_gyro(const gvr_controller_state* state); - -/// Current (latest) controller accelerometer reading, in Start Space. -/// -/// The accelerometer indicates the direction in which the controller feels -/// an acceleration, including gravity. The reading is given in meters -/// per second squared (m/s^2). The axes are the same as for the gyro. -/// To have an intuition for the signs used in the accelerometer, it is useful -/// to imagine that, when at rest, the controller is being "pushed" by a -/// force opposite to gravity. It is as if, by the equivalency princle, it were -/// on a frame of reference that is accelerating in the opposite direction to -/// gravity. For example: -/// -/// * If the controller is lying flat on a table top, it will read a positive -/// acceleration of about 9.8 m/s^2 along the Y axis, corresponding to -/// the acceleration of gravity (as if the table were pushing the controller -/// upwards at 9.8 m/s^2 to counteract gravity). -/// * If, in that situation, the controller is now accelerated upwards at -/// 3.0 m/s^2, then the reading will be 12.8 m/s^2 along the Y axis, -/// since the controller will now feel a stronger acceleration corresponding -/// to the 9.8 m/s^2 plus the upwards push of 3.0 m/s^2. -/// * If, the controller is accelerated downwards at 5.0 m/s^2, then the -/// reading will now be 4.8 m/s^2 along the Y axis, since the controller -/// will now feel a weaker acceleration (as the acceleration is giving in -/// to gravity). -/// * If you were to give in to gravity completely, letting the controller -/// free fall towards the ground, it will read 0 on all axes, as there -/// will be no force acting on the controller. (Please do not put your -/// controller in a free-fall situation. This is just a theoretical -/// example.) -gvr_vec3f gvr_controller_state_get_accel(const gvr_controller_state* state); - -/// Returns whether the user is touching the touchpad. -bool gvr_controller_state_is_touching(const gvr_controller_state* state); - -/// If the user is touching the touchpad, this returns the touch position in -/// normalized coordinates, where (0,0) is the top-left of the touchpad -/// and (1,1) is the bottom right. If the user is not touching the touchpad, -/// then this is the position of the last touch. -gvr_vec2f gvr_controller_state_get_touch_pos(const gvr_controller_state* state); - -/// Returns true if user just started touching touchpad (this is a transient -/// event: -/// it is true for only one frame after the event). -bool gvr_controller_state_get_touch_down(const gvr_controller_state* state); - -/// Returns true if user just stopped touching touchpad (this is a transient -/// event: -/// it is true for only one frame after the event). -bool gvr_controller_state_get_touch_up(const gvr_controller_state* state); - -/// Returns true if a recenter operation just ended (this is a transient event: -/// it is true only for one frame after the recenter ended). If this is -/// true then the `orientation` field is already relative to the new center. -bool gvr_controller_state_get_recentered(const gvr_controller_state* state); - -/// Returns whether the recenter flow is currently in progress. -/// -/// @deprecated Use gvr_controller_state_get_recentered instead. -bool gvr_controller_state_get_recentering(const gvr_controller_state* state); - -/// Returns whether the given button is currently pressed. -bool gvr_controller_state_get_button_state(const gvr_controller_state* state, - - int32_t button); - -/// Returns whether the given button was just pressed (transient). -bool gvr_controller_state_get_button_down(const gvr_controller_state* state, - int32_t button); - -/// Returns whether the given button was just released (transient). -bool gvr_controller_state_get_button_up(const gvr_controller_state* state, - int32_t button); - -/// Returns the timestamp (nanos) when the last orientation event was received. -int64_t gvr_controller_state_get_last_orientation_timestamp( - const gvr_controller_state* state); - -/// Returns the timestamp (nanos) when the last gyro event was received. -int64_t gvr_controller_state_get_last_gyro_timestamp( - const gvr_controller_state* state); - -/// Returns the timestamp (nanos) when the last accelerometer event was -/// received. -int64_t gvr_controller_state_get_last_accel_timestamp( - const gvr_controller_state* state); - -/// Returns the timestamp (nanos) when the last touch event was received. -int64_t gvr_controller_state_get_last_touch_timestamp( - const gvr_controller_state* state); - -/// Returns the timestamp (nanos) when the last button event was received. -int64_t gvr_controller_state_get_last_button_timestamp( - const gvr_controller_state* state); - -// Current (latest) controller simulated position for use with an elbow model. -gvr_vec3f gvr_controller_state_get_position(const gvr_controller_state* state); - -// Returns the timestamp (nanos) when the last position event was received. -int64_t gvr_controller_state_get_last_position_timestamp( - const gvr_controller_state* state); - -/// Returns whether the controller battery is currently charging. -/// This may not be real time information and may be slow to be updated. -bool gvr_controller_state_get_battery_charging( - const gvr_controller_state* state); - -/// Returns the bucketed controller battery level. -/// Note this is a gvr_controller_battery_level and not a percent. -int32_t gvr_controller_state_get_battery_level( - const gvr_controller_state* state); - -/// Returns the timestamp (nanos) when the last battery event was received. -int64_t gvr_controller_state_get_last_battery_timestamp( - const gvr_controller_state* state); - -/// Convenience to convert a battery level to string. The returned pointer -/// is static and valid throughout the lifetime of the application. -/// -/// @param level The gvr_controller_battery_level to convert to string. -/// @return A pointer to a string that describes the value. -const char* gvr_controller_battery_level_to_string(int32_t level); - -/// @} - -#ifdef __cplusplus -} // extern "C" -#endif - - -// Convenience C++ wrapper. -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#include <memory> - -namespace gvr { -/// This is a convenience C++ wrapper for the Controller C API. -/// -/// This wrapper strategy prevents ABI compatibility issues between compilers -/// by ensuring that the interface between client code and the implementation -/// code in libgvr.so is a pure C interface. The translation from C++ calls -/// to C calls provided by this wrapper runs entirely in the client's binary -/// and is compiled by the client's compiler. -/// -/// Methods in this class are only documented insofar as the C++ wrapping logic -/// is concerned; for information about the method itself, please refer to the -/// corresponding function in the C API. -/// -/// Typical C++ initialization example: -/// -/// std::unique_ptr<ControllerApi> controller_api(new ControllerApi); -/// -/// // Your GVR context pointer (which can be obtained from GvrLayout) -/// gvr_context* context = .....; // (get it from GvrLayout) -/// -/// // Set up the options: -/// int32_t options = ControllerApi::DefaultOptions(); -/// -/// // Enable non-default options, if you need them: -/// options |= GVR_CONTROLLER_ENABLE_GYRO; -/// -/// // Init the ControllerApi object: -/// bool success = controller_api->Init(options, context); -/// if (!success) { -/// // Handle failure. -/// // Do NOT call other methods (like Resume, etc) if init failed. -/// return; -/// } -/// -/// // Resume the ControllerApi (if your app is on the foreground). -/// controller_api->Resume(); -/// -/// ControllerState state; -/// -/// Usage example: -/// -/// void DrawFrame() { -/// state.Update(*controller_api); -/// // ... process controller state ... -/// } -/// -/// // When your application gets paused: -/// void OnPause() { -/// controller_api->Pause(); -/// } -/// -/// // When your application gets resumed: -/// void OnResume() { -/// controller_api->Resume(); -/// } -/// -/// To conserve battery, be sure to call Pause() and Resume() when your app -/// gets paused and resumed, respectively. This will allow the underlying -/// logic to unbind from the VR service and let the controller sleep when -/// no apps are using it. -/// -/// THREADING: this class is thread-safe and reentrant after initialized -/// with Init(). -class ControllerApi { - public: - /// Creates an (uninitialized) ControllerApi object. You must initialize - /// it by calling Init() before interacting with it. - ControllerApi() : context_(nullptr) {} - - /// Returns the default controller options. - static int32_t DefaultOptions() { - return gvr_controller_get_default_options(); - } - - // Deprecated factory-style create method. - // TODO(btco): remove this once no one is using it. - static std::unique_ptr<ControllerApi> Create() { - return std::unique_ptr<ControllerApi>(new ControllerApi); - } - - /// Initializes the controller API. - /// - /// This method must be called exactly once in the lifetime of this object. - /// Other methods in this class may only be called after Init() returns true. - /// Note: this does not cause the ControllerApi to be resumed. You must call - /// Resume() explicitly in order to start using the controller. - /// - /// For more information see gvr_controller_create_and_init(). - /// - /// @return True if initialization was successful, false if it failed. - /// Initialization may fail, for example, because invalid options were - /// supplied. - bool Init(int32_t options, gvr_context* context) { - context_ = gvr_controller_create_and_init(options, context); - return context_ != nullptr; - } - -#ifdef __ANDROID__ - /// Overload of Init() with explicit Android context and class loader - /// (for Android only). For more information, see: - /// gvr_controller_create_and_init_android(). - bool Init(JNIEnv *env, jobject android_context, jobject class_loader, - int32_t options, gvr_context* context) { - context_ = gvr_controller_create_and_init_android( - env, android_context, class_loader, options, context); - return context_ != nullptr; - } -#endif // #ifdef __ANDROID__ - - /// Convenience overload that calls Init without a gvr_context. - // TODO(btco): remove once it is no longer being used. - bool Init(int32_t options) { - return Init(options, nullptr); - } - - /// Pauses the controller. - /// For more information, see gvr_controller_pause(). - void Pause() { - gvr_controller_pause(context_); - } - - /// Resumes the controller. - /// For more information, see gvr_controller_resume(). - void Resume() { - gvr_controller_resume(context_); - } - - /// Destroys this ControllerApi instance. - ~ControllerApi() { - if (context_) gvr_controller_destroy(&context_); - } - - /// Convenience functions to convert enums to strings. - /// For more information, see the corresponding functions in the C API. - static const char* ToString(ControllerApiStatus status) { - return gvr_controller_api_status_to_string(status); - } - - static const char* ToString(ControllerConnectionState state) { - return gvr_controller_connection_state_to_string(state); - } - - static const char* ToString(ControllerButton button) { - return gvr_controller_button_to_string(button); - } - - static const char* ToString(ControllerBatteryLevel level) { - return gvr_controller_battery_level_to_string(level); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit ControllerApi(gvr_controller_context* context) - : context_(context) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_controller_context* cobj() { return context_; } - const gvr_controller_context* cobj() const { return context_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_controller_context* release() { - auto result = context_; - context_ = nullptr; - return result; - } - /// @} - - protected: - gvr_controller_context* context_; - - private: - friend class ControllerState; - - // Disallow copy and assign: - ControllerApi(const ControllerApi&); - void operator=(const ControllerApi&); -}; - -/// Convenience C++ wrapper for the opaque gvr_controller_state type. See the -/// gvr_controller_state functions for more information. -class ControllerState { - public: - ControllerState() : state_(gvr_controller_state_create()) {} - - ~ControllerState() { - if (state_) gvr_controller_state_destroy(&state_); - } - - /// For more information, see gvr_controller_state_update(). - void Update(const ControllerApi& api) { - gvr_controller_state_update(api.context_, 0, state_); - } - - /// For more information, see gvr_controller_state_update(). - void Update(const ControllerApi& api, int32_t flags) { - gvr_controller_state_update(api.context_, flags, state_); - } - - /// For more information, see gvr_controller_state_get_api_status(). - ControllerApiStatus GetApiStatus() const { - return static_cast<ControllerApiStatus>( - gvr_controller_state_get_api_status(state_)); - } - - /// For more information, see gvr_controller_state_get_connection_state(). - ControllerConnectionState GetConnectionState() const { - return static_cast<ControllerConnectionState>( - gvr_controller_state_get_connection_state(state_)); - } - - /// For more information, see gvr_controller_state_get_orientation(). - gvr_quatf GetOrientation() const { - return gvr_controller_state_get_orientation(state_); - } - - /// For more information, see gvr_controller_state_get_gyro(). - gvr_vec3f GetGyro() const { return gvr_controller_state_get_gyro(state_); } - - /// For more information, see gvr_controller_state_get_accel(). - gvr_vec3f GetAccel() const { return gvr_controller_state_get_accel(state_); } - - /// For more information, see gvr_controller_state_is_touching(). - bool IsTouching() const { return gvr_controller_state_is_touching(state_); } - - /// For more information, see gvr_controller_state_get_touch_pos(). - gvr_vec2f GetTouchPos() const { - return gvr_controller_state_get_touch_pos(state_); - } - - /// For more information, see gvr_controller_state_get_touch_down(). - bool GetTouchDown() const { - return gvr_controller_state_get_touch_down(state_); - } - - /// For more information, see gvr_controller_state_get_touch_up(). - bool GetTouchUp() const { return gvr_controller_state_get_touch_up(state_); } - - /// For more information, see gvr_controller_state_get_recentered(). - bool GetRecentered() const { - return gvr_controller_state_get_recentered(state_); - } - - /// For more information, see gvr_controller_state_get_recentering(). - bool GetRecentering() const { - return gvr_controller_state_get_recentering(state_); - } - - /// For more information, see gvr_controller_state_get_button_state(). - bool GetButtonState(ControllerButton button) const { - return gvr_controller_state_get_button_state(state_, button); - } - - /// For more information, see gvr_controller_state_get_button_down(). - bool GetButtonDown(ControllerButton button) const { - return gvr_controller_state_get_button_down(state_, button); - } - - /// For more information, see gvr_controller_state_get_button_up(). - bool GetButtonUp(ControllerButton button) const { - return gvr_controller_state_get_button_up(state_, button); - } - - /// For more information, see - /// gvr_controller_state_get_last_orientation_timestamp(). - int64_t GetLastOrientationTimestamp() const { - return gvr_controller_state_get_last_orientation_timestamp(state_); - } - - /// For more information, see gvr_controller_state_get_last_gyro_timestamp(). - int64_t GetLastGyroTimestamp() const { - return gvr_controller_state_get_last_gyro_timestamp(state_); - } - - /// For more information, see gvr_controller_state_get_last_accel_timestamp(). - int64_t GetLastAccelTimestamp() const { - return gvr_controller_state_get_last_accel_timestamp(state_); - } - - /// For more information, see gvr_controller_state_get_last_touch_timestamp(). - int64_t GetLastTouchTimestamp() const { - return gvr_controller_state_get_last_touch_timestamp(state_); - } - - /// For more information, see - /// gvr_controller_state_get_last_button_timestamp(). - int64_t GetLastButtonTimestamp() const { - return gvr_controller_state_get_last_button_timestamp(state_); - } - - /// For more information, see gvr_controller_state_get_position(). - gvr_vec3f GetPosition() const { - return gvr_controller_state_get_position(state_); - } - - /// For more information, see - /// gvr_controller_state_get_last_position_timestamp(). - int64_t GetLastPositionTimestamp() const { - return gvr_controller_state_get_last_position_timestamp(state_); - } - - /// For more information, see gvr_controller_state_get_battery_charging - bool GetBatteryCharging() const { - return gvr_controller_state_get_battery_charging(state_); - } - - /// For more information, see gvr_controller_state_get_battery_level - ControllerBatteryLevel GetBatteryLevel() const { - return static_cast<ControllerBatteryLevel>( - gvr_controller_state_get_battery_level(state_)); - } - - /// For more information, see gvr_controller_state_get_last_battery_timestamp - int64_t GetLastBatteryTimestamp() const { - return gvr_controller_state_get_last_battery_timestamp(state_); - } - - /// @name Wrapper manipulation - /// @{ - /// Creates a C++ wrapper for a C object and takes ownership. - explicit ControllerState(gvr_controller_state* state) : state_(state) {} - - /// Returns the wrapped C object. Does not affect ownership. - gvr_controller_state* cobj() { return state_; } - const gvr_controller_state* cobj() const { return state_; } - - /// Returns the wrapped C object and transfers its ownership to the caller. - /// The wrapper becomes invalid and should not be used. - gvr_controller_state* release() { - auto result = state_; - state_ = nullptr; - return result; - } - /// @} - - private: - gvr_controller_state* state_; -}; - -} // namespace gvr -#endif // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#endif // VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h deleted file mode 100644 index cf81b51c8a..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h +++ /dev/null @@ -1,658 +0,0 @@ -/* Copyright 2016 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_ -#define VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_ - -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/// @defgroup types Google VR Types -/// @brief Various types used in the Google VR NDK. -/// @{ - -/// Primary context for invoking Google VR APIs. -typedef struct gvr_context_ gvr_context; - -/// An enum for the left and right eye. -typedef enum { - GVR_LEFT_EYE = 0, - GVR_RIGHT_EYE, - GVR_NUM_EYES -} gvr_eye; - -/// The type of VR viewer. -typedef enum { - /// A Cardboard-compatible viewer. A typical Cardboard viewer supports a - /// simple touchscreen-based trigger input mechanism. On most platforms, this - // is the default viewer type if no viewer has been explicitly paired. - GVR_VIEWER_TYPE_CARDBOARD = 0, - /// A Daydream-compatible viewer. A typical Daydream viewer supports 3DOF - /// controller input (as defined in gvr_controller.h), and is intended only - /// for Daydream-ready platforms. It does *not* support touchscreen-based - /// input unless Cardboard emulation is explicitly enabled. - GVR_VIEWER_TYPE_DAYDREAM = 1, -} gvr_viewer_type; - -// Types of VR-specific features which may or may not be supported on the -// underlying platform. -typedef enum { - // Asynchronous reprojection warps the app's rendered frame using the most - // recent head pose just before pushing the frame to the display. - GVR_FEATURE_ASYNC_REPROJECTION = 0, -} gvr_feature; - -/// @} - -/// Version information for the Google VR API. -typedef struct gvr_version_ { - int32_t major; - int32_t minor; - int32_t patch; -} gvr_version; - -/// An integral 2D size. Used for render target sizes. -typedef struct gvr_sizei { - int32_t width; - int32_t height; -} gvr_sizei; - -/// An integral 2D rect. Used for window bounds in pixels. -typedef struct gvr_recti { - int32_t left; - int32_t right; - int32_t bottom; - int32_t top; -} gvr_recti; - -/// A floating point 2D rect. Used for field of view, and also for ranges -/// in texture space. When used for a field of view, all angles are in positive -/// degrees from the optical axis. -typedef struct gvr_rectf { - float left; - float right; - float bottom; - float top; -} gvr_rectf; - -/// A floating point 2D vector. -typedef struct gvr_vec2f { - float x; - float y; -} gvr_vec2f; - -/// A floating point 3D vector. -typedef struct gvr_vec3f { - float x; - float y; - float z; -} gvr_vec3f; - -/// A floating point 4x4 matrix. -typedef struct gvr_mat4f { float m[4][4]; } gvr_mat4f; - -/// A floating point quaternion, in JPL format. -/// We use this simple struct in order not to impose a dependency on a -/// particular math library. The user of this API is free to encapsulate this -/// into any math library they want. -typedef struct gvr_quatf { - /// qx, qy, qz are the vector component. - float qx; - float qy; - float qz; - /// qw is the linelar component. - float qw; -} gvr_quatf; - -/// A *monotonic system time* representation. On Android, this is equivalent to -/// System.nanoTime(), or clock_gettime(CLOCK_MONOTONIC). If there is any doubt -/// about how to get the current time for the current platform, simply use -/// gvr_get_time_point_now(). -typedef struct gvr_clock_time_point { - int64_t monotonic_system_time_nanos; -} gvr_clock_time_point; - -/// A structure that ties together a region of a buffer, the field of view -/// rendered into that region and a target eye index to define part of the -/// user's field of view. The SDK implementation uses this information to -/// transform the images generated by the app output into the final display that -/// is sent to the screen. -/// -/// A set of these structures will most often be generated by the API, via -/// gvr_get_recommended_buffer_viewports() or -/// gvr_get_screen_buffer_viewports(). However, the client may also customize -/// these values via gvr_buffer_viewport_list_set(), constructing a custom -/// gvr_buffer_viewport_list for use in the distortion pass. -typedef struct gvr_buffer_viewport_ gvr_buffer_viewport; - -/// List of buffer viewports that completely specifies how to transform the -/// frame's buffers into the image displayed on the screen. -typedef struct gvr_buffer_viewport_list_ gvr_buffer_viewport_list; - -/// Specification of a pixel buffer. A pixel buffer can have color, depth and -/// stencil attachments and mostly corresponds to the OpenGL concept of a -/// framebuffer object. However, since there can be multiple such objects for -/// each frame, we avoid calling them "framebuffers". Pixel buffers which are -/// part of the currently acquired frame are immutable, i.e., they cannot be -/// resized or otherwise reconfigured. -typedef struct gvr_buffer_spec_ gvr_buffer_spec; - -/// Swap chain that contains some number of frames. Frames in the swap chain -/// can be unused, in the process of being distorted and presented on the -/// screen, or acquired and being rendered to by the application. The swap chain -/// ensures that the most recent available frame is always shown and that the -/// application never has to wait to render the next frame. -typedef struct gvr_swap_chain_ gvr_swap_chain; - -/// A single frame acquired from the swap chain. Each frame is composed of one -/// or more buffers, which are then lens distorted and composited into the final -/// output. Buffers are identified by indices that correspond to the position -/// of their gvr_buffer_spec in the list passed when constructing the swap -/// chain. -typedef struct gvr_frame_ gvr_frame; - -/// @addtogroup types -/// @{ - -/// Constants that represent GVR error codes. -typedef enum { - GVR_ERROR_NONE = 0, - GVR_ERROR_CONTROLLER_CREATE_FAILED = 2, - GVR_ERROR_NO_FRAME_AVAILABLE = 3, -} gvr_error; - -/// Controller API options (bit flags). -enum { - /// Indicates that controller orientation data should be reported. - GVR_CONTROLLER_ENABLE_ORIENTATION = 1 << 0, - /// Indicates that controller touchpad data should be reported. - GVR_CONTROLLER_ENABLE_TOUCH = 1 << 1, - /// Indicates that controller gyroscope data should be reported. - GVR_CONTROLLER_ENABLE_GYRO = 1 << 2, - /// Indicates that controller accelerometer data should be reported. - GVR_CONTROLLER_ENABLE_ACCEL = 1 << 3, - /// Indicates that controller gestures should be reported. - GVR_CONTROLLER_ENABLE_GESTURES = 1 << 4, - /// Indicates that controller pose prediction should be enabled. - GVR_CONTROLLER_ENABLE_POSE_PREDICTION = 1 << 5, - /// Indicates that controller position data should be reported. - GVR_CONTROLLER_ENABLE_POSITION = 1 << 6, - /// Indicates that controller battery data should be reported. - GVR_CONTROLLER_ENABLE_BATTERY = 1 << 7, -}; - -/// Constants that represent the status of the controller API. -typedef enum { - /// API is happy and healthy. This doesn't mean the controller itself - /// is connected, it just means that the underlying service is working - /// properly. - GVR_CONTROLLER_API_OK = 0, - - /// Any other status represents a permanent failure that requires - /// external action to fix: - - /// API failed because this device does not support controllers (API is too - /// low, or other required feature not present). - GVR_CONTROLLER_API_UNSUPPORTED = 1, - /// This app was not authorized to use the service (e.g., missing permissions, - /// the app is blacklisted by the underlying service, etc). - GVR_CONTROLLER_API_NOT_AUTHORIZED = 2, - /// The underlying VR service is not present. - GVR_CONTROLLER_API_UNAVAILABLE = 3, - /// The underlying VR service is too old, needs upgrade. - GVR_CONTROLLER_API_SERVICE_OBSOLETE = 4, - /// The underlying VR service is too new, is incompatible with current client. - GVR_CONTROLLER_API_CLIENT_OBSOLETE = 5, - /// The underlying VR service is malfunctioning. Try again later. - GVR_CONTROLLER_API_MALFUNCTION = 6, -} gvr_controller_api_status; - -/// Constants that represent the state of the controller. -typedef enum { - /// Controller is disconnected. - GVR_CONTROLLER_DISCONNECTED = 0, - /// Controller is scanning. - GVR_CONTROLLER_SCANNING = 1, - /// Controller is connecting. - GVR_CONTROLLER_CONNECTING = 2, - /// Controller is connected. - GVR_CONTROLLER_CONNECTED = 3, -} gvr_controller_connection_state; - -/// Controller buttons. -typedef enum { - GVR_CONTROLLER_BUTTON_NONE = 0, - GVR_CONTROLLER_BUTTON_CLICK = 1, ///< Touchpad Click. - GVR_CONTROLLER_BUTTON_HOME = 2, - GVR_CONTROLLER_BUTTON_APP = 3, - GVR_CONTROLLER_BUTTON_VOLUME_UP = 4, - GVR_CONTROLLER_BUTTON_VOLUME_DOWN = 5, - - /// Note: there are 5 buttons on the controller, but the state arrays have - /// this many elements due to the inclusion of a dummy "none" button. - GVR_CONTROLLER_BUTTON_COUNT = 6, -} gvr_controller_button; - -/// Controller battery states. -typedef enum { - GVR_CONTROLLER_BATTERY_LEVEL_UNKNOWN = 0, - GVR_CONTROLLER_BATTERY_LEVEL_CRITICAL_LOW = 1, - GVR_CONTROLLER_BATTERY_LEVEL_LOW = 2, - GVR_CONTROLLER_BATTERY_LEVEL_MEDIUM = 3, - GVR_CONTROLLER_BATTERY_LEVEL_ALMOST_FULL = 4, - GVR_CONTROLLER_BATTERY_LEVEL_FULL = 5, - - /// Note: there are 5 distinct levels, but there are 6 due to the inclusion - /// of an UNKNOWN state before any battery information is collected, etc. - GVR_CONTROLLER_BATTERY_LEVEL_COUNT = 6, -} gvr_controller_battery_level; - - -/// @} - -/// Opaque handle to controller state. -typedef struct gvr_controller_state_ gvr_controller_state; - -/// @addtogroup types -/// @{ - -/// Rendering modes define CPU load / rendering quality balances. -typedef enum { - /// Stereo panning of all Sound Objects. This disables HRTF-based rendering. - GVR_AUDIO_RENDERING_STEREO_PANNING = 0, - /// HRTF-based rendering over a virtual array of 8 loudspeakers arranged in - /// a cube configuration around the listener’s head. - GVR_AUDIO_RENDERING_BINAURAL_LOW_QUALITY = 1, - /// HRTF-based rendering over a virtual array of 16 loudspeakers arranged in - /// an approximate equidistribution about the around the listener’s head. - GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY = 2, -} gvr_audio_rendering_mode; - -/// Room surface material names, used to set room properties. -typedef enum { - /// Acoustically transparent material, reflects no sound. - GVR_AUDIO_MATERIAL_TRANSPARENT = 0, - /// Acoustic ceiling tiles, absorbs most frequencies. - GVR_AUDIO_MATERIAL_ACOUSTIC_CEILING_TILES = 1, - /// Bare brick, relatively reflective. - GVR_AUDIO_MATERIAL_BRICK_BARE = 2, - /// Painted brick - GVR_AUDIO_MATERIAL_BRICK_PAINTED = 3, - /// Coarse surface concrete block. - GVR_AUDIO_MATERIAL_CONCRETE_BLOCK_COARSE = 4, - /// Painted concrete block. - GVR_AUDIO_MATERIAL_CONCRETE_BLOCK_PAINTED = 5, - /// Heavy curtains. - GVR_AUDIO_MATERIAL_CURTAIN_HEAVY = 6, - /// Fiber glass insulation. - GVR_AUDIO_MATERIAL_FIBER_GLASS_INSULATION = 7, - /// Thin glass. - GVR_AUDIO_MATERIAL_GLASS_THIN = 8, - /// Thick glass. - GVR_AUDIO_MATERIAL_GLASS_THICK = 9, - /// Grass. - GVR_AUDIO_MATERIAL_GRASS = 10, - /// Linoleum on concrete. - GVR_AUDIO_MATERIAL_LINOLEUM_ON_CONCRETE = 11, - /// Marble. - GVR_AUDIO_MATERIAL_MARBLE = 12, - /// Galvanized sheet metal. - GVR_AUDIO_MATERIAL_METAL = 13, - /// Wooden parquet on concrete. - GVR_AUDIO_MATERIAL_PARQUET_ON_CONCRETE = 14, - /// Rough plaster surface. - GVR_AUDIO_MATERIAL_PLASTER_ROUGH = 15, - /// Smooth plaster surface. - GVR_AUDIO_MATERIAL_PLASTER_SMOOTH = 16, - /// Plywood panel. - GVR_AUDIO_MATERIAL_PLYWOOD_PANEL = 17, - /// Polished concrete OR tile surface. - GVR_AUDIO_MATERIAL_POLISHED_CONCRETE_OR_TILE = 18, - /// Sheet rock. - GVR_AUDIO_MATERIAL_SHEET_ROCK = 19, - /// Surface of water or ice. - GVR_AUDIO_MATERIAL_WATER_OR_ICE_SURFACE = 20, - /// Wooden ceiling. - GVR_AUDIO_MATERIAL_WOOD_CEILING = 21, - /// Wood paneling. - GVR_AUDIO_MATERIAL_WOOD_PANEL = 22, -} gvr_audio_material_type; - -/// Distance rolloff models used for distance attenuation. -typedef enum { - /// Logarithmic distance rolloff model. - GVR_AUDIO_ROLLOFF_LOGARITHMIC = 0, - /// Linear distance rolloff model. - GVR_AUDIO_ROLLOFF_LINEAR = 1, - /// No distance attenuation will be applied. - GVR_AUDIO_ROLLOFF_NONE = 2, -} gvr_audio_distance_rolloff_type; - -/// Sound object and sound field identifier. -typedef int32_t gvr_audio_source_id; - -/// Supported surround sound formats. -typedef enum { - // Enables to initialize a yet undefined rendering mode. - GVR_AUDIO_SURROUND_FORMAT_INVALID = 0, - - // Virtual stereo speakers at -30 degrees and +30 degrees. - GVR_AUDIO_SURROUND_FORMAT_SURROUND_STEREO = 1, - - // 5.1 surround sound according to the ITU-R BS 775 speaker configuration - // recommendation: - // - Front left (FL) at 30 degrees. - // - Front right (FR) at -30 degrees. - // - Front center (FC) at 0 degrees. - // - Low frequency effects (LFE) at front center at 0 degrees. - // - Left side (LS) at 110 degrees. - // - Right side (RS) at -110 degrees. - // - // The 5.1 channel input layout must matches AAC: FL, FR, FC, LFE, LS, RS. - // Note that this differs from the Vorbis/Opus 5.1 channel layout, which - // is: FL, FC, FR, LS, RS, LFE. - GVR_AUDIO_SURROUND_FORMAT_SURROUND_FIVE_DOT_ONE = 2, - - // First-order ambisonics (AmbiX format: 4 channels, ACN channel ordering, - // SN3D normalization). - GVR_AUDIO_SURROUND_FORMAT_FIRST_ORDER_AMBISONICS = 3, - - // Second-order ambisonics (AmbiX format: 9 channels, ACN channel ordering, - // SN3D normalization). - GVR_AUDIO_SURROUND_FORMAT_SECOND_ORDER_AMBISONICS = 4, - - // Third-order ambisonics (AmbiX format: 16 channels, ACN channel ordering, - // SN3D normalization). - GVR_AUDIO_SURROUND_FORMAT_THIRD_ORDER_AMBISONICS = 5, -} gvr_audio_surround_format_type; - -/// Valid color formats for swap chain buffers. -typedef enum { - /// Equivalent to GL_RGBA8 - GVR_COLOR_FORMAT_RGBA_8888 = 0, - /// Equivalent to GL_RGB565 - GVR_COLOR_FORMAT_RGB_565 = 1, -} gvr_color_format_type; - -typedef enum { - /// No depth or stencil buffer. - GVR_DEPTH_STENCIL_FORMAT_NONE = 255, - /// Equivalent to GL_DEPTH_COMPONENT16. - GVR_DEPTH_STENCIL_FORMAT_DEPTH_16 = 0, - /// Equivalent to GL_DEPTH_COMPONENT24. - GVR_DEPTH_STENCIL_FORMAT_DEPTH_24 = 1, - /// Equivlaent to GL_DEPTH24_STENCIL8. - GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8 = 2, - /// Equivalent to GL_DEPTH_COMPONENT32F. - GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F = 3, - /// Equivalent to GL_DEPTH_32F_STENCIL8. - GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8 = 4, - /// Equivalent to GL_STENCIL8. - GVR_DEPTH_STENCIL_FORMAT_STENCIL_8 = 5, -} gvr_depth_stencil_format_type; - -/// Types of asynchronous reprojection. -typedef enum { - /// Do not reproject. - GVR_REPROJECTION_NONE = 0, - /// Reproject in all dimensions. - GVR_REPROJECTION_FULL = 1, -} gvr_reprojection; - -typedef enum { - GVR_CONTROLLER_RIGHT_HANDED = 0, - GVR_CONTROLLER_LEFT_HANDED = 1, -} gvr_controller_handedness; - -typedef struct gvr_user_prefs_ gvr_user_prefs; - -// Anonymous enum for miscellaneous integer constants. -enum { - /// Constant that represents a nonexistent external surface. Pass to - /// gvr_buffer_viewport_set_external_surface_id() to disable sampling from - /// an external surface. - GVR_EXTERNAL_SURFACE_ID_NONE = -1, - /// Special index for a source buffer that has the same contents as the - /// external surface attached to the given viewport. Pass this to - /// gvr_buffer_viewport_set_source_buffer_index() to use the external surface - /// as the buffer contents. - GVR_BUFFER_INDEX_EXTERNAL_SURFACE = -1, -}; - -/// @} - -#ifdef __cplusplus -} // extern "C" -#endif - -#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) -// These typedefs convert the C-style names to C++-style names. - -namespace gvr { - -const int32_t kControllerEnableOrientation = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_ORIENTATION); -const int32_t kControllerEnableTouch = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_TOUCH); -const int32_t kControllerEnableGyro = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_GYRO); -const int32_t kControllerEnableAccel = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_ACCEL); -const int32_t kControllerEnableGestures = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_GESTURES); -const int32_t kControllerEnablePosePrediction = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_POSE_PREDICTION); -const int32_t kControllerEnablePosition = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_POSITION); -const int32_t kControllerEnableBattery = - static_cast<int32_t>(GVR_CONTROLLER_ENABLE_BATTERY); - -typedef gvr_controller_api_status ControllerApiStatus; -const ControllerApiStatus kControllerApiOk = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_OK); -const ControllerApiStatus kControllerApiUnsupported = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_UNSUPPORTED); -const ControllerApiStatus kControllerApiNotAuthorized = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_NOT_AUTHORIZED); -const ControllerApiStatus kControllerApiUnavailable = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_UNAVAILABLE); -const ControllerApiStatus kControllerApiServiceObsolete = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_SERVICE_OBSOLETE); -const ControllerApiStatus kControllerApiClientObsolete = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_CLIENT_OBSOLETE); -const ControllerApiStatus kControllerApiMalfunction = - static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_MALFUNCTION); - -typedef gvr_controller_connection_state ControllerConnectionState; -const ControllerConnectionState kControllerDisconnected = - static_cast<ControllerConnectionState>(GVR_CONTROLLER_DISCONNECTED); -const ControllerConnectionState kControllerScanning = - static_cast<ControllerConnectionState>(GVR_CONTROLLER_SCANNING); -const ControllerConnectionState kControllerConnecting = - static_cast<ControllerConnectionState>(GVR_CONTROLLER_CONNECTING); -const ControllerConnectionState kControllerConnected = - static_cast<ControllerConnectionState>(GVR_CONTROLLER_CONNECTED); - -typedef gvr_controller_button ControllerButton; -const ControllerButton kControllerButtonNone = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_NONE); -const ControllerButton kControllerButtonClick = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_CLICK); -const ControllerButton kControllerButtonHome = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_HOME); -const ControllerButton kControllerButtonApp = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_APP); -const ControllerButton kControllerButtonVolumeUp = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_VOLUME_UP); -const ControllerButton kControllerButtonVolumeDown = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_VOLUME_DOWN); -const ControllerButton kControllerButtonCount = - static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_COUNT); - -typedef gvr_controller_battery_level ControllerBatteryLevel; -const ControllerBatteryLevel kControllerBatteryLevelUnknown = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_UNKNOWN); -const ControllerBatteryLevel kControllerBatteryLevelCriticalLow = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_CRITICAL_LOW); -const ControllerBatteryLevel kControllerBatteryLevelLow = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_LOW); -const ControllerBatteryLevel kControllerBatteryLevelMedium = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_MEDIUM); -const ControllerBatteryLevel kControllerBatteryLevelAlmostFull = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_ALMOST_FULL); -const ControllerBatteryLevel kControllerBatteryLevelFull = - static_cast<ControllerBatteryLevel>( - GVR_CONTROLLER_BATTERY_LEVEL_FULL); - -/// An uninitialized external surface ID. -const int32_t kUninitializedExternalSurface = GVR_BUFFER_INDEX_EXTERNAL_SURFACE; -/// The default source buffer index for viewports. -const int32_t kDefaultBufferIndex = 0; - -typedef gvr_eye Eye; - -typedef gvr_viewer_type ViewerType; -const ViewerType kViewerTypeCardboard = - static_cast<ViewerType>(GVR_VIEWER_TYPE_CARDBOARD); -const ViewerType kViewerTypeDaydream = - static_cast<ViewerType>(GVR_VIEWER_TYPE_DAYDREAM); - -typedef gvr_version Version; -typedef gvr_sizei Sizei; -typedef gvr_recti Recti; -typedef gvr_rectf Rectf; -typedef gvr_vec2f Vec2f; -typedef gvr_vec3f Vec3f; -typedef gvr_mat4f Mat4f; -typedef gvr_quatf Quatf; -typedef gvr_clock_time_point ClockTimePoint; - -typedef gvr_vec2f ControllerVec2; -typedef gvr_vec3f ControllerVec3; -typedef gvr_quatf ControllerQuat; - -typedef gvr_audio_rendering_mode AudioRenderingMode; -typedef gvr_audio_material_type AudioMaterialName; -typedef gvr_audio_distance_rolloff_type AudioRolloffMethod; -typedef gvr_audio_source_id AudioSourceId; -typedef gvr_audio_surround_format_type AudioSurroundFormat; - -typedef gvr_color_format_type ColorFormat; -const ColorFormat kColorFormatRgba8888 = - static_cast<ColorFormat>(GVR_COLOR_FORMAT_RGBA_8888); -const ColorFormat kColorFormatRgb565 = - static_cast<ColorFormat>(GVR_COLOR_FORMAT_RGB_565); - -typedef gvr_depth_stencil_format_type DepthStencilFormat; -const DepthStencilFormat kDepthStencilFormatNone = - static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_NONE); -const DepthStencilFormat kDepthStencilFormatDepth16 = - static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16); -const DepthStencilFormat kDepthStencilFormatDepth24 = - static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_24); -const DepthStencilFormat kDepthStencilFormatDepth24Stencil8 = - static_cast<DepthStencilFormat>( - GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8); -const DepthStencilFormat kDepthStencilFormatDepth32f = - static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F); -const DepthStencilFormat kDepthStencilFormatDepth32fStencil8 = - static_cast<DepthStencilFormat>( - GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8); -const DepthStencilFormat kDepthStencilFormatStencil8 = - static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_STENCIL_8); - -typedef gvr_controller_handedness ControllerHandedness; -const ControllerHandedness kControllerRightHanded = - static_cast<ControllerHandedness>(GVR_CONTROLLER_RIGHT_HANDED); -const ControllerHandedness kControllerLeftHanded = - static_cast<ControllerHandedness>(GVR_CONTROLLER_LEFT_HANDED); - -typedef gvr_error Error; -const Error kErrorNone = static_cast<Error>(GVR_ERROR_NONE); -const Error kErrorControllerCreateFailed = - static_cast<Error>(GVR_ERROR_CONTROLLER_CREATE_FAILED); -const Error kErrorNoFrameAvailable = - static_cast<Error>(GVR_ERROR_NO_FRAME_AVAILABLE); - -class AudioApi; -class BufferSpec; -class ControllerApi; -class ControllerState; -class Frame; -class GvrApi; -class BufferViewport; -class BufferViewportList; -class SwapChain; -class UserPrefs; - -} // namespace gvr - -// Non-member equality operators for convenience. Since typedefs do not trigger -// argument-dependent lookup, these operators have to be defined for the -// underlying types. -inline bool operator==(const gvr_vec2f& lhs, const gvr_vec2f& rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y; -} - -inline bool operator!=(const gvr_vec2f& lhs, const gvr_vec2f& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const gvr_vec3f& lhs, const gvr_vec3f& rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y; -} - -inline bool operator!=(const gvr_vec3f& lhs, const gvr_vec3f& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const gvr_recti& lhs, const gvr_recti& rhs) { - return lhs.left == rhs.left && lhs.right == rhs.right && - lhs.bottom == rhs.bottom && lhs.top == rhs.top; -} - -inline bool operator!=(const gvr_recti& lhs, const gvr_recti& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const gvr_rectf& lhs, const gvr_rectf& rhs) { - return lhs.left == rhs.left && lhs.right == rhs.right && - lhs.bottom == rhs.bottom && lhs.top == rhs.top; -} - -inline bool operator!=(const gvr_rectf& lhs, const gvr_rectf& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const gvr_sizei& lhs, const gvr_sizei& rhs) { - return lhs.width == rhs.width && lhs.height == rhs.height; -} - -inline bool operator!=(const gvr_sizei& lhs, const gvr_sizei& rhs) { - return !(lhs == rhs); -} - -#endif // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER) - -#endif // VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h deleted file mode 100644 index 5bd617463e..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_ -#define VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_ - -#include <stdbool.h> -#include <stdint.h> - -#include "vr/gvr/capi/include/gvr_types.h" -#include "vr/gvr/capi/src/gvr_types_experimental.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// NOTE: APIs added to this file are *not* part of the core GVR library, and -// should only be used for prototyping or experimental projects. The idea is -// that APIs added here can be used for testing and development, graduating to -// the core API (gvr.h or gvr_private.h) after we're ready to commit to them -// indefinitely. - -// ************************************************************************** // -// * DaydreamOS experimental APIs * // -// ************************************************************************** // - -/// Gets the position and rotation from start space to head space. The head -/// space is a space where the head is at the origin and faces the -Z direction. -/// -/// @param gvr Pointer to the gvr instance from which to get the pose. -/// @param time The time at which to get the head pose. The time should be in -/// the future. If the time is not in the future, it will be clamped to now. -/// @return A matrix representation of the position and rotation from start -// space (the space where the head was last reset) to head space (the space -/// with the head at the origin, and the axes aligned to the view vector). -gvr_mat4f gvr_get_head_space_from_start_space_pose( - gvr_context* gvr, const gvr_clock_time_point time); - -/// Sets the compositor z-order of the swap chain. -/// -/// @param swap_chain the swap chain to change. -/// @param z_order Z order, higher values are displayed on top of lower ones, -/// the default value is 0. -void gvr_swap_chain_set_z_order(const gvr_swap_chain* swap_chain, int z_order); - -/// Creates a gvr_external_surface instance. -/// An external surface is mainly used to pass external content (such as video -/// frames, pre-rendered 2D Android UI) into distortion pass for compositing. -/// The method gvr_external_surface_get_surface can be used to bridge Android -/// components with GVR distortion pass via a traditional Android Surface -/// instance. -/// -/// @param gvr Pointer to the gvr instance from which to create the external -/// surface. -/// @return Pointer to an allocated gvr_external_surface object. The caller -// is responsible for calling gvr_external_surface_destroy() on the -/// returned object when it is no longer needed. -gvr_external_surface* gvr_external_surface_create(gvr_context* gvr); - -/// Frees a gvr_external_surface instance and clears the pointer. -/// Note that once a gvr_external_surface is destroyed, the Java Surface object -/// returned from gvr_external_surface_get_surface remains to be accessible and -/// functioning. It's up to Java's garbage collection to release all resources -/// behind the Java Surface object. -/// -/// @param surface Pointer to a pointer to the gvr_external_surface instance to -/// be destroyed and nulled. -void gvr_external_surface_destroy(gvr_external_surface** surface); - -/// Get an Android Surface as a Java object from the gvr_external_surface. This -/// API is mainly used by standalone display service (aka when -/// gvr_using_vr_display_service returns true) to access an Android Surface. -/// -/// @param surface The gvr_external_surface associated with the Android Surface. -/// Note that this API has to be called within a JNIEnv and is using the -/// JNIEnv passed in during gvr_create. -/// @return A jobject that is an instance of the 'android/view/Surface' Java -/// class, NULL on failure. Note that the return value is really an opaque -/// handle to a Java object and the life cycle of that object is maintained -/// by Java (i.e. it will get garbage collected eventually). Thus, there is -/// no need for an explicit destroy call. -void* gvr_external_surface_get_surface(const gvr_external_surface* surface); - -/// Get the Surface ID associated with the gvr_external_surface. Note that the -/// returned ID is used for internal bookkeeping only and should not be used -/// by the app itself for lookups. -/// @param surface The gvr_external_surface to query the ID for. -/// @return The external surface ID associated with the gvr_external_surface. -int32_t gvr_external_surface_get_surface_id( - const gvr_external_surface* surface); - -/// Sets the z order of the layer to be created. -/// Note that this API is a short-term workaround for SysUI work and is never -/// meant to graduate as is to either gvr.h or gvr_private.h. The proper -/// solution is tracked in b/33946428 and probably involves setting the -/// attribute on some data structure that represents a layer. -/// -/// @param spec Buffer specification. -/// @param z_order Z order, higher values are displayed on top of lower ones, -/// the default value is 0. -void gvr_buffer_spec_set_z_order(gvr_buffer_spec* spec, int z_order); - -/// Sets the initial visibility of the layer to be created. -/// Note that this API is a short-term workaround for SysUI work and is never -/// meant to graduate as is to either gvr.h or gvr_private.h. The proper -/// solution is tracked in b/33946428 and probably involves setting the -/// attribute on some data structure that represents a layer. -/// -/// @param spec Buffer specification. -/// @param visibility Initial visibility of the layer, defaults to GVR_VISIBLE. -/// See enum gvr_visibility for possible values. -void gvr_buffer_spec_set_visibility(gvr_buffer_spec* spec, - int32_t visibility); - -/// Sets whether to blur layers below the layer to be created. -/// Blurring is applied only to visible layers and only when the layer is -/// visible. -/// Note that this API currently is only implemented by the DreamOS -/// implementation of GVR and is a no-op in other implementations. -/// TODO(b/33946428): investigate the proper way to surface this feature -/// to SysUI. -/// -/// @param spec Buffer specification. -/// @param blur_behind whether to blur layers behind, defaults to -/// GVR_BLUR_BEHIND_TRUE. See enum gvr_blur_behind for possible values. -void gvr_buffer_spec_set_blur_behind(gvr_buffer_spec* spec, - int32_t blur_behind); - -// ************************************************************************** // -// * Daydream PlexEng experimental APIs * // -// ************************************************************************** // - -// Registers a new performance event listener that will be invoked on points -// of interest. By default no event listener is attached. If multiple event -// listeners are attached they will all be invoked. Failures can be checked -// with gvr_get_error(). -// @param out_handle The pointer to memory where a successfully created handle -// will be written. -// @param gvr The context to register callbacks for. -// @param user_data The pointer that will be passed back on callbacks for -// user_data. -// @param event_callback The callback to be invoked when an event is observed. -// On performance events callback will be invoked with the -// user_data passed here, the gvr_perf_event_callback_type, and a float -// value (if applicable) or -1.f. -// @return Returns GVR_EXPERIMENTAL_ERROR_NONE if a handle was created, -// GVR_EXPERIMENTAL_ERROR_UNIMPLEMENTED if this feature is disabled, -// or GVR_EXPERIMENTAL_ERROR_INVALID_ARGUMENT if a null pointer was passed. -bool gvr_experimental_register_perf_event_callback( - gvr_context* gvr, int* out_handle, void* user_data, - void (*event_callback)(void*, int, float)); - -// Unregisters a previously registered callback by its handle. Failures can be -// checked with gvr_get_error(). -// @param handle The handle which was returned when registering the callback. -// @return Returns GVR_EXPERIMENTAL_ERROR_NONE if callback was unregistered, -// GVR_EXPERIMENTAL_ERROR_INVALID_ARGUMENT if the if the handle wasn't -// previously -// registered. If this feature is not enabled it will return -// GVR_EXPERIMENTAL_ERROR_UNIMPLEMENTED. -bool gvr_experimental_unregister_perf_event_callback(gvr_context* gvr, - int handle); - -// ************************************************************************** // -// * GVR Analytics experimental APIs * // -// ************************************************************************** // -// TODO(b/31634289): These functions are experimental because their main client -// case is the performance monitoring HUD, whose form and function is still -// under development. Consequently, the analytics API may change as the HUD's -// needs become clearer. -// -// These functions will be moved into the main API (probably gvr_private.h) once -// the HUD is ready to be shipped as part of the SDK. -// -// Contacts: georgelu@ - -/// Returns whether the "Performance Monitoring" developer option is enabled. -/// -/// @param user_prefs Pointer to the gvr_user_prefs object returned by -/// gvr_get_user_prefs. -/// @return True if the "Performance Monitoring" developer option is enabled. -bool gvr_user_prefs_get_performance_monitoring_enabled( - const gvr_user_prefs* user_prefs); - -// Opaque struct returned by gvr_get_analytics that can be queried through -// gvr_analytics_get* functions. -// -// Note: The struct is never actually defined since gvr_analytics is actually -// just a static_cast of a gvr_context, similar to how gvr_user_prefs works. -typedef struct gvr_analytics_ gvr_analytics; - -// Returns an opaque struct that can be queried for analytics data. The returned -// struct remains valid as long as the context is valid. -// -// @param gvr Pointer to the current gvr_context instance. -// @return An opaque struct that can be queried through gvr_analytics_* -// functions. -const gvr_analytics* gvr_get_analytics(gvr_context* gvr); - -// If the "Performance Monitoring" developer option in VR settings is enabled, -// returns a gvr_analytics_sample* containing analytics data. Caller is -// responsible for calling gvr_analytics_destroy_sample on the returned object. -// -// @param analytics gvr_analytics* returned by gvr_get_analytics. -// @return gvr_analytics_sample* containing analytics data. -const gvr_analytics_sample* gvr_analytics_create_sample( - const gvr_analytics* analytics); - -// Returns pointer to a buffer containing a serialized AnalyticsSample proto. -// The buffer is valid only for the lifetime of the gvr_analytics_sample. -// -// @param Pointer to a gvr_analytics_sample object. -// @return Pointer to buffer. -const char* gvr_analytics_sample_get_buffer(const gvr_analytics_sample* sample); - -// Returns the length of the buffer returned by gvr_analytics_sample_get_buffer. -// -// @param Pointer to a gvr_analytics_sample object. -// @return Length of buffer. -size_t gvr_analytics_sample_get_buffer_length( - const gvr_analytics_sample* sample); - -// Destroys a gvr_analytics_sample* previously created through -// gvr_analytics_create_sample. -// -// @param sample Pointer to pointer that will be set to null and whose -// underlying gvr_analytics_sample will be destroyed. -void gvr_analytics_destroy_sample(const gvr_analytics_sample** sample); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h deleted file mode 100644 index 0a9d30ee0e..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h +++ /dev/null @@ -1,378 +0,0 @@ -#ifndef VR_GVR_CAPI_SRC_GVR_PRIVATE_H_ -#define VR_GVR_CAPI_SRC_GVR_PRIVATE_H_ - -#include <stddef.h> - -#include "vr/gvr/capi/include/gvr_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Opaque handle to gvr_tracker_state object containing serialized state. -typedef struct gvr_tracker_state_ gvr_tracker_state; - -// Opaque handle to gvr_display_synchronizer object for display synchronization. -typedef struct gvr_display_synchronizer_ gvr_display_synchronizer; - -// Internal Google VR C API methods. These methods are exposed only to internal -// targets, but should follow all the same backwards-compatible restrictions -// as the public C API. - -/// Sets whether asynchronous reprojection is currently enabled. -/// -/// If enabled, frames will be collected by the rendering system and -/// asynchronously re-projected in sync with the scanout of the display. This -/// feature may not be available on every platform, and requires a -/// high-priority render thread with special extensions to function properly. -/// -/// Note: On Android, this feature can be enabled solely via the GvrLayout Java -/// instance which (indirectly) owns this gvr_context. The corresponding -/// method call is GvrLayout.setAsyncReprojectionEnabled(). -/// -/// @param gvr Pointer to the gvr instance. -/// @Param enabled Whether to enable async reprojection. -/// @return Whether the setting was succesfully applied. -bool gvr_set_async_reprojection_enabled(gvr_context* gvr, bool enabled); - -// Initializes necessary GL-related objects and uses the current thread and -// GL context for racing the scanline. This function should only be called -// by the SDK itself, not by any application, unless that application is -// providing a high-priority thread and GL context for async reprojection. -// -// Note: This method is private as it is intended for use solely by the -// hidden async reprojection implementation in ScanlineRacingRenderer.java, -// called in onSurfaceCreated(). -// -// @param gvr Pointer to the gvr_context instance. -void gvr_on_surface_created_reprojection_thread(gvr_context* gvr); - -// Renders the scanline layer. This function should only be called -// in the same thread that gvr_initialize_gl_projection_thread was called in. -// This function should only be called by the SDK itself, not by any -// application, unless that application is providing a high-priority -// thread and GL context for async reprojection. -// -// Note: This method is private as it is intended for use solely by the -// hidden async reprojection implementation in ScanlineRacingRenderer.java. -// -// @param gvr Pointer to the gvr_context instance. -void gvr_render_reprojection_thread(gvr_context* gvr); - -// Signals to the reprojection thread that it is paused. This is necessary -// in case the application render thread is blocked on pending work by the -// reprojection thread. This function will abort any blocking. -// -// @param gvr Pointer to the gvr_context instance. -void gvr_on_pause_reprojection_thread(gvr_context* gvr); - -// Sets the parameters for the external surface managed by the reprojection -// thread. -// -// @param gvr Pointer to the gvr_context instance. -// @param surface_id The ID of the external Surface managed by the reprojection -// thread. The ID is issued by the SurfaceTextureManager. -// @param texture_id The GL texture ID associated with the external Surface. -// @param timestamp The timestamp of the most recent frame the Surface holds. -// @param surface_transfrom Matrix that transforms homogeneous texture coords to -// the external surface texture space. -void gvr_update_surface_reprojection_thread(gvr_context* gvr, - int32_t surface_id, int32_t texture_id, gvr_clock_time_point timestamp, - gvr_mat4f surface_transform); - -// Removes all external surfaces managed by the reprojection thread. This does -// not destoy the surfaces: it removes tracking by the reprojection thread. -// -// @param gvr Pointer to the gvr_context instance. -void gvr_remove_all_surfaces_reprojection_thread(gvr_context* gvr); - -// Reconnects the sensors when the sensor producers are created internally. -// -// Note: This function is not thread-safe, and should be called only on the -// rendering thread. It is intended to be used internally by GvrLayout when -// the target presentation display changes. -// -// @param gvr Pointer to the gvr_context instance. -void gvr_reconnect_sensors(gvr_context* gvr); - -// Sets VR viewer params for the current context. -// -// Note: This function does not update the viewer proto in the common storage -// location. Rather, it overrides the viewer params solely for the provided -// gvr_context. -// -// @param gvr Pointer to the gvr_context instance. -// @param serialized_viewer_params A pointer to the payload containing the -// serialized viewer params proto. -// @param serialized_viewer_params_size_bytes The length in bytes of the -// serialized viewer params payload. -// @return Whether the serialized viewer params proto was successfully applied. -bool gvr_set_viewer_params(gvr_context* gvr, - const void* serialized_viewer_params, - size_t serialized_viewer_params_size_bytes); - -// Sets the lens offset. -// -// @param offset The offset of the lens center from the expected location in -// screen space. -void gvr_set_lens_offset(gvr_context* gvr, gvr_vec2f offset); - -// Sets display metrics for the current context. -// -// Note: This function does not update the phone proto in the commom storage -// location. Rather, it overrides the internal metrics solely for the provided -// |gvr| context. -// -// @param gvr Pointer to the gvr_context instance. -// @param size_pixels The dimensions in pixels of the active display. -// @param meters_per_pixel The density of the current display in meters/pixel. -// @param border_size_meters The size of the border around the display -// in meters. When the device sits on a surface in the proper -// orientation this is the distance from the surface to the edge -// of the display. -void gvr_set_display_metrics(gvr_context* gvr, gvr_sizei size_pixels, - gvr_vec2f meters_per_pixel, - float border_size_meters); - -// Sets the display rotation offset that is applied at distortion correction -// time to take into account the device's display orientation. -// -// For instance, calling this with display_output_rotation set to 1 allows -// clients to lock their phone orientation to portrait on an Android phone and -// still get a correctly rendered VR mode with the two eyes stacked up along the -// longer phone dimension. -// -// @param gvr Pointer to the gvr_context instance. -// @param display_output_rotation Value encoding the rotation used when -// performing distortion correction. Supported values are: -// 0 - Default mode. Eye viewports are positioned side-by-side along the -// "width" dimension, with left eye in the x < 0.5 half. -// 1 - Applies a clock-wise rotation of 90 degrees on the display when -// doing distortion correction. Eye viewports are positioned -// side-by-side along the "height" dimension, with left eye in the -// y > 0.5 half. -// Rotation modes used when performing distortion correction. -enum { - GVR_PRIVATE_DISPLAY_OUTPUT_ROTATION_0 = 0, - GVR_PRIVATE_DISPLAY_OUTPUT_ROTATION_90 = 1, -}; -void gvr_set_display_output_rotation(gvr_context* gvr, - int32_t display_output_rotation); - -// Gets the size of the border around the display used by the given gvr_context. -// -// @param gvr Pointer to the gvr_context instance. -float gvr_get_border_size_meters(const gvr_context* gvr); - -// Returns whether the surface size was changed since the last call to this -// function (it's changed with gvr_set_surface_size()). -// -// @param gvr Pointer to the gvr_context instance. -// @return Whether the surface size was changed. -bool gvr_check_surface_size_changed(gvr_context* gvr); - -// Returns the current surface size in pixels, or (0, 0) if the surface size -// matches that of the active display (which is the default). -// -// @param gvr Pointer to the gvr_context instance. -// @return The current surface size in pixels. -gvr_sizei gvr_get_surface_size(const gvr_context* gvr); - -// Sets a handler that is called back when the back gesture is detected, -// which is when the phone changes from landscape to portrait orientation -// within a few seconds. -// -// @param gvr Pointer to the gvr_context instance. -// @param handler The event_handler callback. May be null to clear the -// registered event_handler. -// @param user_data An opaque pointer to user_data which will be supplied -// as the callback argument. The caller is responsible for ensuring the -// validity of this data for the duration of the handler registration. -typedef void (*event_handler)(void* user_data); -void gvr_set_back_gesture_event_handler(gvr_context* gvr, event_handler handler, - void* user_data); - -// Internal method to pause head tracking used by GvrLayout. Disables all -// sensors (to save power) and gets the serialized tracker state. -// -// @param gvr Pointer to the gvr instance for which tracking will be paused and -// sensors disabled. -// -// @return Pointer to a tracker_state object containing the serialized tracker -// state. The caller is responsible for calling destroy on the returned -// handle. -gvr_tracker_state* gvr_pause_tracking_get_state(gvr_context* gvr); - -// Internal method to resume head tracking used by GvrLayout. Re-enables all -// sensors and sets the tracker state. -// -// @param gvr Pointer to the gvr instance for which tracking will be resumed. -// serialized tracker state object. -// @param tracker_state Pointer to a tracker_state object containing the -// serialized tracker state object. -void gvr_resume_tracking_set_state( - gvr_context* gvr, gvr_tracker_state* tracker_state); - -// Sets the internal flag that ignores calls to the public API's -// gvr_pause_tracking and gvr_resume_tracking. -// When true, the tracker is handled through GvrLayout -// gvr_pause_tracking_private / gvr_resume_tracking_private direct calls through -// the GvrApi instance are ignored. This is workaround to temporarily support -// clients using GvrLayout that manually call pause/ resume tracking. -// TODO(b/30404822) : clean this up once all existing clients move away from the -// obsolete behavior. -// -// @param gvr Pointer to the gvr instance. -// @param should_ignore Whether manual pause / resume tracker should be ignored. -void gvr_set_ignore_manual_tracker_pause_resume(gvr_context* gvr, - bool should_ignore); - -// Creates a new tracker state object from the serialized tracker state buffer. -// -// @param tracker_state_buffer Pointer to buffer containing the serialized -// tracker state. -// @param buf_size Size of the tracker state buffer. -// -// @return Pointer to a tracker_state object containing the serialized tracker -// state string. The caller is responsible for calling destroy on the returned -// handle. -gvr_tracker_state* gvr_tracker_state_create(const char* tracker_state_buffer, - size_t buf_size); - -// Gets the size of the buffer that is required to hold the serialized -// gvr_tracker_state. -// -// @param Pointer to a gvr_tracker_state object containing the serialized -// tracker state. -// -// @return Size of the buffer, -size_t gvr_tracker_state_get_buffer_size(gvr_tracker_state* tracker_state); - -// Gets the buffer that holds the serialized gvr_tracker_state. -// -// @param Pointer to a tracker_state object containing the serialized tracker -// state. -// -// @return Pointer to the buffer. -const char* gvr_tracker_state_get_buffer(gvr_tracker_state* tracker_state); - -// Destroys a gvr_tracker_state instance. -// -// @param tracker_state Pointer to a pointer of the gvr_tracker_state instance -// to be destroyed and nulled. -void gvr_tracker_state_destroy(gvr_tracker_state** tracker_state); - -// Creates a new synchronizer instance. -// -// @return synchronizer Pointer to the new gvr_display_synchronizer instance. -gvr_display_synchronizer* gvr_display_synchronizer_create(); - -// Destroy the synchonronizer instance and null the pointer. -// -// @param synchronizer Pointer to a pointer to the gvr_display_synchronizer -// instance. -void gvr_display_synchronizer_destroy(gvr_display_synchronizer** synchronizer); - -// Resets the synchronizer with updated vsync timing data. -// -// @param synchronizer Pointer to the new gvr_display_synchronizer instance. -// @param expected_interval_nanos The expected average time between -// synchronization times, in nanoseconds, or 0 if unknown. -// @param vsync_offset_nanos The duration, in nanos, such that the current sync -// time minus the display vsync offset is the time when the physical -// scan-out hardware begins to read data from the frame buffer. -void gvr_display_synchronizer_reset(gvr_display_synchronizer* synchronizer, - int64_t expected_interval_nanos, - int64_t vsync_offset_nanos); - -// Updates the synchronizer with dispplay data for a new frame. -// -// @param vsync_time The new frame's vsync time. -// @param rotation_degrees The screen rotation from sensor space to display -// space in degrees. -void gvr_display_synchronizer_update(gvr_display_synchronizer* synchronizer, - gvr_clock_time_point vsync_time, - int32_t rotation); - -// Installs the display synchronizer into a GVR context. -// -// @param gvr Pointer to the current gvr_context instance. -// @param synchronizer Pointer to the gvr_display_synchronizer instance, to be -// used by the context implementation during rendering. -void gvr_set_display_synchronizer(gvr_context* gvr, - gvr_display_synchronizer* synchronizer); - -// Sets the current error code. Overwrites any existing error code. -// -// @param gvr Pointer to the current gvr_context instance. -// @param error_code The error code to set. -void gvr_set_error(gvr_context* gvr, int32_t error_code); - -// Called by the platform layer to to indicate the application is paused. (e.g. -// On Android, this function is called by GvrLayout.OnPause().) -// -// @param gvr Pointer to the current gvr_context instance. -void gvr_pause(gvr_context* gvr); - -// Called by the platform layer to to indicate the application has resumed. -// (e.g. On Android, this function is called by GvrLayout.OnResume().) -// -// @param gvr Pointer to the current gvr_context instance. -void gvr_resume(gvr_context* gvr); - -// Dumps additional data to logcat or disk to be included in bug reports. -// -// @param gvr Pointer to the current gvr_context instance. -void gvr_dump_debug_data(gvr_context* gvr); - -// Returns true if the libgvr implementation is using the dedicated VR display -// service, false otherwise. -// -// @param gvr Pointer to the current gvr_context instance. -bool gvr_using_vr_display_service(gvr_context* gvr); - -// Creates a new gvr_context using the supplied tracker, only for testing. -// -// Note: The pose returned is *in start space*. This is *not* the same space as -// the pose normally returned by |gvr_get_head_space_from_start_space_rotation|. -// -// @param tracker The test pose tracker to use. -// @param user_data An opaque pointer to user_data which will be supplied -// as the callback argument. The caller is responsible for ensuring the -// validity of this data for the duration of the handler registration. -typedef gvr_mat4f (*gvr_test_pose_tracker)(void*, gvr_clock_time_point); -gvr_context* gvr_create_with_tracker_for_testing(gvr_test_pose_tracker tracker, - void* user_data); - -// Request resource sharing between the application's OpenGL context and the -// scanline racing context. This must be called before gvr_initialize_gl. -// <p> -// This is a best effort request rather than an explicit toggle; it is a no-op -// if the client does not enable async reprojection, or if the platform does not -// support resource sharing. -// <p> -// The only OpenGL resource that we need sharing for is the framebuffer texture -// that the app renders to, and that distortion samples from. If resource -// sharing is disabled, then we use an EGLImage so that it can be accessed from -// both contexts. -// <p> -// Also sets a callback function that is called at the end of gvr_initialize_gl, -// while the application's OpenGL context is still active on the current thread. -// This is used internally to notify the scanline racing renderer that the -// application's OpenGL context has been created. -// -// @param gvr Pointer to the current gvr_context instance. -// @param handler Callback that gets called when the app context becomes ready. -// @param user_data An opaque pointer to user data which will be supplied -// as the callback argument. The caller is responsible for ensuring the -// validity of this data for the duration of the handler registration. -typedef void (*gvr_egl_context_listener)(void*); -void gvr_request_context_sharing(gvr_context* gvr, - gvr_egl_context_listener handler, - void* user_data); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // VR_GVR_CAPI_SRC_GVR_PRIVATE_H_ diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h deleted file mode 100644 index f7ae6a5b00..0000000000 --- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_ -#define VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_ - -#include <string> - -// ************************************************************************** // -// * DaydreamOS experimental Types * // -// ************************************************************************** // - -// Visibility of a layer. -typedef enum { - GVR_INVISIBLE = 0, - GVR_VISIBLE = 1, -} gvr_visibility; - -// Whether to blur layers behind a layer. -typedef enum { - GVR_BLUR_BEHIND_FALSE = 0, - GVR_BLUR_BEHIND_TRUE = 1, -} gvr_blur_behind; - -// GVR external surface -typedef struct gvr_external_surface_ gvr_external_surface; - -// ************************************************************************** // -// * Daydream PlexEng experimental Types * // -// ************************************************************************** // - -// Types of events that can have callbacks registered. -// If documented, type will return a payload value when called, or will -// otherwise be invoked with -1.f. -// This enum has to be duplicated because there is no way to include from -// /vr/gvr/render/performance_registry.h. Duplicate changes made here there. -typedef enum { - // Will be invoked with value -1.f. - GVR_ON_ASYNC_REPROJECTION_FRAME_START = 0, - // Will be invoked with value -1.f. - GVR_ON_ASYNC_REPROJECTION_FRAME_STOP = 1, - // When invoked will be called with how late in microseconds the frame was. - GVR_ON_ASYNC_REPROJECTION_FRAME_DROP = 2, - // The number of types of performance events you can have. - // Also note that this value is considered invalid. - GVR_NUM_PERF_EVENT_CALLBACK_TYPES = 3, -} gvr_perf_event_callback_type; - -// Experimental VR-specific features which may or may not be supported on the -// underlying platform. These values should not overlap with current or future -// gvr_feature values, so we're starting with 1000000 and increasing upward. -typedef enum { - // Head tracking with 6 degrees of freedom (position & rotation) - GVR_FEATURE_HEAD_POSE_6DOF = 1000000, -} gvr_experimental_feature; - -// ************************************************************************** // -// * GVR Analytics experimental APIs * // -// ************************************************************************** // - -// Opaque struct returned by gvr_analytics_create_sample, used to transmit an -// AnaylticsSample proto across the native layer. -typedef struct gvr_analytics_sample_ { - // Serialized AnalyticsSample proto. Note that this is not a C string, meaning - // it is not null-terminated and may contain non-terminating nulls. - std::string serialized_proto; -} gvr_analytics_sample; - -#endif // VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_ diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so Binary files differdeleted file mode 100644 index bfd59566d2..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so Binary files differdeleted file mode 100644 index c3012b1806..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so Binary files differdeleted file mode 100644 index 6608c25f04..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so Binary files differdeleted file mode 100644 index b1d76906e5..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so Binary files differdeleted file mode 100644 index f7f7786795..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so Binary files differdeleted file mode 100644 index 97aec401d9..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so Binary files differdeleted file mode 100644 index 2e2dbc1a2e..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so Binary files differdeleted file mode 100644 index cd8d0e0932..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so +++ /dev/null diff --git a/libs/vr/libgvr/prebuilt/lib/common_library.aar b/libs/vr/libgvr/prebuilt/lib/common_library.aar Binary files differdeleted file mode 100644 index 9c1fbd0d56..0000000000 --- a/libs/vr/libgvr/prebuilt/lib/common_library.aar +++ /dev/null diff --git a/libs/vr/libgvr/shim_gvr.cpp b/libs/vr/libgvr/shim_gvr.cpp deleted file mode 100644 index 5eb6e3daa9..0000000000 --- a/libs/vr/libgvr/shim_gvr.cpp +++ /dev/null @@ -1,1352 +0,0 @@ -#define LOG_TAG "libgvr_shim" - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <GLES3/gl31.h> -#include <GLES3/gl3ext.h> -#include <algorithm> -#include <cmath> - -#ifdef __ARM_NEON -#include <arm_neon.h> -#else -#ifndef __FLOAT32X4T_86 -#define __FLOAT32X4T_86 -typedef float float32x4_t __attribute__ ((__vector_size__ (16))); -typedef struct float32x4x4_t { float32x4_t val[4]; }; -#endif -#endif - -#include <dvr/graphics.h> -#include <dvr/performance_client_api.h> -#include <dvr/pose_client.h> -#include <log/log.h> -#include <private/dvr/buffer_hub_queue_core.h> -#include <private/dvr/buffer_hub_queue_producer.h> -#include <private/dvr/clock_ns.h> -#include <private/dvr/display_client.h> -#include <private/dvr/graphics_private.h> -#include <private/dvr/internal_types.h> -#include <private/dvr/numeric.h> -#include <private/dvr/types.h> -#include <private/dvr/video_mesh_surface_client.h> -#include <sys/system_properties.h> -#include <vr/gvr/capi/include/gvr.h> -#include <vr/gvr/capi/include/gvr_ext.h> -#include <vr/gvr/capi/include/gvr_util.h> -#include <vr/gvr/capi/src/gvr_experimental.h> -#include <vr/gvr/capi/src/gvr_private.h> - -#include <android_runtime/android_view_Surface.h> -#include <gui/Surface.h> - -using android::dvr::DisplayClient; -using android::dvr::EigenToGvrMatrix; -using android::dvr::FieldOfView; -using android::dvr::FovRadiansToDegrees; -using android::dvr::GetSystemClockNs; -using android::dvr::GvrIdentityMatrix; -using android::dvr::GvrMatrixToPosef; -using android::dvr::GvrToDvrFov; -using android::dvr::GvrToEigenMatrix; -using android::dvr::GvrToEigenRotation; -using android::dvr::GvrTranslationMatrix; -using android::dvr::IsEqual; -using android::dvr::PosefToGvrMatrix; -using android::dvr::mat3; -using android::dvr::mat4; -using android::dvr::Posef; -using android::dvr::quat; -using android::dvr::vec3; - -namespace { - -constexpr static int32_t GVR_SDK_MAJOR_VERSION = 2; -constexpr static int32_t GVR_SDK_MINOR_VERSION = 0; -constexpr static int32_t GVR_SDK_PATCH_VERSION = 0; - -// The "DaydreamOS" part has been appended to make easier to see when VrCore -// dynamic GVR API loading is effectively working. -static const char* kVersionString = "2.0.0 DaydreamOS"; -static const char* kViewerVendor = "Google"; -static const char* kViewerModel = "Lucid"; - -// Experimental system property used to provide 6DoF information on 3DoF APIs. -static const char* kForce6DofProp = "experimental.force_6dof"; - -static constexpr int kControllerCount = 2; - -gvr_frame* GetFrameFromSwapChain(gvr_swap_chain* swap_chain) { - return reinterpret_cast<gvr_frame*>(swap_chain); -} - -gvr_swap_chain* GetSwapChainForFrame(gvr_frame* frame) { - return reinterpret_cast<gvr_swap_chain*>(frame); -} - -const gvr_swap_chain* GetSwapChainForFrame(const gvr_frame* frame) { - return reinterpret_cast<const gvr_swap_chain*>(frame); -} - -// Returns the world to head transform as a Posef. -Posef ToPosef(const DvrPoseAsync& pose) { - return Posef( - quat(pose.orientation[3], pose.orientation[0], pose.orientation[1], - pose.orientation[2]), - vec3(pose.translation[0], pose.translation[1], pose.translation[2])); -} - -// Returns the world to head transform, with 0 position, as a gvr matrix -gvr_mat4f Gvr6dofTo3dof(const gvr_mat4f& pose) { - gvr_mat4f ret = pose; - ret.m[0][3] = 0; - ret.m[1][3] = 0; - ret.m[2][3] = 0; - return ret; -} - -void GvrToDvrPose(gvr_mat4f world_to_head_transform, - /*out*/ float32x4_t* orientation, - /*out */ float32x4_t* translation) { - Posef pose = GvrMatrixToPosef(world_to_head_transform); - (*orientation)[0] = pose.GetRotation().x(); - (*orientation)[1] = pose.GetRotation().y(); - (*orientation)[2] = pose.GetRotation().z(); - (*orientation)[3] = pose.GetRotation().w(); - (*translation)[0] = pose.GetPosition().x(); - (*translation)[1] = pose.GetPosition().y(); - (*translation)[2] = pose.GetPosition().z(); - (*translation)[3] = 0; -} - -bool MatricesAlmostEqual(const gvr_mat4f& m1, const gvr_mat4f& m2, - float tolerance) { - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - if (!IsEqual(m1.m[row][col], m2.m[row][col], tolerance)) - return false; - } - } - return true; -} - -gvr_mat4f FovToViewportTransform(const gvr_rectf& fov) { - // Depth range (1 1000) is chosen to match gvr impl in google3, which is - // chosen to match Unity integration. - return EigenToGvrMatrix( - GvrToDvrFov(fov).GetProjectionMatrix(1.f, 1000.f).inverse()); -} - -gvr_rectf ViewportTransformToFov(const gvr_mat4f& transform) { - return DvrToGvrFov( - FieldOfView::FromProjectionMatrix(GvrToEigenMatrix(transform).inverse())); -} - -bool GetGlColorFormat(int32_t gvr_color_format, - /*out*/ GLenum* gl_color_format) { - switch (gvr_color_format) { - case GVR_COLOR_FORMAT_RGBA_8888: - *gl_color_format = GL_RGBA8; - break; - case GVR_COLOR_FORMAT_RGB_565: - *gl_color_format = GL_RGB565; - break; - default: - return false; - } - return true; -} - -bool GetGlDepthFormat(int32_t gvr_depth_format, - /*out*/ GLenum* gl_depth_format) { - switch (gvr_depth_format) { - case GVR_DEPTH_STENCIL_FORMAT_DEPTH_16: - *gl_depth_format = GL_DEPTH_COMPONENT16; - break; - case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24: - *gl_depth_format = GL_DEPTH_COMPONENT24; - break; - case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8: - *gl_depth_format = GL_DEPTH24_STENCIL8; - break; - case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F: - *gl_depth_format = GL_DEPTH_COMPONENT32F; - break; - case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8: - *gl_depth_format = GL_DEPTH32F_STENCIL8; - break; - default: - return false; - } - return true; -} - -// Returns true on success, false on failure. If the swap_chain already has a -// DvrGraphicsContext and gvr buffer, they'll be freed first. If creation fails, -// the DvrGraphicsContext in the swap_chain will be set to null and the -// corresponding gvr buffer will be freed. -bool CreateDvrGraphicsContextAndGvrBuffer(gvr_swap_chain* swap_chain) { - if (swap_chain->buffers_.empty()) { - ALOGE("Can't create a graphics context for an empty swap chain"); - return false; - } - - // We currently only render the first gvr buffer. Create a DvrGraphicsContext - // for the first buffer only. - gvr_buffer& buf = swap_chain->buffers_[0]; - buf.FreeGl(); - - bool visible; - int z_order; - if (swap_chain->graphics_context_ != nullptr) { - visible = dvrGraphicsSurfaceGetVisible(swap_chain->graphics_context_); - z_order = dvrGraphicsSurfaceGetZOrder(swap_chain->graphics_context_); - dvrGraphicsContextDestroy(swap_chain->graphics_context_); - swap_chain->graphics_context_ = nullptr; - } else { - visible = buf.spec.initially_visible; - z_order = buf.spec.z_order; - } - - int width = 0, height = 0; - GLuint texture_id = 0; - GLenum texture_target = 0; - DvrSurfaceParameter surface_params[] = { - DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, false), - DVR_SURFACE_PARAMETER_IN(CREATE_GL_CONTEXT, 0), - DVR_SURFACE_PARAMETER_IN(WIDTH, buf.spec.size.width), - DVR_SURFACE_PARAMETER_IN(HEIGHT, buf.spec.size.height), - DVR_SURFACE_PARAMETER_IN(BLUR_BEHIND, buf.spec.blur_behind), - DVR_SURFACE_PARAMETER_IN(VISIBLE, visible), - DVR_SURFACE_PARAMETER_IN(Z_ORDER, z_order), - DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &width), - DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &height), - DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_TYPE, &texture_target), - DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_ID, &texture_id), - DVR_SURFACE_PARAMETER_LIST_END, - }; - - DvrGraphicsContext* graphics_context; - int ret = dvrGraphicsContextCreate(surface_params, &graphics_context); - if (ret < 0) { - ALOGE("dvrGraphicsContextCreate failed: %d (%s)", ret, strerror(-ret)); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return false; - } - - // Sanity check that the size of the buffer we allocated from the system is - // what we expect - if (buf.spec.size != gvr_sizei{width, height}) { - ALOGE( - "The created surface is the wrong size." - " Should be %dx%d, instead got %dx%d.", - buf.spec.size.width, buf.spec.size.height, width, height); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - dvrGraphicsContextDestroy(graphics_context); - return false; - } - - buf = gvr_buffer(swap_chain->context, buf.spec, texture_id, texture_target); - if (buf.frame_buffer == 0) { - dvrGraphicsContextDestroy(graphics_context); - return false; - } - - swap_chain->graphics_context_ = graphics_context; - return true; -} - -bool SwapChainResizeBuffer(gvr_swap_chain* swap_chain, int buffer_index) { - gvr_buffer& buf = swap_chain->buffers_[buffer_index]; - buf.FreeGl(); - gvr_sizei orig_size = buf.spec.size; - buf.spec.size = buf.requested_size; - bool resize_successful = false; - if (buffer_index == 0) { - resize_successful = CreateDvrGraphicsContextAndGvrBuffer(swap_chain); - } else { - buf = gvr_buffer(swap_chain->context, buf.spec, 0, GL_TEXTURE_2D); - resize_successful = buf.frame_buffer != 0; - } - - if (resize_successful) { - // The resize was successful, so clear the resize request - buf.requested_size = {-1, -1}; - } else { - ALOGE("Failed to resize buffer. orig_size=%dx%d requested_size=%dx%d.", - orig_size.width, orig_size.height, buf.requested_size.width, - buf.requested_size.height); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - buf.spec.size = orig_size; - } - - return resize_successful; -} - -void WaitNextFrame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos, - gvr_frame_schedule* out_next_frame_schedule, - bool called_by_app) { - if (called_by_app) - swap_chain->wait_next_frame_called_by_app_ = true; - - DvrFrameSchedule dvr_schedule; - int ret = dvrGraphicsWaitNextFrame(swap_chain->graphics_context_, - start_delay_nanos, &dvr_schedule); - if (ret < 0) { - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } - if (out_next_frame_schedule) { - out_next_frame_schedule->vsync_count = dvr_schedule.vsync_count; - out_next_frame_schedule->scheduled_finish.monotonic_system_time_nanos = - dvr_schedule.scheduled_frame_finish_ns; - } - - DvrPoseAsync pose; - ret = dvrPoseGet(swap_chain->context->pose_client_, dvr_schedule.vsync_count, - &pose); - if (ret < 0) { - ALOGW("dvrPoseGet failed: %d", ret); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } - - swap_chain->context->next_frame_6dof_pose_ = PosefToGvrMatrix(ToPosef(pose)); - - for (int i = 0; i < kControllerCount; ++i) { - ret = dvrPoseGetController(swap_chain->context->pose_client_, i, - dvr_schedule.vsync_count, &pose); - if (ret == 0) { - // Silently fail when there are no controllers. - swap_chain->context->next_frame_controller_pose_[i] = - PosefToGvrMatrix(ToPosef(pose).Inverse()); - } - } -} - -bool VerifyBufferIndex(const std::string& function_name, - const gvr_swap_chain* swap_chain, int index) { - if (index > static_cast<int32_t>(swap_chain->buffers_.size())) { - ALOGE("%s out of range buffer index. index=%d num_buffers=%zu.", - function_name.c_str(), index, swap_chain->buffers_.size()); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return false; - } - return true; -} - -} // anonymous namespace - -gvr_context* gvr_create(JNIEnv* env, jobject /* app_context */, - jobject /* class_loader */) { - std::unique_ptr<gvr_context> context(new gvr_context); - - // Set cpu set to avoid default scheduling randomness. - dvrSetCpuPartition(0, "/application/performance"); - - context->jni_env_ = env; - context->pose_client_ = dvrPoseCreate(); - if (!context->pose_client_) { - ALOGE("Failed to create pose client"); - return nullptr; - } - - context->display_client_ = DisplayClient::Create(); - if (!context->display_client_) { - ALOGE("Failed to create display client"); - return nullptr; - } - - int ret = - context->display_client_->GetDisplayMetrics(&context->display_metrics_); - if (ret < 0) { - ALOGE("Failed to get display metrics: %d (%s)", ret, strerror(-ret)); - return nullptr; - } - - const float* left_fov = context->display_metrics_.left_fov_lrbt.data(); - context->left_eye_viewport_transform_ = - FovToViewportTransform(FovRadiansToDegrees( - gvr_rectf{left_fov[0], left_fov[1], left_fov[2], left_fov[3]})); - - const float* right_fov = context->display_metrics_.right_fov_lrbt.data(); - context->right_eye_viewport_transform_ = - FovToViewportTransform(FovRadiansToDegrees( - gvr_rectf{right_fov[0], right_fov[1], right_fov[2], right_fov[3]})); - - context->next_frame_6dof_pose_ = GvrIdentityMatrix(); - - for (int i = 0; i < kControllerCount; ++i) { - context->next_frame_controller_pose_[i] = GvrIdentityMatrix(); - } - - // Check the system property to force 6DoF when requested 3DoF. - char prop_buffer[PROP_VALUE_MAX]; - if (__system_property_get(kForce6DofProp, prop_buffer) && - (!strncasecmp("1", prop_buffer, PROP_VALUE_MAX) || - !strncasecmp("true", prop_buffer, PROP_VALUE_MAX))) { - context->force_6dof_ = true; - } - - return context.release(); -} - -gvr_version gvr_get_version() { - gvr_version version = {}; - version.major = GVR_SDK_MAJOR_VERSION; - version.minor = GVR_SDK_MINOR_VERSION; - version.patch = GVR_SDK_PATCH_VERSION; - return version; -} - -const char* gvr_get_version_string() { return kVersionString; } - -int32_t gvr_get_error(gvr_context* gvr) { return gvr->last_error_; } - -int32_t gvr_clear_error(gvr_context* gvr) { - int32_t last_error = gvr->last_error_; - gvr->last_error_ = GVR_ERROR_NONE; - return last_error; -} - -const char* gvr_get_error_string(int32_t error_code) { - switch (error_code) { - case GVR_ERROR_NONE: - return "No error"; - case GVR_ERROR_CONTROLLER_CREATE_FAILED: - return "Creation of GVR controller context failed"; - case GVR_ERROR_NO_FRAME_AVAILABLE: - return "No frame available in swap chain"; - case GVR_ERROR_INTERNAL: - return "Internal error"; - default: - return "(Internal error: unknown error code)"; - } -} - -const gvr_user_prefs* gvr_get_user_prefs(gvr_context* gvr) { - return &gvr->user_prefs_; -} - -int32_t gvr_user_prefs_get_controller_handedness( - const gvr_user_prefs* /* user_prefs */) { - return GVR_CONTROLLER_RIGHT_HANDED; -} - -gvr_context_::~gvr_context_() { - for (gvr_swap_chain* swap_chain : swap_chains_) - swap_chain->context = nullptr; - if (pose_client_) - dvrPoseDestroy(pose_client_); -} - -void gvr_destroy(gvr_context** gvr) { - if (!gvr || !(*gvr)) { - ALOGW("gvr_destroy: Invalid gvr_context pointer."); - return; - } - delete *gvr; - *gvr = nullptr; -} - -void gvr_initialize_gl(gvr_context* /* gvr */) {} - -bool gvr_get_async_reprojection_enabled(const gvr_context* /* gvr */) { - return true; -} - -void gvr_get_recommended_buffer_viewports( - const gvr_context* gvr, gvr_buffer_viewport_list* viewport_list) { - gvr_buffer_viewport left( - /*buffer_index*/ 0, - /*uv*/ {0, .5f, 0, 1}, gvr->left_eye_viewport_transform_, GVR_LEFT_EYE, - GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL); - - gvr_buffer_viewport right( - /*buffer_index*/ 0, - /*uv*/ {.5f, 1, 0, 1}, gvr->right_eye_viewport_transform_, GVR_RIGHT_EYE, - GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL); - - viewport_list->viewports.resize(2); - viewport_list->viewports[0] = left; - viewport_list->viewports[1] = right; -} - -void gvr_get_screen_buffer_viewports(const gvr_context* gvr, - gvr_buffer_viewport_list* viewport_list) { - gvr_get_recommended_buffer_viewports(gvr, viewport_list); -} - -gvr_sizei gvr_get_maximum_effective_render_target_size(const gvr_context* gvr) { - return gvr_sizei{ - static_cast<int32_t>(gvr->display_metrics_.distorted_width), - static_cast<int32_t>(gvr->display_metrics_.distorted_height)}; -} - -gvr_sizei gvr_get_screen_target_size(const gvr_context* gvr) { - // DisplayMetrics returns native_width and native_height for the display in - // portrait orientation, which our device is never in. Swap the width and - // height to account for this. - return gvr_sizei{ - static_cast<int32_t>(gvr->display_metrics_.display_native_height), - static_cast<int32_t>(gvr->display_metrics_.display_native_width)}; -} - -void gvr_set_surface_size(gvr_context* gvr, - gvr_sizei /* surface_size_pixels */) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_set_surface_size not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); -} - -void gvr_distort_to_screen( - gvr_context* gvr, int32_t /* texture_id */, - const gvr_buffer_viewport_list* /* viewport_list */, - gvr_mat4f /* head_space_from_start_space */, - gvr_clock_time_point /* target_presentation_time */) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_distort_to_screen not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); -} - -bool gvr_is_feature_supported(const gvr_context* /*gvr*/, int32_t feature) { - return feature == GVR_FEATURE_ASYNC_REPROJECTION || - feature == GVR_FEATURE_HEAD_POSE_6DOF; -} - -///////////////////////////////////////////////////////////////////////////// -// Viewports and viewport lists -///////////////////////////////////////////////////////////////////////////// - -bool gvr_buffer_viewport::operator==(const gvr_buffer_viewport_& other) const { - return buffer_index == other.buffer_index && uv == other.uv && - eye == other.eye && external_surface_id == other.external_surface_id && - reprojection == other.reprojection && - MatricesAlmostEqual(transform, other.transform, 1e-5f); -} - -gvr_buffer_viewport* gvr_buffer_viewport_create(gvr_context* /* gvr */) { - return new gvr_buffer_viewport; -} - -void gvr_buffer_viewport_destroy(gvr_buffer_viewport** viewport) { - if (viewport) { - delete *viewport; - *viewport = nullptr; - } -} - -gvr_rectf gvr_buffer_viewport_get_source_uv( - const gvr_buffer_viewport* viewport) { - return viewport->uv; -} - -void gvr_buffer_viewport_set_source_uv(gvr_buffer_viewport* viewport, - gvr_rectf uv) { - viewport->uv = uv; -} - -gvr_rectf gvr_buffer_viewport_get_source_fov( - const gvr_buffer_viewport* viewport) { - return ViewportTransformToFov(viewport->transform); -} - -void gvr_buffer_viewport_set_source_fov(gvr_buffer_viewport* viewport, - gvr_rectf fov) { - viewport->transform = FovToViewportTransform(fov); -} - -gvr_mat4f gvr_buffer_viewport_get_transform( - const gvr_buffer_viewport* viewport) { - return viewport->transform; -} - -void gvr_buffer_viewport_set_transform(gvr_buffer_viewport* viewport, - gvr_mat4f transform) { - viewport->transform = transform; -} - -int32_t gvr_buffer_viewport_get_target_eye( - const gvr_buffer_viewport* viewport) { - return viewport->eye; -} - -void gvr_buffer_viewport_set_target_eye(gvr_buffer_viewport* viewport, - int32_t index) { - viewport->eye = index; -} - -int32_t gvr_buffer_viewport_get_source_buffer_index( - const gvr_buffer_viewport* viewport) { - return viewport->buffer_index; -} - -void gvr_buffer_viewport_set_source_buffer_index(gvr_buffer_viewport* viewport, - int32_t buffer_index) { - viewport->buffer_index = buffer_index; -} - -int32_t gvr_buffer_viewport_get_external_surface_id( - const gvr_buffer_viewport* viewport) { - return viewport->external_surface_id; -} - -void gvr_buffer_viewport_set_external_surface_id(gvr_buffer_viewport* viewport, - int32_t external_surface_id) { - viewport->external_surface_id = external_surface_id; -} - -int32_t gvr_buffer_viewport_get_reprojection( - const gvr_buffer_viewport* viewport) { - return viewport->reprojection; -} - -void gvr_buffer_viewport_set_reprojection(gvr_buffer_viewport* viewport, - int32_t reprojection) { - viewport->reprojection = static_cast<gvr_reprojection>(reprojection); -} - -bool gvr_buffer_viewport_equal(const gvr_buffer_viewport* a, - const gvr_buffer_viewport* b) { - return *a == *b; -} - -gvr_buffer_viewport_list* gvr_buffer_viewport_list_create( - const gvr_context* /* gvr */) { - return new gvr_buffer_viewport_list; -} - -void gvr_buffer_viewport_list_destroy( - gvr_buffer_viewport_list** viewport_list) { - if (!viewport_list || !(*viewport_list)) { - ALOGW("gvr_buffer_viewport_list_destroy: Invalid list pointer."); - return; - } - delete *viewport_list; - *viewport_list = nullptr; -} - -size_t gvr_buffer_viewport_list_get_size( - const gvr_buffer_viewport_list* viewport_list) { - return viewport_list->viewports.size(); -} - -void gvr_buffer_viewport_list_get_item( - const gvr_buffer_viewport_list* viewport_list, size_t index, - gvr_buffer_viewport* viewport) { - *viewport = viewport_list->viewports[index]; -} - -void gvr_buffer_viewport_list_set_item(gvr_buffer_viewport_list* viewport_list, - size_t index, - const gvr_buffer_viewport* viewport) { - if (index < viewport_list->viewports.size()) - viewport_list->viewports[index] = *viewport; - else - viewport_list->viewports.push_back(*viewport); -} - -///////////////////////////////////////////////////////////////////////////// -// Swapchains and frames -///////////////////////////////////////////////////////////////////////////// - -gvr_buffer_spec* gvr_buffer_spec_create(gvr_context* /* gvr */) { - return new gvr_buffer_spec; -} - -void gvr_buffer_spec_destroy(gvr_buffer_spec** spec) { - if (spec) { - delete *spec; - *spec = nullptr; - } -} - -gvr_sizei gvr_buffer_spec_get_size(const gvr_buffer_spec* spec) { - return spec->size; -} - -void gvr_buffer_spec_set_size(gvr_buffer_spec* spec, gvr_sizei size) { - spec->size = size; -} - -int32_t gvr_buffer_spec_get_samples(const gvr_buffer_spec* spec) { - return spec->msaa_samples; -} - -void gvr_buffer_spec_set_samples(gvr_buffer_spec* spec, int32_t num_samples) { - spec->msaa_samples = num_samples; -} - -void gvr_buffer_spec_set_color_format(gvr_buffer_spec* spec, - int32_t color_format) { - spec->color_format = color_format; -} - -void gvr_buffer_spec_set_depth_stencil_format(gvr_buffer_spec* spec, - int32_t depth_stencil_format) { - spec->depth_stencil_format = depth_stencil_format; -} - -void gvr_buffer_spec_set_z_order(gvr_buffer_spec* spec, int z_order) { - spec->z_order = z_order; -} - -void gvr_buffer_spec_set_visibility(gvr_buffer_spec* spec, - int32_t visibility) { - spec->initially_visible = (visibility != GVR_INVISIBLE); -} - -void gvr_buffer_spec_set_blur_behind(gvr_buffer_spec* spec, - int32_t blur_behind) { - spec->blur_behind = (blur_behind != GVR_BLUR_BEHIND_FALSE); -} - -void gvr_buffer::SetDefaults() { - spec = gvr_buffer_spec(); - frame_buffer = 0; - color_render_buffer = 0; - depth_stencil_render_buffer = 0; - requested_size = {-1, -1}; -} - -gvr_buffer::gvr_buffer() { SetDefaults(); } - -gvr_buffer::gvr_buffer(gvr_context* gvr, const gvr_buffer_spec& spec_in, - GLuint texture_id, GLenum texture_target) { - SetDefaults(); - spec = spec_in; - - glGetError(); // Clear error state - glGenFramebuffers(1, &frame_buffer); - glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer); - - if (texture_id == 0) { - GLenum gl_color_format; - if (!GetGlColorFormat(spec.color_format, &gl_color_format)) { - ALOGE("Unknown color format: %d", spec.color_format); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - FreeGl(); - return; - } - - glGenRenderbuffers(1, &color_render_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, color_render_buffer); - if (spec.msaa_samples < 2) { - glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format, spec.size.width, - spec.size.height); - } else { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples, - gl_color_format, spec.size.width, - spec.size.height); - } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, color_render_buffer); - } else { - if (spec.msaa_samples < 2) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - texture_target, texture_id, 0); - } else { - glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - texture_target, texture_id, 0, - spec.msaa_samples); - } - } - - if (spec.depth_stencil_format != GVR_DEPTH_STENCIL_FORMAT_NONE) { - GLenum gl_depth_format; - if (!GetGlDepthFormat(spec.depth_stencil_format, &gl_depth_format)) { - ALOGE("Unknown depth/stencil format: %d", spec.depth_stencil_format); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - FreeGl(); - return; - } - - glGenRenderbuffers(1, &depth_stencil_render_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_render_buffer); - if (spec.msaa_samples < 2) { - glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format, spec.size.width, - spec.size.height); - } else { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples, - gl_depth_format, spec.size.width, - spec.size.height); - } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, depth_stencil_render_buffer); - } - - GLenum gl_error = glGetError(); - if (gl_error != GL_NO_ERROR) { - ALOGE("GL error after creating framebuffer: %d", gl_error); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - FreeGl(); - return; - } - - GLenum framebuffer_complete_result = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (framebuffer_complete_result != GL_FRAMEBUFFER_COMPLETE) { - ALOGE("Framebuffer setup failed. glCheckFramebufferStatus returned %d", - framebuffer_complete_result); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - FreeGl(); - return; - } -} - -void gvr_buffer::FreeGl() { - if (frame_buffer != 0) { - glDeleteFramebuffers(1, &frame_buffer); - frame_buffer = 0; - } - if (color_render_buffer != 0) { - glDeleteRenderbuffers(1, &color_render_buffer); - color_render_buffer = 0; - } - if (depth_stencil_render_buffer != 0) { - glDeleteRenderbuffers(1, &depth_stencil_render_buffer); - depth_stencil_render_buffer = 0; - } -} - -gvr_buffer::~gvr_buffer() { FreeGl(); } - -gvr_buffer::gvr_buffer(gvr_buffer&& other) { - spec = other.spec; - frame_buffer = other.frame_buffer; - color_render_buffer = other.color_render_buffer; - depth_stencil_render_buffer = other.depth_stencil_render_buffer; - requested_size = other.requested_size; - other.SetDefaults(); -} - -gvr_buffer& gvr_buffer::operator=(gvr_buffer&& other) { - if (this == &other) - return *this; - spec = other.spec; - frame_buffer = other.frame_buffer; - color_render_buffer = other.color_render_buffer; - depth_stencil_render_buffer = other.depth_stencil_render_buffer; - requested_size = other.requested_size; - other.SetDefaults(); - return *this; -} - -gvr_swap_chain* gvr_swap_chain_create(gvr_context* gvr, - const gvr_buffer_spec** buffers, - int32_t count) { - if (count == 0) { - ALOGE("At least one buffer must be requested"); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return nullptr; - } - - // We only support one buffer, but it's common for gvr apps to use more than - // one. Print an error to the log if the app requests more than one buffer, - // but continue on. We'll only render the first buffer in that case. - if (count > 1) { - ALOGE( - "Only one buffer is supported but the app requested %d." - " Only the first buffer will be rendered.", - count); - } - - std::unique_ptr<gvr_swap_chain> swap_chain(new gvr_swap_chain(gvr)); - - // The first buffer gets a DvrGraphicsContext, which contains the surface we - // pass to displayd for rendering. - swap_chain->buffers_.push_back(gvr_buffer()); - swap_chain->buffers_.back().spec = *buffers[0]; - if (!CreateDvrGraphicsContextAndGvrBuffer(swap_chain.get())) - return nullptr; - - // The rest of the buffers, which we don't render for now, get color render - // buffers. - for (int i = 1; i < count; ++i) { - swap_chain->buffers_.push_back( - gvr_buffer(gvr, *buffers[i], 0, GL_TEXTURE_2D)); - if (swap_chain->buffers_.back().frame_buffer == 0) - return nullptr; - } - - gvr->swap_chains_.push_back(swap_chain.get()); - return swap_chain.release(); -} - -gvr_swap_chain_::~gvr_swap_chain_() { - if (context) { - auto iter = std::find(std::begin(context->swap_chains_), - std::end(context->swap_chains_), this); - if (iter != context->swap_chains_.end()) - context->swap_chains_.erase(iter); - } - buffers_.clear(); - if (graphics_context_ != nullptr) - dvrGraphicsContextDestroy(graphics_context_); -} - -void gvr_swap_chain_destroy(gvr_swap_chain** swap_chain) { - if (!swap_chain || !(*swap_chain)) { - ALOGW("gvr_swap_chain_destroy: Invalid swap chain pointer."); - return; - } - delete *swap_chain; - *swap_chain = nullptr; -} - -int32_t gvr_swap_chain_get_buffer_count(const gvr_swap_chain* swap_chain) { - return swap_chain ? static_cast<int32_t>(swap_chain->buffers_.size()) : 0; -} - -gvr_sizei gvr_swap_chain_get_buffer_size(gvr_swap_chain* swap_chain, - int32_t index) { - if (!VerifyBufferIndex("gvr_swap_chain_get_buffer_size", swap_chain, index)) - return gvr_sizei{0, 0}; - - gvr_buffer& buf = swap_chain->buffers_[index]; - if (buf.requested_size != gvr_sizei{-1, -1}) - return buf.requested_size; - else - return buf.spec.size; -} - -void gvr_swap_chain_resize_buffer(gvr_swap_chain* swap_chain, int32_t index, - gvr_sizei size) { - if (!VerifyBufferIndex("gvr_swap_chain_resize_buffer", swap_chain, index)) - return; - - gvr_buffer& buf = swap_chain->buffers_[index]; - if (size != buf.spec.size) - buf.requested_size = size; - else - buf.requested_size = {-1, -1}; -} - -gvr_frame* gvr_swap_chain_acquire_frame(gvr_swap_chain* swap_chain) { - if (!swap_chain) - return nullptr; - - if (swap_chain->frame_acquired_) { - gvr_set_error(swap_chain->context, GVR_ERROR_NO_FRAME_AVAILABLE); - return nullptr; - } - - // Resize buffers if necessary - for (int i = 0; i < static_cast<int>(swap_chain->buffers_.size()); ++i) { - gvr_buffer& buf = swap_chain->buffers_[i]; - if (buf.requested_size != gvr_sizei{-1, -1}) { - if (!SwapChainResizeBuffer(swap_chain, i)) - return nullptr; - } - } - - // Only call gvr_wait_next_frame() if the app didn't call it already. - if (!swap_chain->wait_next_frame_called_by_app_) - WaitNextFrame(swap_chain, 0, nullptr, /*called_by_app*/ false); - - int ret = dvrBeginRenderFrame(swap_chain->graphics_context_); - if (ret < 0) { - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return nullptr; - } - - swap_chain->frame_acquired_ = true; - return GetFrameFromSwapChain(swap_chain); -} - -void gvr_frame_bind_buffer(gvr_frame* frame, int32_t index) { - gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame); - if (!VerifyBufferIndex("gvr_frame_bind_buffer", swap_chain, index)) - return; - glBindFramebuffer(GL_FRAMEBUFFER, swap_chain->buffers_[index].frame_buffer); -} - -void gvr_frame_unbind(gvr_frame* /* frame */) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -gvr_sizei gvr_frame_get_buffer_size(const gvr_frame* frame, int32_t index) { - const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame); - if (!VerifyBufferIndex("gvr_frame_get_buffer_size", swap_chain, index)) - return gvr_sizei{0, 0}; - return swap_chain->buffers_[index].spec.size; -} - -int32_t gvr_frame_get_framebuffer_object(const gvr_frame* frame, - int32_t index) { - const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame); - if (!VerifyBufferIndex("gvr_frame_get_framebuffer_object", swap_chain, index)) - return 0; - return swap_chain->buffers_[index].frame_buffer; -} - -void gvr_frame_submit(gvr_frame** frame, const gvr_buffer_viewport_list* list, - gvr_mat4f head_space_from_start_space) { - if (!frame) - return; - - gvr_swap_chain* swap_chain = GetSwapChainForFrame(*frame); - - if (!swap_chain->frame_acquired_) { - ALOGE("Frame was never acquired before being submitted"); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } - - *frame = nullptr; - swap_chain->frame_acquired_ = false; - - // Currently, support for arbitrary buffer viewport configs is very limited. - // We assume that the first two viewports have to be the recommended color - // buffer viewports, followed by pairs of external external buffer viewports - // for video rendering. - gvr_buffer_viewport_list supported_viewports; - gvr_get_recommended_buffer_viewports(swap_chain->context, - &supported_viewports); - for (size_t i = 0; i < supported_viewports.viewports.size(); ++i) { - if (i >= list->viewports.size() || - supported_viewports.viewports[i] != list->viewports[i]) { - ALOGE("Custom viewport configurations are not fully supported."); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } - } - - for (size_t i = supported_viewports.viewports.size(); - i < list->viewports.size(); ++i) { - int32_t external_surface_id = list->viewports[i].external_surface_id; - // Ignore additional custom buffer viewport for now, only those buffer - // viewports backed by external surfaces are supported. - // TODO(b/31442094, b/31771861, 28954457) Add full GVR buffer viewport - // support. - if (external_surface_id == GVR_EXTERNAL_SURFACE_ID_NONE) - continue; - - auto surface_it = swap_chain->external_surfaces_.find(external_surface_id); - if (surface_it == swap_chain->external_surfaces_.end()) { - ALOGE("Cannot find external_surface by id: %d.", external_surface_id); - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } - - // Pass the transfrom matrix of video mesh to displayd. - dvrGraphicsVideoMeshSurfacePresent( - swap_chain->graphics_context_, surface_it->second->video_surface, - list->viewports[i].eye, - GvrToEigenMatrix(list->viewports[i].transform).data()); - } - - float32x4_t pose_orientation, pose_translation; - GvrToDvrPose(head_space_from_start_space, &pose_orientation, - &pose_translation); - int ret = dvrSetEdsPose(swap_chain->graphics_context_, pose_orientation, - pose_translation); - if (ret < 0) - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - - ret = dvrPresent(swap_chain->graphics_context_); - if (ret < 0) { - gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL); - return; - } -} - -void gvr_bind_default_framebuffer(gvr_context* /* gvr */) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -///////////////////////////////////////////////////////////////////////////// -// Head tracking -///////////////////////////////////////////////////////////////////////////// - -gvr_clock_time_point gvr_get_time_point_now() { - return gvr_clock_time_point{GetSystemClockNs()}; -} - -gvr_mat4f gvr_get_head_space_from_start_space_rotation( - const gvr_context* gvr, const gvr_clock_time_point /* time */) { - // TODO(steventhomas): Implement prediction according to the supplied time - // value. - return gvr->force_6dof_ ? gvr->next_frame_6dof_pose_ - : Gvr6dofTo3dof(gvr->next_frame_6dof_pose_); -} - -gvr_mat4f gvr_apply_neck_model(const gvr_context* /* gvr */, - gvr_mat4f head_space_from_start_space_rotation, - float /* factor */) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_apply_neck_model not implemented."); - return head_space_from_start_space_rotation; -} - -// This is used to turn off sensors to save power. Not relevant for our all in -// one device. -void gvr_pause_tracking(gvr_context* /* gvr */) {} - -// This is used to turn on sensors. Not relevant for our all in one device. -void gvr_resume_tracking(gvr_context* /* gvr */) {} - -void gvr_reset_tracking(gvr_context* gvr) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_reset_tracking not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); -} - -void gvr_recenter_tracking(gvr_context* gvr) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_recenter_tracking not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); -} - -///////////////////////////////////////////////////////////////////////////// -// Head mounted display -///////////////////////////////////////////////////////////////////////////// - -bool gvr_set_default_viewer_profile(gvr_context* gvr, - const char* /* viewer_profile_uri */) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_set_default_viewer_profile not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return false; -} - -void gvr_refresh_viewer_profile(gvr_context* /* gvr */) {} - -const char* gvr_get_viewer_vendor(const gvr_context* /* gvr */) { - return kViewerVendor; -} - -const char* gvr_get_viewer_model(const gvr_context* /* gvr */) { - return kViewerModel; -} - -int32_t gvr_get_viewer_type(const gvr_context* /* gvr */) { - // TODO(leandrogracia): this needs to be properly implemented. - // In this case, we will probably need to define a new viewer type that - // has 6DoF support. - return GVR_VIEWER_TYPE_DAYDREAM; -} - -gvr_mat4f gvr_get_eye_from_head_matrix(const gvr_context* gvr, - const int32_t eye) { - float eye_mult = eye == GVR_LEFT_EYE ? 1 : -1; - return GvrTranslationMatrix( - .5f * eye_mult * gvr->display_metrics_.inter_lens_distance_m, 0, 0); -} - -gvr_recti gvr_get_window_bounds(const gvr_context* gvr) { - // Our app windows are always full screen - gvr_sizei screen_size = gvr_get_screen_target_size(gvr); - return gvr_recti{0, screen_size.width, 0, screen_size.height}; -} - -void gvr_compute_distorted_point(const gvr_context* /* gvr */, - const int32_t /* eye */, - const gvr_vec2f /* uv_in */, - gvr_vec2f /* uv_out */[3]) { - // TODO(leandrogracia): this needs to be properly implemented. - ALOGE("gvr_compute_distorted_point not implemented."); -} - -///////////////////////////////////////////////////////////////////////////// -// GVR API extension (from gvr_ext.h) -///////////////////////////////////////////////////////////////////////////// - -gvr_frame_schedule* gvr_frame_schedule_create() { - return new gvr_frame_schedule; -} - -void gvr_frame_schedule_destroy(gvr_frame_schedule** schedule) { - if (!schedule || !(*schedule)) { - ALOGW("gvr_frame_schedule_destroy: Invalid frame schedule pointer."); - return; - } - delete *schedule; - *schedule = nullptr; -} - -uint32_t gvr_frame_schedule_get_vsync_count(gvr_frame_schedule* schedule) { - return schedule->vsync_count; -} - -gvr_clock_time_point gvr_frame_schedule_get_scheduled_finish( - gvr_frame_schedule* schedule) { - return schedule->scheduled_finish; -} - -void gvr_wait_next_frame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos, - gvr_frame_schedule* out_next_frame_schedule) { - WaitNextFrame(swap_chain, start_delay_nanos, out_next_frame_schedule, - /*called_by_app*/ true); -} - -gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr, - uint32_t vsync_count) { - DvrPoseAsync pose; - int ret = dvrPoseGet(gvr->pose_client_, vsync_count, &pose); - if (ret < 0) { - ALOGW("dvrPoseGet failed: %d", ret); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return GvrIdentityMatrix(); - } - - return PosefToGvrMatrix(ToPosef(pose)); -} - -gvr_mat4f gvr_get_head_space_from_start_space_pose( - gvr_context* gvr, const gvr_clock_time_point /* time */) { - // TODO(leandrogracia): implement prediction based on the provided time. - // We need to do the same for the 3dof version too. - return gvr->next_frame_6dof_pose_; -} - -void gvr_swap_chain_set_z_order(const gvr_swap_chain* swap_chain, int z_order) { - dvrGraphicsSurfaceSetZOrder(swap_chain->graphics_context_, z_order); -} - -bool gvr_experimental_register_perf_event_callback( - gvr_context* gvr, int* /* out_handle */, void* /* user_data */, - void (* /* event_callback */)(void*, int, float)) { - ALOGE("gvr_experimental_register_perf_event_callback not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return false; -} - -bool gvr_experimental_unregister_perf_event_callback(gvr_context* gvr, - int /* handle */) { - ALOGE("gvr_experimental_unregister_perf_event_callback not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return false; -} - -const gvr_analytics* gvr_get_analytics(gvr_context* gvr) { - ALOGE("gvr_get_analytics not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); - return nullptr; -} - -const gvr_analytics_sample* gvr_analytics_create_sample( - const gvr_analytics* analytics) { - ALOGE("gvr_analytics_create_sample not implemented."); - return nullptr; -} - -const char* gvr_analytics_sample_get_buffer(const gvr_analytics_sample* sample) { - ALOGE("gvr_analytics_sample_get_buffer not implemented."); - return nullptr; -} - -size_t gvr_analytics_sample_get_buffer_length( - const gvr_analytics_sample* sample) { - ALOGE("gvr_analytics_sample_get_buffer_length not implemented."); - return 0; -} - -void gvr_analytics_destroy_sample(const gvr_analytics_sample** sample) { - ALOGE("gvr_analytics_destroy_sample not implemented."); -} - -bool gvr_user_prefs_get_performance_monitoring_enabled( - const gvr_user_prefs* /* user_prefs */) { - ALOGW("gvr_user_prefs_get_performance_monitoring_enabled not implemented."); - return false; -} - -void gvr_enable_context_sharing(gvr_context* gvr, - gvr_egl_context_listener /* handler */, - void* /* user_data */) { - ALOGW("gvr_enable_context_sharing not implemented."); - gvr_set_error(gvr, GVR_ERROR_INTERNAL); -} - -gvr_mat4f gvr_get_start_space_from_controller_space_pose( - gvr_context* gvr, int controller_id, - const gvr_clock_time_point /* time */) { - if (controller_id < 0 || controller_id >= kControllerCount) { - return GvrIdentityMatrix(); - } - - // TODO(leandrogracia): implement prediction based on the provided time. - // We need to do the same for the 3dof version too. - return gvr->next_frame_controller_pose_[controller_id]; -} - -gvr_external_surface* gvr_external_surface_create(gvr_context* context) { - // A |gvr_external_surface| is bound to a DVR Graphics context at the - // moment, which means we need an |gvr_swap_chain| created prior to the call - // of |gvr_external_surface_create|. Check whether the current GVR context - // has |gvr_swap_chain| created. Fail if there is no swap chain created - // already. - if (context->swap_chains_.empty()) { - ALOGE("gvr_external_surface_create: No swapchain has been created yet."); - return nullptr; - } - - // In case there are multiple swap chains in the context, the first is - // implicitly chosen. Actually, this should not happen as current scanline - // racing based GVR implementation only supports single swap chain per GVR - // context. - if (context->swap_chains_.size() > 1) { - ALOGW("gvr_external_surface_create: Multiple swap chains detected. " - "Choosing the first one but this may yield unexpected results."); - } - gvr_swap_chain* swap_chain = context->swap_chains_[0]; - DvrVideoMeshSurface* video_surface = dvrGraphicsVideoMeshSurfaceCreate( - swap_chain->graphics_context_); - - if (video_surface == nullptr) { - ALOGE("gvr_external_surface_create: Failed to create video mesh surface."); - return nullptr; - } - - gvr_external_surface* surface = new gvr_external_surface; - surface->id = swap_chain->next_external_surface_id_++; - surface->swap_chain = swap_chain; - surface->video_surface = video_surface; - - // Insert the surface into a lookup table in swap_chain. This will be - // needed to by the external_surface_id in |gvr_buffer_viewport|. - swap_chain->external_surfaces_.insert({surface->id, surface}); - return surface; -} - -void gvr_external_surface_destroy(gvr_external_surface** surface) { - if (!surface || !(*surface)) { - ALOGW("gvr_external_surface_destroy: Invalid external surface pointer."); - return; - } - - (*surface)->swap_chain->external_surfaces_.erase((*surface)->id); - if ((*surface)->video_surface != nullptr) { - dvrGraphicsVideoMeshSurfaceDestroy((*surface)->video_surface); - } - - delete *surface; - *surface = nullptr; -} - -void* gvr_external_surface_get_surface(const gvr_external_surface* surface) { - LOG_ALWAYS_FATAL_IF(surface->swap_chain == nullptr || - surface->swap_chain->context == nullptr || - surface->swap_chain->context->jni_env_ == nullptr, - "gvr_external_surface_get_surface: Surface must be " - "constructed within a JNIEnv. Check |gvr_create| call."); - - LOG_ALWAYS_FATAL_IF(surface->video_surface == nullptr, - "gvr_external_surface_get_surface: Invalid surface."); - - std::shared_ptr<android::dvr::ProducerQueue> producer_queue = - surface->video_surface->client->GetProducerQueue(); - std::shared_ptr<android::dvr::BufferHubQueueCore> core = - android::dvr::BufferHubQueueCore::Create(producer_queue); - - return android_view_Surface_createFromIGraphicBufferProducer( - surface->swap_chain->context->jni_env_, - new android::dvr::BufferHubQueueProducer(core)); -} - -int32_t gvr_external_surface_get_surface_id( - const gvr_external_surface* surface) { - return surface->id; -} diff --git a/libs/vr/libgvr/shim_gvr_controller.cpp b/libs/vr/libgvr/shim_gvr_controller.cpp deleted file mode 100644 index 0f5590329a..0000000000 --- a/libs/vr/libgvr/shim_gvr_controller.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#define LOG_TAG "libgvr_controller_shim" - -#include <log/log.h> -#include <vr/gvr/capi/include/gvr_controller.h> -#include <vr/gvr/capi/include/gvr_types.h> - -gvr_controller_context* gvr_controller_create_and_init(int32_t options, - gvr_context* context) { - ALOGE("gvr_controller_create_and_init not implemented."); - return nullptr; -} - -gvr_controller_context* gvr_controller_create_and_init_android( - JNIEnv* env, jobject android_context, jobject class_loader, int32_t options, - gvr_context* context) { - ALOGE("gvr_controller_create_and_init_android not implemented."); - return nullptr; -} - -void gvr_controller_destroy(gvr_controller_context** api) { - ALOGE("gvr_controller_destroy not implemented."); -} - -gvr_controller_state* gvr_controller_state_create() { - ALOGE("gvr_controller_state_create not implemented."); - return nullptr; -} - -void gvr_controller_state_destroy(gvr_controller_state** state) { - ALOGE("gvr_controller_state_destroy not implemented."); -} - -void gvr_controller_state_update(gvr_controller_context* api, int32_t flags, - gvr_controller_state* out_state) { - ALOGE("gvr_controller_state_update not implemented."); -} - -int64_t gvr_controller_state_get_last_button_timestamp( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_last_button_timestamp not implemented."); - return 0; -} - -bool gvr_controller_state_get_button_state(const gvr_controller_state* state, - int32_t button) { - ALOGE("gvr_controller_state_get_button_state not implemented."); - return false; -} - -bool gvr_controller_state_get_button_down(const gvr_controller_state* state, - int32_t button) { - ALOGE("gvr_controller_state_get_button_down not implemented."); - return false; -} - -bool gvr_controller_state_get_button_up(const gvr_controller_state* state, - int32_t button) { - ALOGE("gvr_controller_state_get_button_up not implemented."); - return false; -} - -bool gvr_controller_state_is_touching(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_is_touching not implemented."); - return false; -} - -gvr_vec2f gvr_controller_state_get_touch_pos( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_touch_pos not implemented."); - return {0.0f, 0.0f}; -} - -bool gvr_controller_state_get_touch_down(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_touch_down not implemented."); - return false; -} - -bool gvr_controller_state_get_touch_up(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_touch_up not implemented."); - return false; -} - -int64_t gvr_controller_state_get_last_touch_timestamp( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_last_touch_timestamp not implemented."); - return 0; -} - -gvr_quatf gvr_controller_state_get_orientation( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_orientation not implemented."); - return {0.0f, 0.0f, 0.0f, 0.0f}; -} - -int64_t gvr_controller_state_get_last_orientation_timestamp( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_last_orientation_timestamp not implemented."); - return 0; -} - -const char* gvr_controller_api_status_to_string(int32_t status) { - ALOGE("gvr_controller_api_status_to_string not implemented."); - return nullptr; -} - -const char* gvr_controller_connection_state_to_string(int32_t state) { - ALOGE("gvr_controller_connection_state_to_string not implemented."); - return nullptr; -} - -const char* gvr_controller_button_to_string(int32_t button) { - ALOGE("gvr_controller_button_to_string not implemented."); - return nullptr; -} - -int32_t gvr_controller_get_default_options() { - ALOGE("gvr_controller_get_default_options not implemented."); - return 0; -} - -void gvr_controller_pause(gvr_controller_context* api) { - ALOGE("gvr_controller_pause not implemented."); -} - -void gvr_controller_resume(gvr_controller_context* api) { - ALOGE("gvr_controller_resume not implemented."); -} - -int32_t gvr_controller_state_get_api_status(const gvr_controller_state* state) { - return GVR_CONTROLLER_API_OK; -} - -int32_t gvr_controller_state_get_connection_state( - const gvr_controller_state* state) { - return GVR_CONTROLLER_CONNECTED; -} - -gvr_vec3f gvr_controller_state_get_gyro(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_gyro not implemented."); - return {0.0, 0.0, 0.0}; -} - -gvr_vec3f gvr_controller_state_get_accel(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_accel not implemented."); - return {0.0, 0.0, 0.0}; -} - -int64_t gvr_controller_state_get_last_gyro_timestamp( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_last_gyro_timestamp not implemented."); - return 0; -} - -int64_t gvr_controller_state_get_last_accel_timestamp( - const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_last_accel_timestamp not implemented."); - return 0; -} - -bool gvr_controller_state_get_recentered(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_recentered not implemented."); - return false; -} - -bool gvr_controller_state_get_recentering(const gvr_controller_state* state) { - ALOGE("gvr_controller_state_get_recentering not implemented."); - return false; -} diff --git a/libs/vr/libgvr/shim_gvr_private.cpp b/libs/vr/libgvr/shim_gvr_private.cpp deleted file mode 100644 index 25a5110303..0000000000 --- a/libs/vr/libgvr/shim_gvr_private.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#define LOG_TAG "libgvr_shim_private" - -#include <log/log.h> -#include <private/dvr/display_rpc.h> -#include <private/dvr/internal_types.h> -#include <vr/gvr/capi/include/gvr.h> -#include <vr/gvr/capi/src/gvr_private.h> - -#include <pdx/rpc/remote_method.h> -#include "deviceparams/CardboardDevice.nolite.pb.h" - -bool gvr_set_async_reprojection_enabled(gvr_context* /* gvr */, - bool /* enabled */) { - return true; -} - -void gvr_on_surface_created_reprojection_thread(gvr_context* /* gvr */) {} - -void gvr_render_reprojection_thread(gvr_context* /* gvr */) {} - -void gvr_on_pause_reprojection_thread(gvr_context* /* gvr */) {} - -void gvr_update_surface_reprojection_thread( - gvr_context* /* gvr */, int32_t /* surface_id */, int32_t /* texture_id */, - gvr_clock_time_point /* timestamp */, gvr_mat4f /* surface_transform */) { - ALOGE("gvr_update_surface_reprojection_thread not implemented"); -} - -void gvr_remove_all_surfaces_reprojection_thread(gvr_context* /* gvr */) { - ALOGE("gvr_remove_all_surfaces_reprojection_thread not implemented"); -} - -void gvr_reconnect_sensors(gvr_context* /* gvr */) { - ALOGE("gvr_reconnect_sensors not implemented"); -} - -bool gvr_set_viewer_params(gvr_context* gvr, - const void* serialized_viewer_params, - size_t serialized_viewer_params_size_bytes) { - std::string serialized_device_params_string( - reinterpret_cast<const char*>(serialized_viewer_params), - serialized_viewer_params_size_bytes); - std::unique_ptr<proto::DeviceParams> device_params(new proto::DeviceParams); - if (!device_params->ParseFromString(serialized_device_params_string)) { - ALOGE("Invalid serialized Cardboard DeviceParams"); - return false; - } - - android::dvr::ViewerParams viewer_params; - - viewer_params.screen_to_lens_distance = - device_params->screen_to_lens_distance(); - viewer_params.inter_lens_distance = device_params->inter_lens_distance(); - for (int i = 0; i < device_params->left_eye_field_of_view_angles_size(); - ++i) { - viewer_params.left_eye_field_of_view_angles.push_back( - device_params->left_eye_field_of_view_angles(i)); - } - - viewer_params.vertical_alignment = - static_cast<android::dvr::ViewerParams::VerticalAlignmentType>( - device_params->vertical_alignment()); - viewer_params.tray_to_lens_distance = device_params->tray_to_lens_distance(); - - // TODO(hendrikw) Leave the g and b coefficients empty until we support - // chromatic aberration correction. - for (int i = 0; i < device_params->distortion_coefficients_size(); ++i) { - viewer_params.distortion_coefficients_r.push_back( - device_params->distortion_coefficients(i)); - } - - viewer_params.screen_center_to_lens_distance = - viewer_params.inter_lens_distance / 2.0; - if (device_params->has_internal()) { - for (int i = 0; i < device_params->internal().eye_orientations_size(); - ++i) { - viewer_params.eye_orientations.push_back( - static_cast<android::dvr::ViewerParams::EyeOrientation>( - device_params->internal().eye_orientations(i))); - } - - if (device_params->internal().has_screen_center_to_lens_distance()) - viewer_params.screen_center_to_lens_distance = - device_params->internal().screen_center_to_lens_distance(); - } - - if (device_params->has_daydream_internal()) { - viewer_params.daydream_internal.version = - device_params->daydream_internal().version(); - for (int i = 0; - i < device_params->daydream_internal().alignment_markers_size(); ++i) { - viewer_params.daydream_internal.alignment_markers.push_back( - {device_params->daydream_internal().alignment_markers(i).horizontal(), - device_params->daydream_internal().alignment_markers(i).vertical()}); - } - } - - gvr->display_client_->SetViewerParams(viewer_params); - return true; -} - -void gvr_set_lens_offset(gvr_context* /* gvr */, gvr_vec2f /* offset */) { - ALOGE("gvr_set_lens_offset not implemented"); -} - -void gvr_set_display_metrics(gvr_context* /* gvr */, - gvr_sizei /* size_pixels */, - gvr_vec2f /* meters_per_pixel */, - float /* border_size_meters */) { - ALOGE("gvr_set_display_metrics not implemented"); -} - -void gvr_set_display_output_rotation(gvr_context* /* gvr */, - int /* display_output_rotation */) { - ALOGE("gvr_set_display_output_rotation not implemented"); -} - -float gvr_get_border_size_meters(const gvr_context* /* gvr */) { - ALOGE("gvr_get_border_size_meters not implemented"); - return 0.0f; -} - -bool gvr_check_surface_size_changed(gvr_context* /* gvr */) { return false; } - -gvr_sizei gvr_get_surface_size(const gvr_context* /* gvr */) { - ALOGE("gvr_get_surface_size not implemented"); - return {0, 0}; -} - -void gvr_set_back_gesture_event_handler(gvr_context* /* gvr */, - event_handler /* handler */, - void* /* user_data */) { - ALOGE("gvr_set_back_gesture_event_handler not implemented"); -} - -gvr_tracker_state* gvr_pause_tracking_get_state(gvr_context* /* gvr */) { - ALOGE("gvr_pause_tracking_get_state not implemented"); - return nullptr; -} - -void gvr_resume_tracking_set_state(gvr_context* /* gvr */, - gvr_tracker_state* /* tracker_state */) { - ALOGE("gvr_resume_tracking_set_state not implemented"); -} - -void gvr_set_ignore_manual_tracker_pause_resume(gvr_context* /* gvr */, - bool /* should_ignore */) { - ALOGE("gvr_set_ignore_manual_tracker_pause_resume not implemented"); -} - -gvr_tracker_state* gvr_tracker_state_create( - const char* /* tracker_state_buffer */, size_t /* buf_size */) { - ALOGE("gvr_tracker_state_create not implemented"); - return nullptr; -} - -size_t gvr_tracker_state_get_buffer_size( - gvr_tracker_state* /* tracker_state */) { - ALOGE("gvr_tracker_state_get_buffer_size not implemented"); - return 0; -} - -const char* gvr_tracker_state_get_buffer( - gvr_tracker_state* /* tracker_state */) { - ALOGE("gvr_tracker_state_get_buffer not implemented"); - return nullptr; -} - -void gvr_tracker_state_destroy(gvr_tracker_state** /* tracker_state */) { - ALOGE("gvr_tracker_state_destroy not implemented"); -} - -gvr_display_synchronizer* gvr_display_synchronizer_create() { - // We don't actually support (or need) any of the synchronizer functionality, - // but if we return null here the gvr setup code in the app fails. Instead - // return a dummy object that does nothing, which allows gvr apps to work. - return new gvr_display_synchronizer; -} - -void gvr_display_synchronizer_destroy(gvr_display_synchronizer** synchronizer) { - if (synchronizer) { - delete *synchronizer; - *synchronizer = nullptr; - } -} - -void gvr_display_synchronizer_reset( - gvr_display_synchronizer* /* synchronizer */, - int64_t /* expected_interval_nanos */, int64_t /* vsync_offset_nanos */) {} - -void gvr_display_synchronizer_update( - gvr_display_synchronizer* /* synchronizer */, - gvr_clock_time_point /* vsync_time */, int32_t /* rotation */) {} - -void gvr_set_display_synchronizer( - gvr_context* /* gvr */, gvr_display_synchronizer* /* synchronizer */) {} - -void gvr_set_error(gvr_context* gvr, int32_t error_code) { - if (gvr->last_error_ != GVR_ERROR_NONE) { - ALOGW("Overwriting existing error code: %d (%s)", gvr->last_error_, - gvr_get_error_string(gvr->last_error_)); - } - gvr->last_error_ = error_code; -} - -void gvr_pause(gvr_context* gvr) { - if (gvr == nullptr) { - ALOGW("gvr_pause called with a null gvr_context. This is a bug."); - return; - } - for (gvr_swap_chain* swap_chain : gvr->swap_chains_) { - if (swap_chain->graphics_context_) - dvrGraphicsSurfaceSetVisible(swap_chain->graphics_context_, 0); - } -} - -void gvr_resume(gvr_context* gvr) { - if (gvr == nullptr) { - ALOGW("gvr_resume called with a null gvr_context. This is a bug."); - return; - } - for (gvr_swap_chain* swap_chain : gvr->swap_chains_) { - if (swap_chain->graphics_context_) - dvrGraphicsSurfaceSetVisible(swap_chain->graphics_context_, 1); - } -} - -void gvr_dump_debug_data(gvr_context* /* gvr */) {} - -bool gvr_using_vr_display_service(gvr_context* /* gvr */) { return true; } - -void gvr_request_context_sharing(gvr_context* /* gvr */, - gvr_egl_context_listener /* handler */, - void* /* user_data */) {} diff --git a/services/vr/vr_manager/Android.mk b/libs/vr/libvr_manager/Android.mk index 54b1c1a2db..e9987f7020 100644 --- a/services/vr/vr_manager/Android.mk +++ b/libs/vr/libvr_manager/Android.mk @@ -14,11 +14,16 @@ LOCAL_PATH := $(call my-dir) +exported_include_dirs := \ + $(LOCAL_PATH)/include + +include_dirs := \ + frameworks/native/include/vr/vr_manager \ + $(exported_include_dirs) + src_files := \ vr_manager.cpp \ - -inc_files := \ - frameworks/native/include/vr/vr_manager + trusted_uids.cpp static_libs := \ libutils \ @@ -26,13 +31,12 @@ static_libs := \ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(src_files) -LOCAL_C_INCLUDES := $(inc_files) +LOCAL_C_INCLUDES := $(include_dirs) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(exported_include_dirs) LOCAL_CFLAGS += -Wall LOCAL_CFLAGS += -Werror LOCAL_CFLAGS += -Wunused LOCAL_CFLAGS += -Wunreachable-code -LOCAL_EXPORT_C_INCLUDE_DIRS := $(inc_files) -#LOCAL_SHARED_LIBRARIES := $(sharedLibraries) LOCAL_STATIC_LIBRARIES := $(static_libs) LOCAL_MODULE := libvr_manager include $(BUILD_STATIC_LIBRARY) diff --git a/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h b/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h new file mode 100644 index 0000000000..4496fbff7a --- /dev/null +++ b/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h @@ -0,0 +1,33 @@ +#ifndef ANDROID_DVR_TRUSTED_UIDS_H_ +#define ANDROID_DVR_TRUSTED_UIDS_H_ + +#include <sys/types.h> + +namespace android { +namespace dvr { + +/** + * Tells if a provided UID can be trusted to access restricted VR APIs. + * + * UID trust is based on the android.permission.RESTRICTED_VR_ACCESS permission. + * AID_SYSTEM and AID_ROOT are automatically trusted by Android. + * + * UIDs are guaranteed not to be reused until the next reboot even in case + * of package reinstall. For performance reasons this method caches results by + * default, as otherwise every check would trigger a Java call. + * + * This function is thread-safe. + * + * @param uid The uid to check. + * @param use_cache If true any cached result for the provided uid will be + * reused. If false this call will reach the Application Manager Service + * in Java to get updated values. Any updates will be stored in the cache. + * @return true if the uid is trusted, false if not or if the VR Manager Service + * could not be reached to verify the uid. + */ +bool IsTrustedUid(uid_t uid, bool use_cache = true); + +} // namespace dvr +} // namespace android + +#endif // ANDROID_DVR_TRUSTED_UIDS_H_ diff --git a/libs/vr/libvr_manager/trusted_uids.cpp b/libs/vr/libvr_manager/trusted_uids.cpp new file mode 100644 index 0000000000..4228a050db --- /dev/null +++ b/libs/vr/libvr_manager/trusted_uids.cpp @@ -0,0 +1,51 @@ +#include "private/dvr/trusted_uids.h" + +#include <mutex> +#include <unordered_map> + +#include <binder/IPermissionController.h> +#include <binder/IServiceManager.h> +#include <private/android_filesystem_config.h> +#include <utils/String16.h> +#include <vr/vr_manager/vr_manager.h> + +namespace android { +namespace dvr { + +bool IsTrustedUid(uid_t uid, bool use_cache) { + static std::unordered_map<uid_t, bool> uid_cache; + static std::mutex uid_cache_mutex; + + // Whitelist requests from the system UID. + // These are already whitelisted by the permission service, but it might not + // be available if the ActivityManagerService is up during boot. + // This ensures the correct result for system services while booting up. + if (uid == AID_SYSTEM) + return true; + + std::lock_guard<std::mutex> lock(uid_cache_mutex); + + if (use_cache) { + auto it = uid_cache.find(uid); + if (it != uid_cache.end()) + return it->second; + } + + sp<IBinder> binder = defaultServiceManager()->getService(String16("permission")); + if (binder == 0) { + ALOGW("Could not access permission service"); + return false; + } + + // Note: we ignore the pid because it's only used to automatically reply + // true if the caller is the Activity Manager Service. + bool trusted = interface_cast<IPermissionController>(binder)->checkPermission( + String16("android.permission.RESTRICTED_VR_ACCESS"), -1, uid); + + // Cache the information for this uid to avoid future Java calls. + uid_cache[uid] = trusted; + return trusted; +} + +} // namespace dvr +} // namespace android diff --git a/services/vr/vr_manager/vr_manager.cpp b/libs/vr/libvr_manager/vr_manager.cpp index d24cbb5a1a..d24cbb5a1a 100644 --- a/services/vr/vr_manager/vr_manager.cpp +++ b/libs/vr/libvr_manager/vr_manager.cpp diff --git a/libs/vr/libvrflinger/Android.mk b/libs/vr/libvrflinger/Android.mk index 6b5e7cc88e..1706f30cd7 100644 --- a/libs/vr/libvrflinger/Android.mk +++ b/libs/vr/libvrflinger/Android.mk @@ -45,6 +45,7 @@ staticLibraries := \ libperformance \ libsensor \ libpdx_default_transport \ + libvr_manager \ sharedLibraries := \ android.dvr.composer@1.0 \ @@ -76,11 +77,6 @@ LOCAL_CFLAGS += -DLOG_TAG=\"vr_flinger\" LOCAL_CFLAGS += -DTRACE=0 LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -ifeq ($(TARGET_USES_QCOM_BSP), true) - LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc - LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils - LOCAL_SHARED_LIBRARIES += libqdutils -endif LOCAL_SHARED_LIBRARIES := $(sharedLibraries) LOCAL_WHOLE_STATIC_LIBRARIES := $(staticLibraries) LOCAL_MODULE := libvrflinger diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp index c464c983c0..5309acf9d3 100644 --- a/libs/vr/libvrflinger/display_service.cpp +++ b/libs/vr/libvrflinger/display_service.cpp @@ -318,6 +318,10 @@ int DisplayService::UpdateActiveDisplaySurfaces() { return hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces)); } +void DisplayService::OnHardwareComposerRefresh() { + hardware_composer_.OnHardwareComposerRefresh(); +} + void DisplayService::SetDisplayConfigurationUpdateNotifier( DisplayConfigurationUpdateNotifier update_notifier) { update_notifier_ = update_notifier; diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h index ebd97de2fa..5de4f1de72 100644 --- a/libs/vr/libvrflinger/display_service.h +++ b/libs/vr/libvrflinger/display_service.h @@ -68,6 +68,8 @@ class DisplayService : public pdx::ServiceBase<DisplayService> { } } + void OnHardwareComposerRefresh(); + private: friend BASE; friend DisplaySurface; diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index 5253b26051..e6ed66589f 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -1287,6 +1287,10 @@ void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/, // TODO(eieio): implement display hotplug callbacks. } +void HardwareComposer::OnHardwareComposerRefresh() { + // TODO(steventhomas): Handle refresh. +} + void HardwareComposer::SetBacklightBrightness(int brightness) { if (backlight_brightness_fd_) { std::array<char, 32> text; diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h index 33f090d27e..b6aa807e19 100644 --- a/libs/vr/libvrflinger/hardware_composer.h +++ b/libs/vr/libvrflinger/hardware_composer.h @@ -224,6 +224,8 @@ class HardwareComposer { Compositor* GetCompositor() { return &compositor_; } + void OnHardwareComposerRefresh(); + private: int32_t EnableVsync(bool enabled); diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h index 04c836378d..17dce96870 100644 --- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h +++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h @@ -21,6 +21,7 @@ class VrFlinger { void EnterVrMode(); void ExitVrMode(); + void OnHardwareComposerRefresh(); private: std::thread displayd_thread_; diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp index e17494386f..fd1c5820e7 100644 --- a/libs/vr/libvrflinger/screenshot_service.cpp +++ b/libs/vr/libvrflinger/screenshot_service.cpp @@ -3,7 +3,9 @@ #include <utils/Trace.h> #include <pdx/default_transport/service_endpoint.h> +#include <private/android_filesystem_config.h> #include <private/dvr/display_types.h> +#include <private/dvr/trusted_uids.h> using android::pdx::Message; using android::pdx::MessageInfo; @@ -40,6 +42,12 @@ int ScreenshotService::OnGetFormat(pdx::Message&) { ScreenshotData ScreenshotService::OnTakeScreenshot(pdx::Message& message, int layer_index) { + // Also allow AID_SHELL to support vrscreencap commands. + if (message.GetEffectiveUserId() != AID_SHELL && + !IsTrustedUid(message.GetEffectiveUserId())) { + REPLY_ERROR_RETURN(message, EACCES, {}); + } + AddWaiter(std::move(message), layer_index); return {}; } diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp index 82ce0678ac..9163e71f79 100644 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ b/libs/vr/libvrflinger/vr_flinger.cpp @@ -106,5 +106,13 @@ void VrFlinger::ExitVrMode() { } } +void VrFlinger::OnHardwareComposerRefresh() { + if (display_service_) { + display_service_->OnHardwareComposerRefresh(); + } else { + ALOGE("OnHardwareComposerRefresh failed : Display service is not started."); + } +} + } // namespace dvr } // namespace android diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 027c18d8cc..df84c934de 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -619,6 +619,16 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (co #endif #endif +#ifndef EGL_ANDROID_get_native_client_buffer +#define EGL_ANDROID_get_native_client_buffer 1 +struct AHardwareBuffer; +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const AHardwareBuffer *buffer); +#else +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const AHardwareBuffer *buffer); +#endif +#endif + #ifndef EGL_ANDROID_front_buffer_auto_refresh #define EGL_ANDROID_front_buffer_auto_refresh 1 #define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C @@ -632,22 +642,31 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (co #ifndef EGL_ANDROID_get_frame_timestamps #define EGL_ANDROID_get_frame_timestamps 1 #define EGL_TIMESTAMPS_ANDROID 0x314D -#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E -#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F -#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150 -#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151 -#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152 -#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153 -#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154 -#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155 -#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156 -#define EGL_READS_DONE_TIME_ANDROID 0x3157 +#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E +#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F +#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150 +#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151 +#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152 +#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153 +#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154 +#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155 +#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156 +#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157 +#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158 +#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3159 +#define EGL_READS_DONE_TIME_ANDROID 0x315A #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); -EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); +EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values); +EGLAPI EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint name); +EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +EGLAPI EGLBoolean eglGetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #else -typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); #endif #endif diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 2782ed7a7d..ef3d7a3fa2 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -27,6 +27,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> +#include <android/hardware_buffer.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <cutils/memory.h> @@ -56,8 +57,6 @@ using namespace android; -#define ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS 0 - // ---------------------------------------------------------------------------- namespace android { @@ -87,10 +86,9 @@ extern char const * const gBuiltinExtensionString = "EGL_ANDROID_presentation_time " "EGL_KHR_swap_buffers_with_damage " "EGL_ANDROID_create_native_client_buffer " + "EGL_ANDROID_get_native_client_buffer " "EGL_ANDROID_front_buffer_auto_refresh " -#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS "EGL_ANDROID_get_frame_timestamps " -#endif ; extern char const * const gExtensionString = "EGL_KHR_image " // mandatory @@ -182,10 +180,14 @@ static const extention_map_t sExtensionMap[] = { { "eglSwapBuffersWithDamageKHR", (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, - // EGL_ANDROID_native_client_buffer + // EGL_ANDROID_create_native_client_buffer { "eglCreateNativeClientBufferANDROID", (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID }, + // EGL_ANDROID_get_native_client_buffer + { "eglGetNativeClientBufferANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID }, + // EGL_KHR_partial_update { "eglSetDamageRegionKHR", (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, @@ -216,10 +218,16 @@ static const extention_map_t sExtensionMap[] = { (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, // EGL_ANDROID_get_frame_timestamps + { "eglGetNextFrameIdANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, + { "eglGetCompositorTimingANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID }, + { "eglGetCompositorTimingSupportedANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID }, { "eglGetFrameTimestampsANDROID", (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, - { "eglQueryTimestampSupportedANDROID", - (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID }, + { "eglGetFrameTimestampSupportedANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID }, }; /* @@ -1240,7 +1248,6 @@ EGLBoolean eglSurfaceAttrib( setError(EGL_BAD_SURFACE, EGL_FALSE); } -#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS if (attribute == EGL_TIMESTAMPS_ANDROID) { if (!s->win.get()) { return setError(EGL_BAD_SURFACE, EGL_FALSE); @@ -1250,7 +1257,6 @@ EGLBoolean eglSurfaceAttrib( return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, EGL_FALSE); } -#endif if (s->cnx->egl.eglSurfaceAttrib) { return s->cnx->egl.eglSurfaceAttrib( @@ -1980,6 +1986,17 @@ error_condition: return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0); } +EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) { + clearError(); + + if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); + + // FIXME: remove this dangerous reinterpret_cast. + const GraphicBuffer* graphicBuffer = + reinterpret_cast<const GraphicBuffer*>(buffer); + return static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer()); +} + // ---------------------------------------------------------------------------- // NVIDIA extensions // ---------------------------------------------------------------------------- @@ -2048,8 +2065,131 @@ EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, return EGL_FALSE; } +EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, + EGLuint64KHR *frameId) { + clearError(); + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + if (!s->win.get()) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + uint64_t nextFrameId = 0; + status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId); + + if (ret != NO_ERROR) { + // This should not happen. Return an error that is not in the spec + // so it's obvious something is very wrong. + ALOGE("eglGetNextFrameId: Unexpected error."); + return setError(EGL_NOT_INITIALIZED, EGL_FALSE); + } + + *frameId = nextFrameId; + return EGL_TRUE; +} + +EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, + EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values) +{ + clearError(); + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + if (!s->win.get()) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + nsecs_t* compositeDeadline = nullptr; + nsecs_t* compositeInterval = nullptr; + nsecs_t* compositeToPresentLatency = nullptr; + + for (int i = 0; i < numTimestamps; i++) { + switch (names[i]) { + case EGL_COMPOSITE_DEADLINE_ANDROID: + compositeDeadline = &values[i]; + break; + case EGL_COMPOSITE_INTERVAL_ANDROID: + compositeInterval = &values[i]; + break; + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: + compositeToPresentLatency = &values[i]; + break; + default: + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + } + } + + status_t ret = native_window_get_compositor_timing(s->win.get(), + compositeDeadline, compositeInterval, compositeToPresentLatency); + + switch (ret) { + case NO_ERROR: + return EGL_TRUE; + case INVALID_OPERATION: + return setError(EGL_BAD_SURFACE, EGL_FALSE); + default: + // This should not happen. Return an error that is not in the spec + // so it's obvious something is very wrong. + ALOGE("eglGetCompositorTiming: Unexpected error."); + return setError(EGL_NOT_INITIALIZED, EGL_FALSE); + } +} + +EGLBoolean eglGetCompositorTimingSupportedANDROID( + EGLDisplay dpy, EGLSurface surface, EGLint name) +{ + clearError(); + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + egl_surface_t const * const s = get_surface(surface); + + ANativeWindow* window = s->win.get(); + if (!window) { + return setError(EGL_BAD_SURFACE, EGL_FALSE); + } + + switch (name) { + case EGL_COMPOSITE_DEADLINE_ANDROID: + case EGL_COMPOSITE_INTERVAL_ANDROID: + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: + return EGL_TRUE; + default: + return EGL_FALSE; + } +} + EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, - EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, + EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values) { clearError(); @@ -2118,7 +2258,7 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, } } - status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo, + status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId, requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime, displayRetireTime, dequeueReadyTime, releaseTime); @@ -2135,12 +2275,13 @@ EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, default: // This should not happen. Return an error that is not in the spec // so it's obvious something is very wrong. + ALOGE("eglGetFrameTimestamps: Unexpected error."); return setError(EGL_NOT_INITIALIZED, EGL_FALSE); } } -EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, - EGLint timestamp) +EGLBoolean eglGetFrameTimestampSupportedANDROID( + EGLDisplay dpy, EGLSurface surface, EGLint timestamp) { clearError(); @@ -2162,7 +2303,9 @@ EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, } switch (timestamp) { -#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS + case EGL_COMPOSITE_DEADLINE_ANDROID: + case EGL_COMPOSITE_INTERVAL_ANDROID: + case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: case EGL_REQUESTED_PRESENT_TIME_ANDROID: case EGL_RENDERING_COMPLETE_TIME_ANDROID: case EGL_COMPOSITION_LATCH_TIME_ANDROID: @@ -2184,7 +2327,6 @@ EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &value); return value == 0 ? EGL_FALSE : EGL_TRUE; } -#endif default: return EGL_FALSE; } diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in index 2b567187ba..b587a16203 100644 --- a/opengl/libs/EGL/egl_entries.in +++ b/opengl/libs/EGL/egl_entries.in @@ -81,6 +81,7 @@ EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface) EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR) EGL_ENTRY(EGLClientBuffer, eglCreateNativeClientBufferANDROID, const EGLint *) +EGL_ENTRY(EGLClientBuffer, eglGetNativeClientBufferANDROID, const AHardwareBuffer *) /* NVIDIA extensions */ diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt index c8b83f544e..89269a0231 100644 --- a/opengl/libs/libEGL.map.txt +++ b/opengl/libs/libEGL.map.txt @@ -28,6 +28,7 @@ LIBEGL { eglGetCurrentSurface; eglGetDisplay; eglGetError; + eglGetNativeClientBufferANDROID; # introduced=26 eglGetProcAddress; eglGetStreamFileDescriptorKHR; # introduced=23 eglGetSyncAttribKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21 diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt index 7aa0d30481..d0ed8e172f 100644 --- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt +++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt @@ -8,11 +8,19 @@ Name Strings Contributors + Brian Anderson + Dan Stoza Pablo Ceballos + Jesse Hall + Fabien Sanglard Contact + Brian Anderson, Google Inc. (brianderson 'at' google.com) + Dan Stoza, Google Inc. (stoza 'at' google.com) Pablo Ceballos, Google Inc. (pceballos 'at' google.com) + Jesse Hall, Google Inc. (jessehall 'at' google.com) + Fabien Sanglard, Google Inc. (sanglardf 'at' google.com) Status @@ -20,7 +28,7 @@ Status Version - Version 1, May 31, 2016 + Version 1, January 13, 2017 Number @@ -57,26 +65,36 @@ New Types New Procedures and Functions + EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, + EGLuint64KHR *frameId); + + EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, + EGLSurface surface, EGLint numTimestamps, + const EGLint *names, EGLnsecsANDROID *values); + EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, - EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, - EGLnsecsANDROID *values); + EGLuint64KHR frameId, EGLint numTimestamps, + const EGLint *timestamps, EGLnsecsANDROID *values); - EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface - surface, EGLint timestamp); + EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, + EGLSurface surface, EGLint timestamp); New Tokens EGL_TIMESTAMPS_ANDROID 0x314D - EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E - EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F - EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150 - EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151 - EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152 - EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153 - EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154 - EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155 - EGL_DEQUEUE_READY_TIME_ANDROID 0x3156 - EGL_READS_DONE_TIME_ANDROID 0x3157 + EGL_COMPOSITE_DEADLINE_ANDROID 0x314E + EGL_COMPOSITE_INTERVAL_ANDROID 0x314F + EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150 + EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151 + EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152 + EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153 + EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154 + EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155 + EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156 + EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157 + EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158 + EGL_DEQUEUE_READY_TIME_ANDROID 0x3159 + EGL_READS_DONE_TIME_ANDROID 0x315A Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6 "Surface Attributes", page 43: @@ -86,7 +104,6 @@ Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6 enables timestamp collection, while a value of EGL_FALSE disables it. The initial value is false. If surface is not a window surface this has no effect. - Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) Add a new subsection under Section 3, @@ -95,23 +112,60 @@ Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) The function - EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface - surface, EGLint framesAgo, EGLint numTimestamps, + EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, + EGLuint64KHR *frameId); + + Returns an identifier for the next frame to be swapped. The identifier can + be used to correlate a particular eglSwapBuffers with its timestamps in + eglGetFrameTimestampsANDROID. If any error is generated, the function will + return EGL_FALSE. + + The function + + EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, + EGLSurface surface, EGLint numTimestamps, + const EGLint *names, EGLnsecsANDROID *values); + + allows querying anticipated timestamps and durations related to the + composition and display of a window surface. The values are not associated + with a particular frame and can be retrieved before the first swap. + + The eglGetCompositorTimingANDROID function takes an array of names to + query and returns their values in the corresponding indices of the values + array. The possible names that can be queried are: + - EGL_COMPOSITE_DEADLINE_ANDROID - The timestamp of the next time the + compositor will begin composition. This is effectively the deadline + for when the compositor must receive a newly queued frame. + - EGL_COMPOSITE_INTERVAL_ANDROID - The time delta between subsequent + composition events. + - EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID - The time delta between + the start of composition and the expected present time of that + composition. This can be used to estimate the latency of the + actual present time. + + The function + + EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, + EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); - allows querying various timestamps related to the composition and display of - a window surface. + allows querying various timestamps related to the composition and display + of specific frames of a window surface. - The framesAgo parameter indicates how many frames before the last queued - frame to query. So a value of zero would indicate that the query is for the - last queued frame. Note that the implementation maintains a limited history - of timestamp data. If a query is made for a frame whose timestamp history - no longer exists then EGL_BAD_ACCESS is generated. If timestamp collection - has not been enabled for the surface then EGL_BAD_SURFACE is generated. - Timestamps for events that will not occur or have not yet occurred will be - zero. Timestamp queries that are not supported will generate an - EGL_BAD_PARAMETER error. If any error is generated the function will return - EGL_FALSE. + The frameId indicates which frame to query. The implementation maintains a + limited history of timestamp data. If a query is made for a frame whose + timestamp history no longer exists then EGL_BAD_ACCESS is generated. If + timestamp collection has not been enabled for the surface then + EGL_BAD_SURFACE is generated. Timestamps for events that will not occur or + have not yet occurred will be zero. Timestamp queries that are not + supported will generate an EGL_BAD_PARAMETER error. If any error is + generated the function will return EGL_FALSE. + + The application can poll for the timestamp of particular events by calling + eglGetFrameTimestamps over and over without needing to call any other EGL + function between calls. This is true even for the most recently swapped + frame. eglGetFrameTimestamps is thread safe and can be called from a + different thread than the swapping thread. The eglGetFrameTimestampsANDROID function takes an array of timestamps to query and returns timestamps in the corresponding indices of the values @@ -151,12 +205,19 @@ Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) purpose of display/composition were completed for this frame. Not all implementations may support all of the above timestamp queries. The - function + functions + + EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, + EGLSurface surface, EGLint name); + + and - EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface - surface, EGLint timestamp); + EGLBoolean eglGetFrameTimestampsSupportedANDROID(EGLDisplay dpy, + EGLSurface surface, EGLint timestamp); - allows querying which timestamps are supported on the implementation." + allows querying which values are supported by the implementations of + eglGetCompositoTimingANDROID and eglGetFrameTimestampsSupportedANDROID + respectively." Issues @@ -164,14 +225,21 @@ Issues Revision History -#1 (Pablo Ceballos, May 31, 2016) - - Initial draft. +#5 (Brian Anderson, January 13, 2017) + - Add eglGetCompositorTimingANDROID. -#2 (Brian Anderson, July 22, 2016) - - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID. - - Add DISPLAY_PRESENT_TIME_ANDROID. +#4 (Brian Anderson, January 10, 2017) + - Use an absolute frameId rather than a relative framesAgo. #3 (Brian Anderson, November 30, 2016) - Add EGL_COMPOSITION_LATCH_TIME_ANDROID, EGL_LAST_COMPOSITION_START_TIME_ANDROID, and EGL_DEQUEUE_READY_TIME_ANDROID. + +#2 (Brian Anderson, July 22, 2016) + - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID. + - Add DISPLAY_PRESENT_TIME_ANDROID. + +#1 (Pablo Ceballos, May 31, 2016) + - Initial draft. + diff --git a/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt new file mode 100644 index 0000000000..de012a0c30 --- /dev/null +++ b/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt @@ -0,0 +1,96 @@ +Name + + ANDROID_get_native_client_buffer + +Name Strings + + EGL_ANDROID_get_native_client_buffer + +Contributors + + Craig Donner + +Contact + + Craig Donner, Google Inc. (cdonner 'at' google.com) + +Status + + Draft + +Version + + Version 1.0, January 27, 2017 + +Number + + EGL Extension #XXX + +Dependencies + + Requires EGL 1.2. + + EGL_ANDROID_image_native_buffer and EGL_KHR_image_base are required. + + This extension is written against the wording of the EGL 1.2 + Specification as modified by EGL_KHR_image_base and + EGL_ANDROID_image_native_buffer. + +Overview + + This extension allows creating an EGLClientBuffer from an Android + AHardwareBuffer object which can be later used to create an EGLImage. + +New Types + +struct AHardwareBuffer + +New Procedures and Functions + +EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) + +New Tokens + + None + +Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) + + Add the following to section 2.5.1 "EGLImage Specification" (as modified by + the EGL_KHR_image_base and EGL_ANDROID_image_native_buffer specifications), + below the description of eglCreateImageKHR: + + "The command + + EGLClientBuffer eglGeteNativeClientBufferANDROID( + AHardwareBuffer *buffer) + + may be used to create an EGLClientBuffer from an AHardwareBuffer object. + EGL implementations must guarantee that the lifetime of the returned + EGLClientBuffer is at least as long as the EGLImage(s) it is bound to, + following the lifetime semantics described below in section 2.5.2; the + EGLClientBuffer must be destroyed no earlier than when all of its associated + EGLImages are destroyed by eglDestroyImageKHR. + + Errors + + If eglGeteNativeClientBufferANDROID fails, NULL will be returned, no + memory will be allocated, and the following error will be generated: + + * If the value of buffer is NULL, the error EGL_BAD_PARAMETER is + generated. + +Issues + + 1. Should this extension define what particular AHardwareBuffer formats EGL + implementations are required to support? + + RESOLVED: No. + + The set of valid formats is implementation-specific and may depend on + additional EGL extensions. The particular valid combinations for a given + Android version and implementation should be documented by that version. + +Revision History + +#1 (Craig Donner, January 27, 2017) + - Initial draft. diff --git a/opengl/specs/README b/opengl/specs/README index 8a3a7aa947..0c49023f08 100644 --- a/opengl/specs/README +++ b/opengl/specs/README @@ -1,5 +1,5 @@ This directory contains OpenGL ES and EGL extension specifications that have -been or are being defined for Android. +been or are being defined for Android. The table below tracks usage of EGL enumerant values that have been reserved for use by Android extensions. @@ -20,14 +20,17 @@ for use by Android extensions. 0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop) 0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh) 0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x314E EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x314F EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3150 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3151 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3152 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3153 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3154 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3155 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3156 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3157 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) -0x3158 - 0x315F (unused) +0x314E EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x314F EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3150 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3151 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3152 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3153 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3154 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3155 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3156 EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3157 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3158 EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x3159 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x315A EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps) +0x315B - 0x315F (unused) diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp index 47edc4bd31..e8a9c3472f 100644 --- a/services/audiomanager/IPlayer.cpp +++ b/services/audiomanager/IPlayer.cpp @@ -35,6 +35,7 @@ enum { SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3, SET_PAN = IBinder::FIRST_CALL_TRANSACTION + 4, SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5, + APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6, }; class BpPlayer : public BpInterface<IPlayer> @@ -88,6 +89,36 @@ public: data.writeInt32(delayMs); remote()->transact(SET_START_DELAY_MS, data, &reply); } + + virtual void applyVolumeShaper( + const sp<VolumeShaper::Configuration>& configuration, + const sp<VolumeShaper::Operation>& operation) { + Parcel data, reply; + data.writeInterfaceToken(IPlayer::getInterfaceDescriptor()); + + status_t status = configuration.get() == nullptr + ? data.writeInt32(0) + : data.writeInt32(1) + ?: configuration->writeToParcel(&data); + if (status != NO_ERROR) { + ALOGW("applyVolumeShaper failed configuration parceling: %d", status); + return; // ignore error + } + + status = operation.get() == nullptr + ? status = data.writeInt32(0) + : data.writeInt32(1) + ?: operation->writeToParcel(&data); + if (status != NO_ERROR) { + ALOGW("applyVolumeShaper failed operation parceling: %d", status); + return; // ignore error + } + + status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply); + + ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status); + return; // one way transaction, ignore error + } }; IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer"); @@ -128,6 +159,28 @@ status_t BnPlayer::onTransact( setStartDelayMs(data.readInt32()); return NO_ERROR; } break; + case APPLY_VOLUME_SHAPER: { + CHECK_INTERFACE(IPlayer, data, reply); + sp<VolumeShaper::Configuration> configuration; + sp<VolumeShaper::Operation> operation; + + int32_t present; + status_t status = data.readInt32(&present); + if (status == NO_ERROR && present != 0) { + configuration = new VolumeShaper::Configuration(); + status = configuration->readFromParcel(data); + } + status = status ?: data.readInt32(&present); + if (status == NO_ERROR && present != 0) { + operation = new VolumeShaper::Operation(); + status = operation->readFromParcel(data); + } + if (status == NO_ERROR) { + // one way transaction, no error returned + applyVolumeShaper(configuration, operation); + } + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk index c41630a20b..d61f26fe84 100644 --- a/services/sensorservice/Android.mk +++ b/services/sensorservice/Android.mk @@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \ OrientationSensor.cpp \ RecentEventLogger.cpp \ RotationVectorSensor.cpp \ + SensorDevice.cpp \ SensorDirectConnection.cpp \ SensorEventConnection.cpp \ SensorFusion.cpp \ @@ -25,13 +26,6 @@ LOCAL_CFLAGS += -Wall -Werror -Wextra LOCAL_CFLAGS += -fvisibility=hidden -ifeq ($(ENABLE_TREBLE), true) -LOCAL_SRC_FILES += SensorDeviceTreble.cpp -LOCAL_CFLAGS += -DENABLE_TREBLE=1 -else -LOCAL_SRC_FILES += SensorDevice.cpp -endif - LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware \ @@ -42,10 +36,6 @@ LOCAL_SHARED_LIBRARIES := \ libui \ libgui \ libcrypto \ - -ifeq ($(ENABLE_TREBLE), true) - -LOCAL_SHARED_LIBRARIES += \ libbase \ libhidlbase \ libhidltransport \ @@ -55,8 +45,6 @@ LOCAL_SHARED_LIBRARIES += \ LOCAL_STATIC_LIBRARIES := \ android.hardware.sensors@1.0-convert -endif # ENABLE_TREBLE - LOCAL_MODULE:= libsensorservice include $(BUILD_SHARED_LIBRARY) diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index de0321db67..3edd50bd81 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -14,138 +14,167 @@ * limitations under the License. */ +#include <inttypes.h> +#include <math.h> +#include <stdint.h> +#include <sys/types.h> + +#include <android-base/logging.h> +#include <utils/Atomic.h> +#include <utils/Errors.h> +#include <utils/Singleton.h> #include "SensorDevice.h" #include "SensorService.h" +#include <sensors/convert.h> -#include <binder/BinderService.h> -#include <binder/Parcel.h> -#include <binder/IServiceManager.h> -#include <cutils/ashmem.h> -#include <hardware/sensors.h> -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/Singleton.h> +using android::hardware::hidl_vec; -#include <inttypes.h> -#include <math.h> -#include <sys/mman.h> -#include <stdint.h> -#include <sys/types.h> -#include <sstream> -#include <unistd.h> +using namespace android::hardware::sensors::V1_0; +using namespace android::hardware::sensors::V1_0::implementation; namespace android { // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice) -SensorDevice::SensorDevice() - : mSensorDevice(0), - mSensorModule(0) { - status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, - (hw_module_t const**)&mSensorModule); +static status_t StatusFromResult(Result result) { + switch (result) { + case Result::OK: + return OK; + case Result::BAD_VALUE: + return BAD_VALUE; + case Result::PERMISSION_DENIED: + return PERMISSION_DENIED; + case Result::INVALID_OPERATION: + return INVALID_OPERATION; + case Result::NO_MEMORY: + return NO_MEMORY; + } +} - ALOGE_IF(err, "couldn't load %s module (%s)", - SENSORS_HARDWARE_MODULE_ID, strerror(-err)); +SensorDevice::SensorDevice() { + mSensors = ISensors::getService(); - if (mSensorModule) { - err = sensors_open_1(&mSensorModule->common, &mSensorDevice); + if (mSensors == NULL) { + return; + } - ALOGE_IF(err, "couldn't open device for module %s (%s)", - SENSORS_HARDWARE_MODULE_ID, strerror(-err)); + mSensors->getSensorsList( + [&](const auto &list) { + const size_t count = list.size(); - if (mSensorDevice) { + mActivationCount.setCapacity(count); + Info model; + for (size_t i=0 ; i < count; i++) { + sensor_t sensor; + convertToSensor(list[i], &sensor); + mSensorList.push_back(sensor); - sensor_t const* list; - ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); + mActivationCount.add(list[i].sensorHandle, model); - if (mSensorDevice->common.version < SENSORS_DEVICE_API_VERSION_1_3) { - ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3, ignoring sensors reported by this device"); - count = 0; - } + mSensors->activate(list[i].sensorHandle, 0 /* enabled */); + } + }); - mActivationCount.setCapacity(count); - Info model; - for (size_t i=0 ; i<size_t(count) ; i++) { - mActivationCount.add(list[i].handle, model); - mSensorDevice->activate( - reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), - list[i].handle, 0); - } - } - } + mIsDirectReportSupported = + (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION); } void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) { if (connected) { Info model; mActivationCount.add(handle, model); - mSensorDevice->activate( - reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), handle, 0); + mSensors->activate(handle, 0 /* enabled */); } else { mActivationCount.removeItem(handle); } } std::string SensorDevice::dump() const { - if (!mSensorModule) return "HAL not initialized\n"; + if (mSensors == NULL) return "HAL not initialized\n"; String8 result; - sensor_t const* list; - int count = mSensorModule->get_sensors_list(mSensorModule, &list); - - result.appendFormat("HAL: %s (%s), version %#010x\n", - mSensorModule->common.name, - mSensorModule->common.author, - getHalDeviceVersion()); - result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size()); + mSensors->getSensorsList([&](const auto &list) { + const size_t count = list.size(); + + result.appendFormat( + "Total %zu h/w sensors, %zu running:\n", + count, + mActivationCount.size()); + + Mutex::Autolock _l(mLock); + for (size_t i = 0 ; i < count ; i++) { + const Info& info = mActivationCount.valueFor( + list[i].sensorHandle); + + if (info.batchParams.isEmpty()) continue; + result.appendFormat( + "0x%08x) active-count = %zu; ", + list[i].sensorHandle, + info.batchParams.size()); + + result.append("sampling_period(ms) = {"); + for (size_t j = 0; j < info.batchParams.size(); j++) { + const BatchParams& params = info.batchParams.valueAt(j); + result.appendFormat( + "%.1f%s", + params.batchDelay / 1e6f, + j < info.batchParams.size() - 1 ? ", " : ""); + } + result.appendFormat( + "}, selected = %.1f ms; ", + info.bestBatchParams.batchDelay / 1e6f); + + result.append("batching_period(ms) = {"); + for (size_t j = 0; j < info.batchParams.size(); j++) { + BatchParams params = info.batchParams.valueAt(j); + + result.appendFormat( + "%.1f%s", + params.batchTimeout / 1e6f, + j < info.batchParams.size() - 1 ? ", " : ""); + } - Mutex::Autolock _l(mLock); - for (int i = 0 ; i < count ; i++) { - const Info& info = mActivationCount.valueFor(list[i].handle); - if (info.batchParams.isEmpty()) continue; - result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle, - info.batchParams.size()); - - result.append("sampling_period(ms) = {"); - for (size_t j = 0; j < info.batchParams.size(); j++) { - const BatchParams& params = info.batchParams.valueAt(j); - result.appendFormat("%.1f%s", params.batchDelay / 1e6f, - j < info.batchParams.size() - 1 ? ", " : ""); - } - result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f); + result.appendFormat( + "}, selected = %.1f ms\n", + info.bestBatchParams.batchTimeout / 1e6f); + } + }); - result.append("batching_period(ms) = {"); - for (size_t j = 0; j < info.batchParams.size(); j++) { - BatchParams params = info.batchParams.valueAt(j); - result.appendFormat("%.1f%s", params.batchTimeout / 1e6f, - j < info.batchParams.size() - 1 ? ", " : ""); - } - result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f); - } return result.string(); } ssize_t SensorDevice::getSensorList(sensor_t const** list) { - if (!mSensorModule) return NO_INIT; - ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list); - return count; + *list = &mSensorList[0]; + + return mSensorList.size(); } status_t SensorDevice::initCheck() const { - return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT; + return mSensors != NULL ? NO_ERROR : NO_INIT; } ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { - if (!mSensorDevice) return NO_INIT; - ssize_t c; - do { - c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), - buffer, count); - } while (c == -EINTR); - return c; + if (mSensors == NULL) return NO_INIT; + + ssize_t err; + + mSensors->poll( + count, + [&](auto result, + const auto &events, + const auto &dynamicSensorsAdded) { + if (result == Result::OK) { + convertToSensorEvents(events, dynamicSensorsAdded, buffer); + err = (ssize_t)events.size(); + } else { + err = StatusFromResult(result); + } + }); + + return err; } void SensorDevice::autoDisable(void *ident, int handle) { @@ -155,7 +184,8 @@ void SensorDevice::autoDisable(void *ident, int handle) { } status_t SensorDevice::activate(void* ident, int handle, int enabled) { - if (!mSensorDevice) return NO_INIT; + if (mSensors == NULL) return NO_INIT; + status_t err(NO_ERROR); bool actuateHardware = false; @@ -187,24 +217,30 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) { } else { ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident)); + // If a connected dynamic sensor is deactivated, remove it from the + // dictionary. + auto it = mConnectedDynamicSensors.find(handle); + if (it != mConnectedDynamicSensors.end()) { + delete it->second; + mConnectedDynamicSensors.erase(it); + } + if (info.removeBatchParamsForIdent(ident) >= 0) { if (info.numActiveClients() == 0) { // This is the last connection, we need to de-activate the underlying h/w sensor. actuateHardware = true; } else { - const int halVersion = getHalDeviceVersion(); - if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) { - // Call batch for this sensor with the previously calculated best effort - // batch_rate and timeout. One of the apps has unregistered for sensor - // events, and the best effort batch parameters might have changed. - ALOGD_IF(DEBUG_CONNECTIONS, - "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags, - info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - } + // Call batch for this sensor with the previously calculated best effort + // batch_rate and timeout. One of the apps has unregistered for sensor + // events, and the best effort batch parameters might have changed. + ALOGD_IF(DEBUG_CONNECTIONS, + "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle, + info.bestBatchParams.flags, info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout); + mSensors->batch( + handle, + info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout); } } else { // sensor wasn't enabled for this ident @@ -218,8 +254,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) { if (actuateHardware) { ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled); - err = mSensorDevice->activate( - reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled); + err = StatusFromResult(mSensors->activate(handle, enabled)); ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, strerror(-err)); @@ -229,31 +264,21 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) { } } - // On older devices which do not support batch, call setDelay(). - if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) { - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle, - info.bestBatchParams.batchDelay); - mSensorDevice->setDelay( - reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), - handle, info.bestBatchParams.batchDelay); - } return err; } -status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs, - int64_t maxBatchReportLatencyNs) { - if (!mSensorDevice) return NO_INIT; +status_t SensorDevice::batch( + void* ident, + int handle, + int flags, + int64_t samplingPeriodNs, + int64_t maxBatchReportLatencyNs) { + if (mSensors == NULL) return NO_INIT; if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) { samplingPeriodNs = MINIMUM_EVENTS_PERIOD; } - const int halVersion = getHalDeviceVersion(); - if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) { - // Batch is not supported on older devices return invalid operation. - return INVALID_OPERATION; - } - ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64, ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs); @@ -282,21 +307,17 @@ status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplin status_t err(NO_ERROR); // If the min period or min timeout has changed since the last batch call, call batch. if (prevBestBatchParams != info.bestBatchParams) { - if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) { - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags, - info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - } else { - // For older devices which do not support batch, call setDelay() after activate() is - // called. Some older devices may not support calling setDelay before activate(), so - // call setDelay in SensorDevice::activate() method. - } + ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle, + info.bestBatchParams.flags, info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout); + err = StatusFromResult( + mSensors->batch( + handle, + info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout)); if (err != NO_ERROR) { ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s", - mSensorDevice, handle, + mSensors.get(), handle, info.bestBatchParams.flags, info.bestBatchParams.batchDelay, info.bestBatchParams.batchTimeout, strerror(-err)); info.removeBatchParamsForIdent(ident); @@ -306,7 +327,7 @@ status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplin } status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) { - if (!mSensorDevice) return NO_INIT; + if (mSensors == NULL) return NO_INIT; if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) { samplingPeriodNs = MINIMUM_EVENTS_PERIOD; } @@ -325,22 +346,20 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodN BatchParams& params = info.batchParams.editValueAt(index); params.batchDelay = samplingPeriodNs; info.selectBatchParams(); - return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), - handle, info.bestBatchParams.batchDelay); + + return StatusFromResult( + mSensors->batch(handle, info.bestBatchParams.batchDelay, 0)); } int SensorDevice::getHalDeviceVersion() const { - if (!mSensorDevice) return -1; - return mSensorDevice->common.version; + if (mSensors == NULL) return -1; + return SENSORS_DEVICE_API_VERSION_1_4; } status_t SensorDevice::flush(void* ident, int handle) { - if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { - return INVALID_OPERATION; - } if (isClientDisabled(ident)) return INVALID_OPERATION; ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle); - return mSensorDevice->flush(mSensorDevice, handle); + return StatusFromResult(mSensors->flush(handle)); } bool SensorDevice::isClientDisabled(void* ident) { @@ -356,7 +375,6 @@ void SensorDevice::enableAllSensors() { Mutex::Autolock _l(mLock); mDisabledClients.clear(); ALOGI("cleared mDisabledClients"); - const int halVersion = getHalDeviceVersion(); for (size_t i = 0; i< mActivationCount.size(); ++i) { Info& info = mActivationCount.editValueAt(i); if (info.batchParams.isEmpty()) continue; @@ -364,42 +382,32 @@ void SensorDevice::enableAllSensors() { const int sensor_handle = mActivationCount.keyAt(i); ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ", sensor_handle); - status_t err(NO_ERROR); - if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) { - err = mSensorDevice->batch(mSensorDevice, sensor_handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err)); - } + status_t err = StatusFromResult( + mSensors->batch( + sensor_handle, + info.bestBatchParams.batchDelay, + info.bestBatchParams.batchTimeout)); + ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err)); if (err == NO_ERROR) { - err = mSensorDevice->activate( - reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), - sensor_handle, 1); + err = StatusFromResult( + mSensors->activate(sensor_handle, 1 /* enabled */)); ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err)); } - - if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) { - err = mSensorDevice->setDelay( - reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), - sensor_handle, info.bestBatchParams.batchDelay); - ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err)); - } } } void SensorDevice::disableAllSensors() { Mutex::Autolock _l(mLock); - for (size_t i = 0; i< mActivationCount.size(); ++i) { + for (size_t i = 0; i< mActivationCount.size(); ++i) { const Info& info = mActivationCount.valueAt(i); // Check if this sensor has been activated previously and disable it. if (info.batchParams.size() > 0) { const int sensor_handle = mActivationCount.keyAt(i); ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ", sensor_handle); - mSensorDevice->activate( - reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), - sensor_handle, 0); + mSensors->activate(sensor_handle, 0 /* enabled */); + // Add all the connections that were registered for this sensor to the disabled // clients list. for (size_t j = 0; j < info.batchParams.size(); ++j) { @@ -410,25 +418,27 @@ void SensorDevice::disableAllSensors() { } } -status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) { - ALOGD_IF(DEBUG_CONNECTIONS, - "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f", - injected_sensor_event->sensor, - injected_sensor_event->timestamp, injected_sensor_event->data[0], - injected_sensor_event->data[1], injected_sensor_event->data[2], - injected_sensor_event->data[3], injected_sensor_event->data[4], - injected_sensor_event->data[5]); - if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) { - return INVALID_OPERATION; - } - return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event); +status_t SensorDevice::injectSensorData( + const sensors_event_t *injected_sensor_event) { + ALOGD_IF(DEBUG_CONNECTIONS, + "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f", + injected_sensor_event->sensor, + injected_sensor_event->timestamp, injected_sensor_event->data[0], + injected_sensor_event->data[1], injected_sensor_event->data[2], + injected_sensor_event->data[3], injected_sensor_event->data[4], + injected_sensor_event->data[5]); + + Event ev; + convertFromSensorEvent(*injected_sensor_event, &ev); + + return StatusFromResult(mSensors->injectSensorData(ev)); } status_t SensorDevice::setMode(uint32_t mode) { - if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) { - return INVALID_OPERATION; - } - return mSensorModule->set_operation_mode(mode); + + return StatusFromResult( + mSensors->setOperationMode( + static_cast<hardware::sensors::V1_0::OperationMode>(mode))); } // --------------------------------------------------------------------------- @@ -491,44 +501,139 @@ void SensorDevice::notifyConnectionDestroyed(void* ident) { } int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) { + Mutex::Autolock _l(mLock); - if (!isDirectReportSupported()) { - return INVALID_OPERATION; + SharedMemType type; + switch (memory->type) { + case SENSOR_DIRECT_MEM_TYPE_ASHMEM: + type = SharedMemType::ASHMEM; + break; + case SENSOR_DIRECT_MEM_TYPE_GRALLOC: + type = SharedMemType::GRALLOC; + break; + default: + return BAD_VALUE; } - Mutex::Autolock _l(mLock); - - int32_t channelHandle = mSensorDevice->register_direct_channel( - mSensorDevice, memory, -1 /*channel_handle*/); - return channelHandle; + SharedMemFormat format; + if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) { + return BAD_VALUE; + } + format = SharedMemFormat::SENSORS_EVENT; + + SharedMemInfo mem = { + .type = type, + .format = format, + .size = static_cast<uint32_t>(memory->size), + .memoryHandle = memory->handle, + }; + + int32_t ret; + mSensors->registerDirectChannel(mem, + [&ret](auto result, auto channelHandle) { + if (result == Result::OK) { + ret = channelHandle; + } else { + ret = StatusFromResult(result); + } + }); + return ret; } void SensorDevice::unregisterDirectChannel(int32_t channelHandle) { Mutex::Autolock _l(mLock); - - mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle); + mSensors->unregisterDirectChannel(channelHandle); } -int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle, - const struct sensors_direct_cfg_t *config) { +int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, + int32_t channelHandle, const struct sensors_direct_cfg_t *config) { + Mutex::Autolock _l(mLock); - if (!isDirectReportSupported()) { - return INVALID_OPERATION; + RateLevel rate; + switch(config->rate_level) { + case SENSOR_DIRECT_RATE_STOP: + rate = RateLevel::STOP; + break; + case SENSOR_DIRECT_RATE_NORMAL: + rate = RateLevel::NORMAL; + break; + case SENSOR_DIRECT_RATE_FAST: + rate = RateLevel::FAST; + break; + case SENSOR_DIRECT_RATE_VERY_FAST: + rate = RateLevel::VERY_FAST; + break; + default: + return BAD_VALUE; } - Mutex::Autolock _l(mLock); + int32_t ret; + mSensors->configDirectReport(sensorHandle, channelHandle, rate, + [&ret, rate] (auto result, auto token) { + if (rate == RateLevel::STOP) { + ret = StatusFromResult(result); + } else { + if (result == Result::OK) { + ret = token; + } else { + ret = StatusFromResult(result); + } + } + }); - int32_t ret = mSensorDevice->config_direct_report( - mSensorDevice, sensorHandle, channelHandle, config); - ALOGE_IF(ret < 0, "SensorDevice::configureDirectChannel ret %d", ret); return ret; } bool SensorDevice::isDirectReportSupported() const { - bool ret = mSensorDevice->register_direct_channel != nullptr - && mSensorDevice->config_direct_report != nullptr; - return ret; + return mIsDirectReportSupported; +} + +void SensorDevice::convertToSensorEvent( + const Event &src, sensors_event_t *dst) { + ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent( + src, dst); + + if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) { + const DynamicSensorInfo &dyn = src.u.dynamic; + + dst->dynamic_sensor_meta.connected = dyn.connected; + dst->dynamic_sensor_meta.handle = dyn.sensorHandle; + if (dyn.connected) { + auto it = mConnectedDynamicSensors.find(dyn.sensorHandle); + CHECK(it != mConnectedDynamicSensors.end()); + + dst->dynamic_sensor_meta.sensor = it->second; + + memcpy(dst->dynamic_sensor_meta.uuid, + dyn.uuid.data(), + sizeof(dst->dynamic_sensor_meta.uuid)); + } + } } + +void SensorDevice::convertToSensorEvents( + const hidl_vec<Event> &src, + const hidl_vec<SensorInfo> &dynamicSensorsAdded, + sensors_event_t *dst) { + // Allocate a sensor_t structure for each dynamic sensor added and insert + // it into the dictionary of connected dynamic sensors keyed by handle. + for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) { + const SensorInfo &info = dynamicSensorsAdded[i]; + + auto it = mConnectedDynamicSensors.find(info.sensorHandle); + CHECK(it == mConnectedDynamicSensors.end()); + + sensor_t *sensor = new sensor_t; + convertToSensor(info, sensor); + + mConnectedDynamicSensors.insert( + std::make_pair(sensor->handle, sensor)); + } + + for (size_t i = 0; i < src.size(); ++i) { + convertToSensorEvent(src[i], &dst[i]); + } +} + // --------------------------------------------------------------------------- }; // namespace android - diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index 7dd256aaa1..7f95429b75 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -20,19 +20,16 @@ #include "SensorServiceUtils.h" #include <gui/Sensor.h> +#include <stdint.h> +#include <sys/types.h> #include <utils/KeyedVector.h> #include <utils/Singleton.h> #include <utils/String8.h> -#include <stdint.h> -#include <sys/types.h> #include <string> - -#ifdef ENABLE_TREBLE #include <map> #include "android/hardware/sensors/1.0/ISensors.h" -#endif // --------------------------------------------------------------------------- @@ -76,14 +73,10 @@ public: virtual std::string dump() const; private: friend class Singleton<SensorDevice>; -#ifdef ENABLE_TREBLE + sp<android::hardware::sensors::V1_0::ISensors> mSensors; Vector<sensor_t> mSensorList; std::map<int32_t, sensor_t*> mConnectedDynamicSensors; -#else - sensors_poll_device_1_t* mSensorDevice; - struct sensors_module_t* mSensorModule; -#endif static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz mutable Mutex mLock; // protect mActivationCount[].batchParams @@ -138,7 +131,6 @@ private: bool isClientDisabled(void* ident); bool isClientDisabledLocked(void* ident); -#ifdef ENABLE_TREBLE using Event = hardware::sensors::V1_0::Event; using SensorInfo = hardware::sensors::V1_0::SensorInfo; @@ -150,7 +142,6 @@ private: sensors_event_t *dst); bool mIsDirectReportSupported; -#endif // ENABLE_TREBLE }; // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp deleted file mode 100644 index 3edd50bd81..0000000000 --- a/services/sensorservice/SensorDeviceTreble.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <inttypes.h> -#include <math.h> -#include <stdint.h> -#include <sys/types.h> - -#include <android-base/logging.h> -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/Singleton.h> - -#include "SensorDevice.h" -#include "SensorService.h" - -#include <sensors/convert.h> - -using android::hardware::hidl_vec; - -using namespace android::hardware::sensors::V1_0; -using namespace android::hardware::sensors::V1_0::implementation; - -namespace android { -// --------------------------------------------------------------------------- - -ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice) - -static status_t StatusFromResult(Result result) { - switch (result) { - case Result::OK: - return OK; - case Result::BAD_VALUE: - return BAD_VALUE; - case Result::PERMISSION_DENIED: - return PERMISSION_DENIED; - case Result::INVALID_OPERATION: - return INVALID_OPERATION; - case Result::NO_MEMORY: - return NO_MEMORY; - } -} - -SensorDevice::SensorDevice() { - mSensors = ISensors::getService(); - - if (mSensors == NULL) { - return; - } - - mSensors->getSensorsList( - [&](const auto &list) { - const size_t count = list.size(); - - mActivationCount.setCapacity(count); - Info model; - for (size_t i=0 ; i < count; i++) { - sensor_t sensor; - convertToSensor(list[i], &sensor); - mSensorList.push_back(sensor); - - mActivationCount.add(list[i].sensorHandle, model); - - mSensors->activate(list[i].sensorHandle, 0 /* enabled */); - } - }); - - mIsDirectReportSupported = - (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION); -} - -void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) { - if (connected) { - Info model; - mActivationCount.add(handle, model); - mSensors->activate(handle, 0 /* enabled */); - } else { - mActivationCount.removeItem(handle); - } -} - -std::string SensorDevice::dump() const { - if (mSensors == NULL) return "HAL not initialized\n"; - - String8 result; - mSensors->getSensorsList([&](const auto &list) { - const size_t count = list.size(); - - result.appendFormat( - "Total %zu h/w sensors, %zu running:\n", - count, - mActivationCount.size()); - - Mutex::Autolock _l(mLock); - for (size_t i = 0 ; i < count ; i++) { - const Info& info = mActivationCount.valueFor( - list[i].sensorHandle); - - if (info.batchParams.isEmpty()) continue; - result.appendFormat( - "0x%08x) active-count = %zu; ", - list[i].sensorHandle, - info.batchParams.size()); - - result.append("sampling_period(ms) = {"); - for (size_t j = 0; j < info.batchParams.size(); j++) { - const BatchParams& params = info.batchParams.valueAt(j); - result.appendFormat( - "%.1f%s", - params.batchDelay / 1e6f, - j < info.batchParams.size() - 1 ? ", " : ""); - } - result.appendFormat( - "}, selected = %.1f ms; ", - info.bestBatchParams.batchDelay / 1e6f); - - result.append("batching_period(ms) = {"); - for (size_t j = 0; j < info.batchParams.size(); j++) { - BatchParams params = info.batchParams.valueAt(j); - - result.appendFormat( - "%.1f%s", - params.batchTimeout / 1e6f, - j < info.batchParams.size() - 1 ? ", " : ""); - } - - result.appendFormat( - "}, selected = %.1f ms\n", - info.bestBatchParams.batchTimeout / 1e6f); - } - }); - - return result.string(); -} - -ssize_t SensorDevice::getSensorList(sensor_t const** list) { - *list = &mSensorList[0]; - - return mSensorList.size(); -} - -status_t SensorDevice::initCheck() const { - return mSensors != NULL ? NO_ERROR : NO_INIT; -} - -ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { - if (mSensors == NULL) return NO_INIT; - - ssize_t err; - - mSensors->poll( - count, - [&](auto result, - const auto &events, - const auto &dynamicSensorsAdded) { - if (result == Result::OK) { - convertToSensorEvents(events, dynamicSensorsAdded, buffer); - err = (ssize_t)events.size(); - } else { - err = StatusFromResult(result); - } - }); - - return err; -} - -void SensorDevice::autoDisable(void *ident, int handle) { - Info& info( mActivationCount.editValueFor(handle) ); - Mutex::Autolock _l(mLock); - info.removeBatchParamsForIdent(ident); -} - -status_t SensorDevice::activate(void* ident, int handle, int enabled) { - if (mSensors == NULL) return NO_INIT; - - status_t err(NO_ERROR); - bool actuateHardware = false; - - Mutex::Autolock _l(mLock); - Info& info( mActivationCount.editValueFor(handle) ); - - ALOGD_IF(DEBUG_CONNECTIONS, - "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu", - ident, handle, enabled, info.batchParams.size()); - - if (enabled) { - ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident)); - - if (isClientDisabledLocked(ident)) { - ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d", - ident, handle); - return INVALID_OPERATION; - } - - if (info.batchParams.indexOfKey(ident) >= 0) { - if (info.numActiveClients() == 1) { - // This is the first connection, we need to activate the underlying h/w sensor. - actuateHardware = true; - } - } else { - // Log error. Every activate call should be preceded by a batch() call. - ALOGE("\t >>>ERROR: activate called without batch"); - } - } else { - ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident)); - - // If a connected dynamic sensor is deactivated, remove it from the - // dictionary. - auto it = mConnectedDynamicSensors.find(handle); - if (it != mConnectedDynamicSensors.end()) { - delete it->second; - mConnectedDynamicSensors.erase(it); - } - - if (info.removeBatchParamsForIdent(ident) >= 0) { - if (info.numActiveClients() == 0) { - // This is the last connection, we need to de-activate the underlying h/w sensor. - actuateHardware = true; - } else { - // Call batch for this sensor with the previously calculated best effort - // batch_rate and timeout. One of the apps has unregistered for sensor - // events, and the best effort batch parameters might have changed. - ALOGD_IF(DEBUG_CONNECTIONS, - "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - mSensors->batch( - handle, - info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - } - } else { - // sensor wasn't enabled for this ident - } - - if (isClientDisabledLocked(ident)) { - return NO_ERROR; - } - } - - if (actuateHardware) { - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, - enabled); - err = StatusFromResult(mSensors->activate(handle, enabled)); - ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, - strerror(-err)); - - if (err != NO_ERROR && enabled) { - // Failure when enabling the sensor. Clean up on failure. - info.removeBatchParamsForIdent(ident); - } - } - - return err; -} - -status_t SensorDevice::batch( - void* ident, - int handle, - int flags, - int64_t samplingPeriodNs, - int64_t maxBatchReportLatencyNs) { - if (mSensors == NULL) return NO_INIT; - - if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) { - samplingPeriodNs = MINIMUM_EVENTS_PERIOD; - } - - ALOGD_IF(DEBUG_CONNECTIONS, - "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64, - ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs); - - Mutex::Autolock _l(mLock); - Info& info(mActivationCount.editValueFor(handle)); - - if (info.batchParams.indexOfKey(ident) < 0) { - BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs); - info.batchParams.add(ident, params); - } else { - // A batch has already been called with this ident. Update the batch parameters. - info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs); - } - - BatchParams prevBestBatchParams = info.bestBatchParams; - // Find the minimum of all timeouts and batch_rates for this sensor. - info.selectBatchParams(); - - ALOGD_IF(DEBUG_CONNECTIONS, - "\t>>> curr_period=%" PRId64 " min_period=%" PRId64 - " curr_timeout=%" PRId64 " min_timeout=%" PRId64, - prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay, - prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout); - - status_t err(NO_ERROR); - // If the min period or min timeout has changed since the last batch call, call batch. - if (prevBestBatchParams != info.bestBatchParams) { - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout); - err = StatusFromResult( - mSensors->batch( - handle, - info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout)); - if (err != NO_ERROR) { - ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s", - mSensors.get(), handle, - info.bestBatchParams.flags, info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout, strerror(-err)); - info.removeBatchParamsForIdent(ident); - } - } - return err; -} - -status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) { - if (mSensors == NULL) return NO_INIT; - if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) { - samplingPeriodNs = MINIMUM_EVENTS_PERIOD; - } - Mutex::Autolock _l(mLock); - if (isClientDisabledLocked(ident)) return INVALID_OPERATION; - Info& info( mActivationCount.editValueFor(handle) ); - // If the underlying sensor is NOT in continuous mode, setDelay() should return an error. - // Calling setDelay() in batch mode is an invalid operation. - if (info.bestBatchParams.batchTimeout != 0) { - return INVALID_OPERATION; - } - ssize_t index = info.batchParams.indexOfKey(ident); - if (index < 0) { - return BAD_INDEX; - } - BatchParams& params = info.batchParams.editValueAt(index); - params.batchDelay = samplingPeriodNs; - info.selectBatchParams(); - - return StatusFromResult( - mSensors->batch(handle, info.bestBatchParams.batchDelay, 0)); -} - -int SensorDevice::getHalDeviceVersion() const { - if (mSensors == NULL) return -1; - return SENSORS_DEVICE_API_VERSION_1_4; -} - -status_t SensorDevice::flush(void* ident, int handle) { - if (isClientDisabled(ident)) return INVALID_OPERATION; - ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle); - return StatusFromResult(mSensors->flush(handle)); -} - -bool SensorDevice::isClientDisabled(void* ident) { - Mutex::Autolock _l(mLock); - return isClientDisabledLocked(ident); -} - -bool SensorDevice::isClientDisabledLocked(void* ident) { - return mDisabledClients.indexOf(ident) >= 0; -} - -void SensorDevice::enableAllSensors() { - Mutex::Autolock _l(mLock); - mDisabledClients.clear(); - ALOGI("cleared mDisabledClients"); - for (size_t i = 0; i< mActivationCount.size(); ++i) { - Info& info = mActivationCount.editValueAt(i); - if (info.batchParams.isEmpty()) continue; - info.selectBatchParams(); - const int sensor_handle = mActivationCount.keyAt(i); - ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ", - sensor_handle); - status_t err = StatusFromResult( - mSensors->batch( - sensor_handle, - info.bestBatchParams.batchDelay, - info.bestBatchParams.batchTimeout)); - ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err)); - - if (err == NO_ERROR) { - err = StatusFromResult( - mSensors->activate(sensor_handle, 1 /* enabled */)); - ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err)); - } - } -} - -void SensorDevice::disableAllSensors() { - Mutex::Autolock _l(mLock); - for (size_t i = 0; i< mActivationCount.size(); ++i) { - const Info& info = mActivationCount.valueAt(i); - // Check if this sensor has been activated previously and disable it. - if (info.batchParams.size() > 0) { - const int sensor_handle = mActivationCount.keyAt(i); - ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ", - sensor_handle); - mSensors->activate(sensor_handle, 0 /* enabled */); - - // Add all the connections that were registered for this sensor to the disabled - // clients list. - for (size_t j = 0; j < info.batchParams.size(); ++j) { - mDisabledClients.add(info.batchParams.keyAt(j)); - ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j)); - } - } - } -} - -status_t SensorDevice::injectSensorData( - const sensors_event_t *injected_sensor_event) { - ALOGD_IF(DEBUG_CONNECTIONS, - "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f", - injected_sensor_event->sensor, - injected_sensor_event->timestamp, injected_sensor_event->data[0], - injected_sensor_event->data[1], injected_sensor_event->data[2], - injected_sensor_event->data[3], injected_sensor_event->data[4], - injected_sensor_event->data[5]); - - Event ev; - convertFromSensorEvent(*injected_sensor_event, &ev); - - return StatusFromResult(mSensors->injectSensorData(ev)); -} - -status_t SensorDevice::setMode(uint32_t mode) { - - return StatusFromResult( - mSensors->setOperationMode( - static_cast<hardware::sensors::V1_0::OperationMode>(mode))); -} - -// --------------------------------------------------------------------------- - -int SensorDevice::Info::numActiveClients() { - SensorDevice& device(SensorDevice::getInstance()); - int num = 0; - for (size_t i = 0; i < batchParams.size(); ++i) { - if (!device.isClientDisabledLocked(batchParams.keyAt(i))) { - ++num; - } - } - return num; -} - -status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags, - int64_t samplingPeriodNs, - int64_t maxBatchReportLatencyNs) { - ssize_t index = batchParams.indexOfKey(ident); - if (index < 0) { - ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)", - ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index)); - return BAD_INDEX; - } - BatchParams& params = batchParams.editValueAt(index); - params.flags = flags; - params.batchDelay = samplingPeriodNs; - params.batchTimeout = maxBatchReportLatencyNs; - return NO_ERROR; -} - -void SensorDevice::Info::selectBatchParams() { - BatchParams bestParams(0, -1, -1); - SensorDevice& device(SensorDevice::getInstance()); - - for (size_t i = 0; i < batchParams.size(); ++i) { - if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue; - BatchParams params = batchParams.valueAt(i); - if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) { - bestParams.batchDelay = params.batchDelay; - } - if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) { - bestParams.batchTimeout = params.batchTimeout; - } - } - bestBatchParams = bestParams; -} - -ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) { - ssize_t idx = batchParams.removeItem(ident); - if (idx >= 0) { - selectBatchParams(); - } - return idx; -} - -void SensorDevice::notifyConnectionDestroyed(void* ident) { - Mutex::Autolock _l(mLock); - mDisabledClients.remove(ident); -} - -int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) { - Mutex::Autolock _l(mLock); - - SharedMemType type; - switch (memory->type) { - case SENSOR_DIRECT_MEM_TYPE_ASHMEM: - type = SharedMemType::ASHMEM; - break; - case SENSOR_DIRECT_MEM_TYPE_GRALLOC: - type = SharedMemType::GRALLOC; - break; - default: - return BAD_VALUE; - } - - SharedMemFormat format; - if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) { - return BAD_VALUE; - } - format = SharedMemFormat::SENSORS_EVENT; - - SharedMemInfo mem = { - .type = type, - .format = format, - .size = static_cast<uint32_t>(memory->size), - .memoryHandle = memory->handle, - }; - - int32_t ret; - mSensors->registerDirectChannel(mem, - [&ret](auto result, auto channelHandle) { - if (result == Result::OK) { - ret = channelHandle; - } else { - ret = StatusFromResult(result); - } - }); - return ret; -} - -void SensorDevice::unregisterDirectChannel(int32_t channelHandle) { - Mutex::Autolock _l(mLock); - mSensors->unregisterDirectChannel(channelHandle); -} - -int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, - int32_t channelHandle, const struct sensors_direct_cfg_t *config) { - Mutex::Autolock _l(mLock); - - RateLevel rate; - switch(config->rate_level) { - case SENSOR_DIRECT_RATE_STOP: - rate = RateLevel::STOP; - break; - case SENSOR_DIRECT_RATE_NORMAL: - rate = RateLevel::NORMAL; - break; - case SENSOR_DIRECT_RATE_FAST: - rate = RateLevel::FAST; - break; - case SENSOR_DIRECT_RATE_VERY_FAST: - rate = RateLevel::VERY_FAST; - break; - default: - return BAD_VALUE; - } - - int32_t ret; - mSensors->configDirectReport(sensorHandle, channelHandle, rate, - [&ret, rate] (auto result, auto token) { - if (rate == RateLevel::STOP) { - ret = StatusFromResult(result); - } else { - if (result == Result::OK) { - ret = token; - } else { - ret = StatusFromResult(result); - } - } - }); - - return ret; -} - -bool SensorDevice::isDirectReportSupported() const { - return mIsDirectReportSupported; -} - -void SensorDevice::convertToSensorEvent( - const Event &src, sensors_event_t *dst) { - ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent( - src, dst); - - if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) { - const DynamicSensorInfo &dyn = src.u.dynamic; - - dst->dynamic_sensor_meta.connected = dyn.connected; - dst->dynamic_sensor_meta.handle = dyn.sensorHandle; - if (dyn.connected) { - auto it = mConnectedDynamicSensors.find(dyn.sensorHandle); - CHECK(it != mConnectedDynamicSensors.end()); - - dst->dynamic_sensor_meta.sensor = it->second; - - memcpy(dst->dynamic_sensor_meta.uuid, - dyn.uuid.data(), - sizeof(dst->dynamic_sensor_meta.uuid)); - } - } -} - -void SensorDevice::convertToSensorEvents( - const hidl_vec<Event> &src, - const hidl_vec<SensorInfo> &dynamicSensorsAdded, - sensors_event_t *dst) { - // Allocate a sensor_t structure for each dynamic sensor added and insert - // it into the dictionary of connected dynamic sensors keyed by handle. - for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) { - const SensorInfo &info = dynamicSensorsAdded[i]; - - auto it = mConnectedDynamicSensors.find(info.sensorHandle); - CHECK(it == mConnectedDynamicSensors.end()); - - sensor_t *sensor = new sensor_t; - convertToSensor(info, sensor); - - mConnectedDynamicSensors.insert( - std::make_pair(sensor->handle, sensor)); - } - - for (size_t i = 0; i < src.size(); ++i) { - convertToSensorEvent(src[i], &dst[i]); - } -} - -// --------------------------------------------------------------------------- -}; // namespace android diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp index 1996a00ed7..34cd8ddd7b 100644 --- a/services/sensorservice/SensorServiceUtils.cpp +++ b/services/sensorservice/SensorServiceUtils.cpp @@ -54,6 +54,7 @@ size_t eventSizeBySensorType(int type) { case SENSOR_TYPE_STATIONARY_DETECT: case SENSOR_TYPE_MOTION_DETECT: case SENSOR_TYPE_HEART_BEAT: + case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT: return 1; default: diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index aa8f189f60..9e81a8c95e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -133,6 +133,7 @@ LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_STATIC_LIBRARIES := \ libhwcomposer-command-buffer \ + android.hardware.configstore-utils \ libtrace_proto \ libvkjson \ libvr_manager \ diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 6c18ef7389..9af4402802 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -47,6 +47,9 @@ #include "SurfaceFlinger.h" #include "Layer.h" +#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> +#include <configstore/Utils.h> + // ---------------------------------------------------------------------------- using namespace android; // ---------------------------------------------------------------------------- @@ -57,6 +60,14 @@ static constexpr bool kEGLAndroidSwapRectangle = true; static constexpr bool kEGLAndroidSwapRectangle = false; #endif +// retrieve triple buffer setting from configstore +using namespace android::hardware::configstore; +using namespace android::hardware::configstore::V1_0; + +static bool useTripleFramebuffer = getBool< + ISurfaceFlingerConfigs, + &ISurfaceFlingerConfigs::useTripleFramebuffer>(false); + #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle) // Dummy implementation in case it is missing. inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) { @@ -165,9 +176,9 @@ DisplayDevice::DisplayDevice( // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); -#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS - surface->allocateBuffers(); -#endif + if (useTripleFramebuffer) { + surface->allocateBuffers(); + } } DisplayDevice::~DisplayDevice() { diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp index 2b603ccec5..a6171f551e 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp @@ -2010,7 +2010,8 @@ HWC2On1Adapter::Layer::Layer(Display& display) mZ(0), mReleaseFence(), mHwc1Id(0), - mHasUnsupportedPlaneAlpha(false) {} + mHasUnsupportedPlaneAlpha(false), + mHasUnsupportedBackgroundColor(false) {} bool HWC2On1Adapter::SortLayersByZ::operator()( const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) @@ -2466,7 +2467,7 @@ bool HWC2On1Adapter::prepareAllDisplays() } } - if (mHwc1DisplayMap.count(0) == 0) { + if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) { ALOGE("prepareAllDisplays: Unable to find primary HWC1 display"); return false; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 1c99036b1b..4a281d4ae4 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -60,9 +60,8 @@ namespace android { // --------------------------------------------------------------------------- -HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer) - : mFlinger(flinger), - mAdapter(), +HWComposer::HWComposer(bool useVrComposer) + : mAdapter(), mHwcDevice(), mDisplayData(2), mFreeDisplaySlots(), @@ -211,7 +210,7 @@ void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display, } void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) { - mFlinger->repaintEverything(); + mEventHandler->onInvalidateReceived(this); } void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display, @@ -257,7 +256,7 @@ void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display, snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); - mEventHandler->onVSyncReceived(disp, timestamp); + mEventHandler->onVSyncReceived(this, disp, timestamp); } status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, @@ -915,6 +914,10 @@ void HWComposerBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot, sp<GraphicBuffer>* outBuffer) { +#ifdef BYPASS_IHWC + *outSlot = slot; + *outBuffer = buffer; +#else if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) { // default to slot 0 slot = 0; @@ -935,6 +938,7 @@ void HWComposerBufferCache::getHwcBuffer(int slot, // update cache mBuffers[slot] = buffer; } +#endif } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 7b61e0e967..07137095e2 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -64,15 +64,16 @@ class HWC2On1Adapter; class NativeHandle; class Region; class String8; -class SurfaceFlinger; class HWComposer { public: class EventHandler { friend class HWComposer; - virtual void onVSyncReceived(int32_t disp, nsecs_t timestamp) = 0; + virtual void onVSyncReceived( + HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0; virtual void onHotplugReceived(int32_t disp, bool connected) = 0; + virtual void onInvalidateReceived(HWComposer* composer) = 0; protected: virtual ~EventHandler() {} }; @@ -80,7 +81,7 @@ public: // useVrComposer is passed to the composer HAL. When true, the composer HAL // will use the vr composer service, otherwise it uses the real hardware // composer. - HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer); + HWComposer(bool useVrComposer); ~HWComposer(); @@ -211,7 +212,6 @@ private: HWC2::Vsync vsyncEnabled; }; - sp<SurfaceFlinger> mFlinger; std::unique_ptr<HWC2On1Adapter> mAdapter; std::unique_ptr<HWC2::Device> mHwcDevice; std::vector<DisplayData> mDisplayData; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp index e0946a758b..bb815cc393 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp @@ -277,7 +277,7 @@ void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp, } void HWComposer::invalidate() { - mFlinger->repaintEverything(); + mEventHandler.onInvalidateReceived(this); } void HWComposer::vsync(int disp, int64_t timestamp) { @@ -302,7 +302,7 @@ void HWComposer::vsync(int disp, int64_t timestamp) { snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); - mEventHandler.onVSyncReceived(disp, timestamp); + mEventHandler.onVSyncReceived(this, disp, timestamp); } } @@ -1319,7 +1319,7 @@ bool HWComposer::VSyncThread::threadLoop() { } while (err<0 && errno == EINTR); if (err == 0) { - mHwc.mEventHandler.onVSyncReceived(0, next_vsync); + mHwc.mEventHandler.onVSyncReceived(&mHwc, 0, next_vsync); } return true; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h index bca25ac448..a94bc1e821 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h @@ -62,8 +62,10 @@ class HWComposer public: class EventHandler { friend class HWComposer; - virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0; + virtual void onVSyncReceived( + HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0; virtual void onHotplugReceived(int disp, bool connected) = 0; + virtual void onInvalidateReceived(HWComposer* composer) = 0; protected: virtual ~EventHandler() {} }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bb1fca68d7..0eef708afd 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -155,6 +155,10 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); #endif mFrameTracker.setDisplayRefreshPeriod(displayPeriod); + + CompositorTiming compositorTiming; + flinger->getCompositorTiming(&compositorTiming); + mFrameEventHistory.initializeCompositorTiming(compositorTiming); } void Layer::onFirstRef() { @@ -427,7 +431,9 @@ Rect Layer::computeBounds(const Region& activeTransparentRegion) const { Rect bounds = win; const auto& p = getParent(); if (p != nullptr) { - bounds = p->computeScreenBounds(); + // Look in computeScreenBounds recursive call for explanation of + // why we pass false here. + bounds = p->computeScreenBounds(false /* reduceTransparentRegion */); } Transform t = getTransform(); @@ -1881,10 +1887,10 @@ bool Layer::onPreComposition(nsecs_t refreshStartTime) { return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; } -bool Layer::onPostComposition( - const std::shared_ptr<FenceTime>& glDoneFence, +bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, - const std::shared_ptr<FenceTime>& retireFence) { + const std::shared_ptr<FenceTime>& retireFence, + const CompositorTiming& compositorTiming) { mAcquireTimeline.updateSignalTimes(); mReleaseTimeline.updateSignalTimes(); @@ -1897,7 +1903,7 @@ bool Layer::onPostComposition( { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.addPostComposition(mCurrentFrameNumber, - glDoneFence, presentFence); + glDoneFence, presentFence, compositorTiming); mFrameEventHistory.addRetire(mPreviousFrameNumber, retireFence); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 12166a8655..8227daec8d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -296,10 +296,10 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - bool onPostComposition( - const std::shared_ptr<FenceTime>& glDoneFence, + bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, - const std::shared_ptr<FenceTime>& retireFence); + const std::shared_ptr<FenceTime>& retireFence, + const CompositorTiming& compositorTiming); #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8af03577d2..462e5a6758 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -87,6 +87,7 @@ #include <cutils/compiler.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> +#include <configstore/Utils.h> #define DISPLAY_COUNT 1 @@ -100,22 +101,9 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { +using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; -static sp<ISurfaceFlingerConfigs> getConfigs() { - static sp<ISurfaceFlingerConfigs> configs - = ISurfaceFlingerConfigs::getService(); - return configs; -} - -static int64_t getVsyncEventPhaseOffsetNs() { - int64_t ret = 1000000; // default value - getConfigs()->vsyncEventPhaseOffsetNs([&](OptionalInt64 value) { - if (value.specified) ret = value.value; - }); - return ret; -} - // This is the phase offset in nanoseconds of the software vsync event // relative to the vsync event reported by HWComposer. The software vsync // event is when SurfaceFlinger and Choreographer-based applications run each @@ -136,10 +124,12 @@ static int64_t getVsyncEventPhaseOffsetNs() { // the latency will end up being an additional vsync period, and animations // will hiccup. Therefore, this latency should be tuned somewhat // conservatively (or at least with awareness of the trade-off being made). -static int64_t vsyncPhaseOffsetNs = getVsyncEventPhaseOffsetNs(); +static int64_t vsyncPhaseOffsetNs = getInt64< + ISurfaceFlingerConfigs, + &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000); // This is the phase offset at which SurfaceFlinger's composition runs. -static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS; +static constexpr int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS; // --------------------------------------------------------------------------- @@ -219,8 +209,8 @@ SurfaceFlinger::SurfaceFlinger() mUseHwcVirtualDisplays = atoi(value); ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays"); - property_get("ro.sf.disable_triple_buffer", value, "0"); - mLayerTripleBufferingDisabled = !atoi(value); + property_get("ro.sf.disable_triple_buffer", value, "1"); + mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering"); } @@ -579,7 +569,7 @@ void SurfaceFlinger::init() { // the lock because on creation, it will call back into SurfaceFlinger to // initialize the primary display. LOG_ALWAYS_FATAL_IF(mEnterVrMode, "Starting in vr mode is not currently supported."); - mRealHwc = new HWComposer(this, false); + mRealHwc = new HWComposer(false); mHwc = mRealHwc; mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this)); @@ -1102,7 +1092,14 @@ void SurfaceFlinger::resyncWithRateLimit() { } } -void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) { +void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type, + nsecs_t timestamp) { + Mutex::Autolock lock(mStateLock); + // Ignore any vsyncs from the non-active hardware composer. + if (composer != mHwc) { + return; + } + bool needsHwVsync = false; { // Scope for the lock @@ -1119,6 +1116,11 @@ void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) { } } +void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { + std::lock_guard<std::mutex> lock(mCompositeTimingLock); + *compositorTiming = mCompositorTiming; +} + void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) { ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false"); if (disp == DisplayDevice::DISPLAY_PRIMARY) { @@ -1163,6 +1165,20 @@ void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) { } } +void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) { + Mutex::Autolock lock(mStateLock); + if (composer == mHwc) { + repaintEverything(); + } else { + // This isn't from our current hardware composer. If it's a callback + // from the real composer, forward the refresh request to vr + // flinger. Otherwise ignore it. + if (!composer->isUsingVrComposer()) { + mVrFlinger->OnHardwareComposerRefresh(); + } + } +} + void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { ATRACE_CALL(); getHwComposer().setVsyncEnabled(disp, @@ -1209,7 +1225,7 @@ void SurfaceFlinger::updateVrMode() { } if (!mVrHwc) { - mVrHwc = new HWComposer(this, true); + mVrHwc = new HWComposer(true); ALOGV("Vr HWC created"); } @@ -1240,11 +1256,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { - updateVrMode(); + // TODO(eieio): Disabled until SELinux issues are resolved. + //updateVrMode(); bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE && - mPreviousPresentFence->getSignalTime() == INT64_MAX; + (mPreviousPresentFence->getSignalTime() == + Fence::SIGNAL_TIME_PENDING); ATRACE_INT("FrameMissed", static_cast<int>(frameMissed)); if (mPropagateBackpressure && frameMissed) { signalLayerUpdate(); @@ -1293,7 +1311,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(); + postComposition(refreshStartTime); mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); @@ -1368,7 +1386,61 @@ void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) } } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::updateCompositorTiming( + nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, + std::shared_ptr<FenceTime>& presentFenceTime) { + // Update queue of past composite+present times and determine the + // most recently known composite to present latency. + mCompositePresentTimes.push({compositeTime, presentFenceTime}); + nsecs_t compositeToPresentLatency = -1; + while (!mCompositePresentTimes.empty()) { + CompositePresentTime& cpt = mCompositePresentTimes.front(); + // Cached values should have been updated before calling this method, + // which helps avoid duplicate syscalls. + nsecs_t displayTime = cpt.display->getCachedSignalTime(); + if (displayTime == Fence::SIGNAL_TIME_PENDING) { + break; + } + compositeToPresentLatency = displayTime - cpt.composite; + mCompositePresentTimes.pop(); + } + + // Don't let mCompositePresentTimes grow unbounded, just in case. + while (mCompositePresentTimes.size() > 16) { + mCompositePresentTimes.pop(); + } + + // Integer division and modulo round toward 0 not -inf, so we need to + // treat negative and positive offsets differently. + nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ? + (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) : + ((-sfVsyncPhaseOffsetNs) % vsyncInterval); + + // Snap the latency to a value that removes scheduling jitter from the + // composition and present times, which often have >1ms of jitter. + // Reducing jitter is important if an app attempts to extrapolate + // something (such as user input) to an accurate diasplay time. + // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs + // with (presentLatency % interval). + nsecs_t snappedCompositeToPresentLatency = -1; + if (compositeToPresentLatency >= 0) { + nsecs_t bias = vsyncInterval / 2; + int64_t extraVsyncs = + (compositeToPresentLatency - idealLatency + bias) / + vsyncInterval; + nsecs_t extraLatency = extraVsyncs * vsyncInterval; + snappedCompositeToPresentLatency = idealLatency + extraLatency; + } + + std::lock_guard<std::mutex> lock(mCompositeTimingLock); + mCompositorTiming.deadline = vsyncPhase - idealLatency; + mCompositorTiming.interval = vsyncInterval; + if (snappedCompositeToPresentLatency >= 0) { + mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; + } +} + +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("postComposition"); @@ -1403,9 +1475,19 @@ void SurfaceFlinger::postComposition() } else { retireFenceTime = &displayFenceTime; } + + nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); + nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); + + // We use the refreshStartTime which might be sampled a little later than + // when we started doing work for this frame, but that should be okay + // since updateCompositorTiming has snapping logic. + updateCompositorTiming( + vsyncPhase, vsyncInterval, refreshStartTime, displayFenceTime); + mDrawingState.traverseInZOrder([&](Layer* layer) { bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, - *presentFenceTime, *retireFenceTime); + *presentFenceTime, *retireFenceTime, mCompositorTiming); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); @@ -1450,9 +1532,8 @@ void SurfaceFlinger::postComposition() if (mHasPoweredOff) { mHasPoweredOff = false; } else { - nsecs_t period = mPrimaryDispSync.getPeriod(); nsecs_t elapsedTime = currentTime - mLastSwapTime; - size_t numPeriods = static_cast<size_t>(elapsedTime / period); + size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval); if (numPeriods < NUM_BUCKETS - 1) { mFrameBuckets[numPeriods] += elapsedTime; } else { @@ -2855,6 +2936,11 @@ void SurfaceFlinger::onInitializeDisplays() { const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); + + { + std::lock_guard<std::mutex> lock(mCompositeTimingLock); + mCompositorTiming.interval = period; + } } void SurfaceFlinger::initializeDisplays() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6dfdf0874d..f52bd2d5a8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -42,6 +42,7 @@ #include <ui/PixelFormat.h> #include <ui/mat4.h> +#include <gui/FrameTimestamps.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposerClient.h> #include <gui/OccupancyTracker.h> @@ -65,7 +66,10 @@ #include "Effects/Daltonizer.h" #include <map> +#include <mutex> +#include <queue> #include <string> +#include <utility> namespace android { @@ -247,8 +251,9 @@ private: /* ------------------------------------------------------------------------ * HWComposer::EventHandler interface */ - virtual void onVSyncReceived(int type, nsecs_t timestamp); + virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp); virtual void onHotplugReceived(int disp, bool connected); + virtual void onInvalidateReceived(HWComposer* composer); /* ------------------------------------------------------------------------ * Message handling @@ -412,7 +417,10 @@ private: Region& dirtyRegion, Region& opaqueRegion); void preComposition(nsecs_t refreshStartTime); - void postComposition(); + void postComposition(nsecs_t refreshStartTime); + void updateCompositorTiming( + nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, + std::shared_ptr<FenceTime>& presentFenceTime); void rebuildLayerStacks(); void setUpHWComposer(); void doComposition(); @@ -433,12 +441,13 @@ private: /* ------------------------------------------------------------------------ * VSync */ - void enableHardwareVsync(); - void resyncToHardwareVsync(bool makeAvailable); - void disableHardwareVsync(bool makeUnavailable); + void enableHardwareVsync(); + void resyncToHardwareVsync(bool makeAvailable); + void disableHardwareVsync(bool makeUnavailable); public: - void resyncWithRateLimit(); + void resyncWithRateLimit(); + void getCompositorTiming(CompositorTiming* compositorTiming); private: /* ------------------------------------------------------------------------ @@ -580,6 +589,17 @@ private: bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; + // protected by mCompositorTimingLock; + mutable std::mutex mCompositeTimingLock; + CompositorTiming mCompositorTiming; + + // Only accessed from the main thread. + struct CompositePresentTime { + nsecs_t composite { -1 }; + std::shared_ptr<FenceTime> display { FenceTime::NO_FENCE }; + }; + std::queue<CompositePresentTime> mCompositePresentTimes; + /* ------------------------------------------------------------------------ * Feature prototyping */ diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index faa68e8fcd..477eb27063 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -192,8 +192,8 @@ SurfaceFlinger::SurfaceFlinger() mUseHwcVirtualDisplays = atoi(value); ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays"); - property_get("ro.sf.disable_triple_buffer", value, "0"); - mLayerTripleBufferingDisabled = !atoi(value); + property_get("ro.sf.disable_triple_buffer", value, "1"); + mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering"); } @@ -1018,7 +1018,8 @@ void SurfaceFlinger::resyncWithRateLimit() { } } -void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { +void SurfaceFlinger::onVSyncReceived(HWComposer* /*composer*/, int type, + nsecs_t timestamp) { bool needsHwVsync = false; { // Scope for the lock @@ -1035,6 +1036,11 @@ void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { } } +void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { + std::lock_guard<std::mutex> lock(mCompositeTimingLock); + *compositorTiming = mCompositorTiming; +} + void SurfaceFlinger::onHotplugReceived(int type, bool connected) { if (mEventThread == NULL) { // This is a temporary workaround for b/7145521. A non-null pointer @@ -1058,6 +1064,10 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) { } } +void SurfaceFlinger::onInvalidateReceived(HWComposer* /*composer*/) { + repaintEverything(); +} + void SurfaceFlinger::eventControl(int disp, int event, int enabled) { ATRACE_CALL(); getHwComposer().eventControl(disp, event, enabled); @@ -1109,7 +1119,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(); + postComposition(refreshStartTime); } void SurfaceFlinger::doDebugFlashRegions() @@ -1166,7 +1176,61 @@ void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) } } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::updateCompositorTiming( + nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime, + std::shared_ptr<FenceTime>& presentFenceTime) { + // Update queue of past composite+present times and determine the + // most recently known composite to present latency. + mCompositePresentTimes.push({compositeTime, presentFenceTime}); + nsecs_t compositeToPresentLatency = -1; + while (!mCompositePresentTimes.empty()) { + CompositePresentTime& cpt = mCompositePresentTimes.front(); + // Cached values should have been updated before calling this method, + // which helps avoid duplicate syscalls. + nsecs_t displayTime = cpt.display->getCachedSignalTime(); + if (displayTime == Fence::SIGNAL_TIME_PENDING) { + break; + } + compositeToPresentLatency = displayTime - cpt.composite; + mCompositePresentTimes.pop(); + } + + // Don't let mCompositePresentTimes grow unbounded, just in case. + while (mCompositePresentTimes.size() > 16) { + mCompositePresentTimes.pop(); + } + + // Integer division and modulo round toward 0 not -inf, so we need to + // treat negative and positive offsets differently. + nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ? + (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) : + ((-sfVsyncPhaseOffsetNs) % vsyncInterval); + + // Snap the latency to a value that removes scheduling jitter from the + // composition and present times, which often have >1ms of jitter. + // Reducing jitter is important if an app attempts to extrapolate + // something (such as user input) to an accurate diasplay time. + // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs + // with (presentLatency % interval). + nsecs_t snappedCompositeToPresentLatency = -1; + if (compositeToPresentLatency >= 0) { + nsecs_t bias = vsyncInterval / 2; + int64_t extraVsyncs = + (compositeToPresentLatency - idealLatency + bias) / + vsyncInterval; + nsecs_t extraLatency = extraVsyncs * vsyncInterval; + snappedCompositeToPresentLatency = idealLatency + extraLatency; + } + + std::lock_guard<std::mutex> lock(mCompositeTimingLock); + mCompositorTiming.deadline = vsyncPhase - idealLatency; + mCompositorTiming.interval = vsyncInterval; + if (snappedCompositeToPresentLatency >= 0) { + mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; + } +} + +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { const HWComposer& hwc = getHwComposer(); const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); @@ -1187,10 +1251,18 @@ void SurfaceFlinger::postComposition() mDisplayTimeline.push(retireFenceTime); mDisplayTimeline.updateSignalTimes(); + nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); + nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); + + // We use the refreshStartTime which might be sampled a little later than + // when we started doing work for this frame, but that should be okay + // since updateCompositorTiming has snapping logic. + updateCompositorTiming( + vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime); + mDrawingState.traverseInZOrder([&](Layer* layer) { bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, - presentFenceTime, retireFenceTime); - + presentFenceTime, retireFenceTime, mCompositorTiming); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk index 36d8400d61..e213bd6644 100644 --- a/services/vr/sensord/Android.mk +++ b/services/vr/sensord/Android.mk @@ -46,21 +46,10 @@ sharedLibraries := \ cFlags := -DLOG_TAG=\"sensord\" \ -DTRACE=0 -ifeq ($(TARGET_USES_QCOM_BSP), true) -ifneq ($(TARGET_QCOM_DISPLAY_VARIANT),) - platform := . -else - platform := $(TARGET_BOARD_PLATFORM) -endif - cFlags += -DQCOM_B_FAMILY \ - -DQCOM_BSP -endif - include $(CLEAR_VARS) # Don't strip symbols so we see stack traces in logcat. LOCAL_STRIP_MODULE := false LOCAL_SRC_FILES := $(sourceFiles) -PLATFORM := $(platform) LOCAL_CFLAGS := $(cFlags) LOCAL_STATIC_LIBRARIES := $(staticLibraries) LOCAL_SHARED_LIBRARIES := $(sharedLibraries) diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc index 0311474166..d868a7e934 100644 --- a/services/vr/sensord/sensord.rc +++ b/services/vr/sensord/sensord.rc @@ -1,3 +1,7 @@ +on init + mkdir /dev/socket/pdx/system/vr/pose 0775 system system + mkdir /dev/socket/pdx/system/vr/sensors 0775 system system + service sensord /system/bin/sensord class core user system diff --git a/services/vr/vr_window_manager/Android.mk b/services/vr/vr_window_manager/Android.mk index 47d9dcc68c..e9552bc4d8 100644 --- a/services/vr/vr_window_manager/Android.mk +++ b/services/vr/vr_window_manager/Android.mk @@ -37,33 +37,18 @@ LOCAL_MODULE := libvrwm_binder LOCAL_MODULE_TAGS := optional include $(BUILD_STATIC_LIBRARY) - native_src := \ application.cpp \ controller_mesh.cpp \ elbow_model.cpp \ hwc_callback.cpp \ reticle.cpp \ - render_thread.cpp \ shell_view.cpp \ surface_flinger_view.cpp \ texture.cpp \ vr_window_manager.cpp \ ../virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl \ -src := \ - vr_window_manager_jni.cpp \ - application.cpp \ - controller_mesh.cpp \ - elbow_model.cpp \ - hwc_callback.cpp \ - reticle.cpp \ - render_thread.cpp \ - shell_view.cpp \ - surface_flinger_view.cpp \ - texture.cpp \ - ../virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl \ - static_libs := \ libdisplay \ libbufferhub \ @@ -86,6 +71,7 @@ shared_libs := \ libbinder \ libinput \ libhardware \ + libhwbinder \ libsync \ libutils \ libgui \ @@ -97,29 +83,10 @@ shared_libs := \ libhidlbase \ libhidltransport - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(src) -LOCAL_STATIC_LIBRARIES := $(static_libs) -LOCAL_SHARED_LIBRARIES := $(shared_libs) -LOCAL_SHARED_LIBRARIES += libgvr -LOCAL_STATIC_LIBRARIES += libgvr_ext -LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\" -LOCAL_LDLIBS := -llog -LOCAL_MODULE := libvr_window_manager_jni -LOCAL_MODULE_TAGS := optional -LOCAL_MULTILIB := 64 -LOCAL_CXX_STL := libc++_static -include $(BUILD_SHARED_LIBRARY) - include $(CLEAR_VARS) LOCAL_SRC_FILES := $(native_src) LOCAL_STATIC_LIBRARIES := $(static_libs) libvrwm_binder LOCAL_SHARED_LIBRARIES := $(shared_libs) -LOCAL_SHARED_LIBRARIES += libgvr -LOCAL_STATIC_LIBRARIES += libgvr_ext LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\" @@ -129,27 +96,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_INIT_RC := vr_wm.rc include $(BUILD_EXECUTABLE) -include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := VrWindowManager - -# We need to be priveleged to run as the system user, which is necessary for -# getting hmd input events and doing input injection. -LOCAL_CERTIFICATE := platform -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, java) -LOCAL_JNI_SHARED_LIBRARIES := libvr_window_manager_jni -LOCAL_STATIC_JAVA_AAR_LIBRARIES := gvr_common_library_aar -# gvr_common_library_aar depends on nano version of libprotobuf -LOCAL_STATIC_JAVA_LIBRARIES := libprotobuf-java-nano -# Make sure that libgvr's resources are loaded -LOCAL_AAPT_FLAGS += --auto-add-overlay -LOCAL_AAPT_FLAGS += --extra-packages com.google.vr.cardboard -LOCAL_PROGUARD_FLAG_FILES := proguard.flags -include $(BUILD_PACKAGE) - - cmd_src := \ vr_wm_ctl.cpp \ aidl/android/service/vr/IVrWindowManager.aidl diff --git a/services/vr/vr_window_manager/AndroidManifest.xml b/services/vr/vr_window_manager/AndroidManifest.xml deleted file mode 100644 index d5008a3a09..0000000000 --- a/services/vr/vr_window_manager/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.google.vr.windowmanager" - coreApp="true" - android:sharedUserId="android.uid.system" - android:versionCode="1" - android:versionName="1.0" > - - <!-- The GVR SDK requires API 19+ and OpenGL ES 2+. --> - <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24" /> - <uses-feature android:glEsVersion="0x00020000" android:required="true" /> - - <!-- We need the DIAGNOSTIC permission to read HMD button events. DIAGNOSTIC - ensures our process runs with the "input" group, so we can access - /dev/input. See frameworks/base/data/etc/platform.xml for the permission - to group mappings. - - TODO(steventhomas): We shouldn't use this DIAGNOSTIC permission. Figure - out the correct way to get access to the HMD buttons. - Bug: b/33253485. --> - <uses-permission android:name="android.permission.DIAGNOSTIC"/> - <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> - - <application - android:label="vr_window_manager" - android:theme="@style/AppStyle"> - <service android:name=".VrWindowManagerService" /> - <receiver android:name="com.google.vr.windowmanager.BootCompletedReceiver"> - <intent-filter> - <!-- action android:name="android.intent.action.BOOT_COMPLETED" / --> - </intent-filter> - </receiver> - </application> -</manifest> diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp index 895f25f3f6..33cd499aa6 100644 --- a/services/vr/vr_window_manager/application.cpp +++ b/services/vr/vr_window_manager/application.cpp @@ -16,25 +16,18 @@ namespace android { namespace dvr { -Application::Application() - : controller_api_status_logged_(false), - controller_connection_state_logged_(false) {} +Application::Application() {} Application::~Application() { } -int Application::Initialize(JNIEnv* env, jobject app_context, - jobject class_loader) { +int Application::Initialize() { dvrSetCpuPartition(0, "/application/performance"); bool is_right_handed = true; // TODO: retrieve setting from system elbow_model_.Enable(ElbowModel::kDefaultNeckPosition, is_right_handed); last_frame_time_ = std::chrono::system_clock::now(); - java_env_ = env; - app_context_ = app_context; - class_loader_ = class_loader; - return 0; } @@ -100,42 +93,10 @@ int Application::AllocateResources() { fov_[1] = FieldOfView(lens_info.right_fov[0], lens_info.right_fov[1], lens_info.right_fov[2], lens_info.right_fov[3]); - if (java_env_) { - int ret = InitializeController(); - if (ret) - return ret; - } - - return 0; -} - -int Application::InitializeController() { - gvr_context_ = gvr::GvrApi::Create(java_env_, app_context_, class_loader_); - if (gvr_context_ == nullptr) { - ALOGE("Gvr context creation failed"); - return 1; - } - - int32_t options = gvr_controller_get_default_options(); - options |= GVR_CONTROLLER_ENABLE_GYRO | GVR_CONTROLLER_ENABLE_ACCEL; - - controller_.reset(new gvr::ControllerApi); - if (!controller_->Init(java_env_, app_context_, class_loader_, options, - gvr_context_->cobj())) { - ALOGE("Gvr controller init failed"); - return 1; - } - - controller_state_.reset(new gvr::ControllerState); - return 0; } void Application::DeallocateResources() { - gvr_context_.reset(); - controller_.reset(); - controller_state_.reset(); - if (graphics_context_) dvrGraphicsContextDestroy(graphics_context_); @@ -162,8 +123,8 @@ void Application::ProcessTasks(const std::vector<MainThreadTask>& tasks) { break; case MainThreadTask::EnteringVrMode: if (!initialized_) { - if (AllocateResources()) - ALOGE("Failed to allocate resources"); + LOG_ALWAYS_FATAL_IF(AllocateResources(), + "Failed to allocate resources"); } break; case MainThreadTask::ExitingVrMode: @@ -309,47 +270,6 @@ void Application::ProcessControllerInput() { return; } } - - if (!controller_) - return; - - controller_state_->Update(*controller_); - gvr::ControllerApiStatus new_api_status = controller_state_->GetApiStatus(); - gvr::ControllerConnectionState new_connection_state = - controller_state_->GetConnectionState(); - - if (!controller_api_status_logged_) { - controller_api_status_logged_ = true; - ALOGI("Controller api status: %s", - gvr::ControllerApi::ToString(new_api_status)); - } else if (new_api_status != controller_api_status_) { - ALOGI("Controller api status changed: %s --> %s", - gvr::ControllerApi::ToString(controller_api_status_), - gvr::ControllerApi::ToString(new_api_status)); - } - - if (new_api_status == gvr::kControllerApiOk) { - if (!controller_connection_state_logged_) { - controller_connection_state_logged_ = true; - ALOGI("Controller connection state: %s", - gvr::ControllerApi::ToString(new_connection_state)); - } else if (new_connection_state != controller_connection_state_) { - ALOGI("Controller connection state changed: %s --> %s", - gvr::ControllerApi::ToString(controller_connection_state_), - gvr::ControllerApi::ToString(new_connection_state)); - } - } else { - controller_connection_state_logged_ = false; - } - - if (new_api_status == gvr::kControllerApiOk) { - gvr_quatf orientation = controller_state_->GetOrientation(); - controller_orientation_ = - quat(orientation.qw, orientation.qx, orientation.qy, orientation.qz); - } - - controller_api_status_ = new_api_status; - controller_connection_state_ = new_connection_state; } void Application::SetVisibility(bool visible) { @@ -357,12 +277,6 @@ void Application::SetVisibility(bool visible) { if (changed) { is_visible_ = visible; dvrGraphicsSurfaceSetVisible(graphics_context_, is_visible_); - if (controller_) { - if (is_visible_) - controller_->Resume(); - else - controller_->Pause(); - } OnVisibilityChanged(is_visible_); } } diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h index 0c6385f7db..c7aa4dd87d 100644 --- a/services/vr/vr_window_manager/application.h +++ b/services/vr/vr_window_manager/application.h @@ -1,15 +1,13 @@ #ifndef VR_WINDOW_MANAGER_APPLICATION_H_ #define VR_WINDOW_MANAGER_APPLICATION_H_ -#include <jni.h> #include <memory> #include <private/dvr/types.h> #include <stdint.h> -#include <vr/gvr/capi/include/gvr.h> -#include <vr/gvr/capi/include/gvr_controller.h> #include <chrono> #include <mutex> +#include <vector> #include "controller_data_provider.h" #include "elbow_model.h" @@ -25,8 +23,7 @@ class Application { Application(); virtual ~Application(); - virtual int Initialize(JNIEnv* env, jobject app_context, - jobject class_loader); + virtual int Initialize(); virtual int AllocateResources(); virtual void DeallocateResources(); @@ -59,8 +56,6 @@ class Application { void QueueTask(MainThreadTask task); - int InitializeController(); - DvrGraphicsContext* graphics_context_ = nullptr; DvrPose* pose_client_ = nullptr; @@ -69,15 +64,8 @@ class Application { FieldOfView fov_[2]; Posef last_pose_; - std::unique_ptr<gvr::GvrApi> gvr_context_; - std::unique_ptr<gvr::ControllerApi> controller_; - std::unique_ptr<gvr::ControllerState> controller_state_; - gvr::ControllerApiStatus controller_api_status_; - gvr::ControllerConnectionState controller_connection_state_; quat controller_orientation_; bool shmem_controller_active_ = false; - bool controller_api_status_logged_; - bool controller_connection_state_logged_; uint64_t shmem_controller_buttons_; bool is_visible_ = false; @@ -95,11 +83,6 @@ class Application { bool initialized_ = false; std::vector<MainThreadTask> main_thread_tasks_; - // Java Resources. - JNIEnv* java_env_; - jobject app_context_; - jobject class_loader_; - // Controller data provider from shared memory buffer. ControllerDataProvider* controller_data_provider_ = nullptr; diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp index 5f8168d243..1096a3742d 100644 --- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp +++ b/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp @@ -3,7 +3,9 @@ namespace android { namespace dvr { -VrComposerView::VrComposerView() : composer_view_(nullptr) {} +VrComposerView::VrComposerView( + std::unique_ptr<VrComposerView::Callback> callback) + : composer_view_(nullptr), callback_(std::move(callback)) {} VrComposerView::~VrComposerView() { composer_view_->UnregisterObserver(this); @@ -14,66 +16,19 @@ void VrComposerView::Initialize(ComposerView* composer_view) { composer_view_->RegisterObserver(this); } -Return<void> VrComposerView::registerCallback( - const sp<IVrComposerCallback>& callback) { - callback_ = callback; - return Void(); -} - -Return<void> VrComposerView::releaseFrame() { +void VrComposerView::ReleaseFrame() { + LOG_ALWAYS_FATAL_IF(!composer_view_, "VrComposerView not initialized"); composer_view_->ReleaseFrame(); - return Void(); } void VrComposerView::OnNewFrame(const ComposerView::Frame& frame) { + std::lock_guard<std::mutex> guard(mutex_); if (!callback_.get()) { - releaseFrame(); + ReleaseFrame(); return; } - std::vector<IVrComposerCallback::Layer> layers; - std::vector<native_handle_t*> fences; - for (size_t i = 0; i < frame.size(); ++i) { - native_handle_t* fence; - if (frame[i].fence->isValid()) { - fence = native_handle_create(1, 0); - fence->data[0] = frame[i].fence->dup(); - } else { - fence = native_handle_create(0, 0); - } - fences.push_back(fence); - - layers.push_back(IVrComposerCallback::Layer{ - .buffer = hidl_handle(frame[i].buffer->getNativeBuffer()->handle), - .fence = hidl_handle(fence), - .display_frame = frame[i].display_frame, - .crop = frame[i].crop, - .blend_mode= frame[i].blend_mode, - .alpha = frame[i].alpha, - .type = frame[i].type, - .app_id = frame[i].app_id, - }); - } - - auto status = - callback_->onNewFrame(hidl_vec<IVrComposerCallback::Layer>(layers)); - if (!status.isOk()) { - ALOGE("Failed to send onNewFrame: %s", status.description().c_str()); - releaseFrame(); - } - - for (size_t i = 0; i < fences.size(); ++i) { - native_handle_close(fences[i]); - native_handle_delete(fences[i]); - } -} - -VrComposerView* GetVrComposerViewFromIVrComposerView(IVrComposerView* view) { - return static_cast<VrComposerView*>(view); -} - -IVrComposerView* HIDL_FETCH_IVrComposerView(const char* name) { - return new VrComposerView(); + callback_->OnNewFrame(frame); } } // namespace dvr diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h b/services/vr/vr_window_manager/composer/impl/vr_composer_view.h index 133bbc8004..5a938e906c 100644 --- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h +++ b/services/vr/vr_window_manager/composer/impl/vr_composer_view.h @@ -1,41 +1,37 @@ #ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_ #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_ -#include <android/dvr/composer/1.0/IVrComposerCallback.h> -#include <android/dvr/composer/1.0/IVrComposerView.h> +#include <memory> #include "vr_hwc.h" namespace android { namespace dvr { -using composer::V1_0::IVrComposerView; -using composer::V1_0::IVrComposerCallback; - -class VrComposerView : public IVrComposerView, public ComposerView::Observer { +class VrComposerView : public ComposerView::Observer { public: - VrComposerView(); + class Callback { + public: + virtual ~Callback() = default; + virtual void OnNewFrame(const ComposerView::Frame& frame) = 0; + }; + + VrComposerView(std::unique_ptr<Callback> callback); ~VrComposerView() override; void Initialize(ComposerView* composer_view); - // IVrComposerView - Return<void> registerCallback(const sp<IVrComposerCallback>& callback) - override; - Return<void> releaseFrame() override; + void ReleaseFrame(); // ComposerView::Observer void OnNewFrame(const ComposerView::Frame& frame) override; private: ComposerView* composer_view_; - sp<IVrComposerCallback> callback_; + std::unique_ptr<Callback> callback_; + std::mutex mutex_; }; -VrComposerView* GetVrComposerViewFromIVrComposerView(IVrComposerView* view); - -IVrComposerView* HIDL_FETCH_IVrComposerView(const char* name); - } // namespace dvr } // namespace android diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp index 12a76d8fc2..b29d17525a 100644 --- a/services/vr/vr_window_manager/hwc_callback.cpp +++ b/services/vr/vr_window_manager/hwc_callback.cpp @@ -12,11 +12,16 @@ namespace dvr { namespace { sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) { + GraphicBufferMapper& mapper = GraphicBufferMapper::get(); + if (mapper.registerBuffer(handle) != OK) { + ALOGE("Failed to register buffer"); + return nullptr; + } + uint32_t width = 0, height = 0, stride = 0, layer_count = 1; uint64_t producer_usage = 0, consumer_usage = 0; int32_t format = 0; - GraphicBufferMapper& mapper = GraphicBufferMapper::get(); if (mapper.getDimensions(handle, &width, &height) || mapper.getStride(handle, &stride) || mapper.getFormat(handle, &format) || @@ -33,10 +38,6 @@ sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) { sp<GraphicBuffer> buffer = new GraphicBuffer( width, height, format, layer_count, producer_usage, consumer_usage, stride, native_handle_clone(handle), true); - if (mapper.registerBuffer(buffer.get()) != OK) { - ALOGE("Failed to register buffer"); - return nullptr; - } return buffer; } @@ -62,27 +63,18 @@ HwcCallback::FrameStatus GetFrameStatus(const HwcCallback::Frame& frame) { } // namespace -HwcCallback::HwcCallback(IVrComposerView* composer_view, Client* client) - : composer_view_(composer_view), - client_(client) { - composer_view_->registerCallback(this); +HwcCallback::HwcCallback(Client* client) : client_(client) { } HwcCallback::~HwcCallback() { - composer_view_->registerCallback(nullptr); } -Return<void> HwcCallback::onNewFrame( - const hidl_vec<IVrComposerCallback::Layer>& frame) { - +void HwcCallback::OnNewFrame(const ComposerView::Frame& frame) { std::vector<HwcLayer> hwc_frame(frame.size()); for (size_t i = 0; i < frame.size(); ++i) { - int fence = frame[i].fence.getNativeHandle()->numFds ? - dup(frame[i].fence.getNativeHandle()->data[0]) : -1; - hwc_frame[i] = HwcLayer{ - .fence = new Fence(fence), - .buffer = GetBufferFromHandle(frame[i].buffer.getNativeHandle()), + .fence = frame[i].fence, + .buffer = frame[i].buffer, .crop = frame[i].crop, .display_frame = frame[i].display_frame, .blending = static_cast<int32_t>(frame[i].blend_mode), @@ -92,10 +84,7 @@ Return<void> HwcCallback::onNewFrame( }; } - std::lock_guard<std::mutex> guard(mutex_); client_->OnFrame(std::make_unique<Frame>(std::move(hwc_frame))); - - return Void(); } HwcCallback::Frame::Frame(std::vector<HwcLayer>&& layers) diff --git a/services/vr/vr_window_manager/hwc_callback.h b/services/vr/vr_window_manager/hwc_callback.h index 05a889bb32..d4d6e66bbc 100644 --- a/services/vr/vr_window_manager/hwc_callback.h +++ b/services/vr/vr_window_manager/hwc_callback.h @@ -6,8 +6,7 @@ #include <mutex> #include <vector> -#include <android/dvr/composer/1.0/IVrComposerCallback.h> -#include <android/dvr/composer/1.0/IVrComposerView.h> +#include <impl/vr_composer_view.h> #include <impl/vr_hwc.h> namespace android { @@ -20,10 +19,7 @@ namespace dvr { using Recti = ComposerView::ComposerLayer::Recti; using Rectf = ComposerView::ComposerLayer::Rectf; -using composer::V1_0::IVrComposerCallback; -using composer::V1_0::IVrComposerView; - -class HwcCallback : public IVrComposerCallback { +class HwcCallback : public VrComposerView::Callback { public: struct HwcLayer { enum LayerType : uint32_t { @@ -86,19 +82,12 @@ class HwcCallback : public IVrComposerCallback { virtual void OnFrame(std::unique_ptr<Frame>) = 0; }; - explicit HwcCallback(IVrComposerView* composer_view, Client* client); + explicit HwcCallback(Client* client); ~HwcCallback() override; private: - // This is the only method called on the binder thread. Everything else is - // called on the render thread. - Return<void> onNewFrame(const hidl_vec<IVrComposerCallback::Layer>& frame) - override; - - IVrComposerView* composer_view_; + void OnNewFrame(const ComposerView::Frame& frame) override; Client *client_; - std::mutex mutex_; - HwcCallback(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; diff --git a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java b/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java deleted file mode 100644 index 01d1bdb76b..0000000000 --- a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.google.vr.windowmanager; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -public class BootCompletedReceiver extends BroadcastReceiver { - private static final String TAG = BootCompletedReceiver.class.getSimpleName(); - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Starting VRWindowManager"); - Intent vrWindowManagerIntent = new Intent(context, VrWindowManagerService.class); - context.startService(vrWindowManagerIntent); - } -} diff --git a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java b/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java deleted file mode 100644 index 1d815ca68b..0000000000 --- a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.google.vr.windowmanager; - -import android.app.Service; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Handler; -import android.os.IBinder; -import android.util.Log; - -public class VrWindowManagerService extends Service { - private static final String TAG = VrWindowManagerService.class.getSimpleName(); - private long nativeVrWindowManager; - - // This is a temporary debugging tool for development only. - // It allows us to show VrWindowManager in debug mode via command line. - private final BroadcastReceiver debugReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals("com.google.vr.windowmanager.intent.SHOW")) { - nativeEnableDebug(nativeVrWindowManager); - } else if (action.equals("com.google.vr.windowmanager.intent.HIDE")) { - nativeDisableDebug(nativeVrWindowManager); - } else if (action.equals("com.google.vr.windowmanager.intent.ENTER_VR")) { - nativeEnterVrMode(nativeVrWindowManager); - } else if (action.equals("com.google.vr.windowmanager.intent.EXIT_VR")) { - nativeExitVrMode(nativeVrWindowManager); - } - } - }; - - static { - System.loadLibrary("vr_window_manager_jni"); - } - - @Override - public void onCreate() { - super.onCreate(); - destroyRenderer(); - nativeVrWindowManager = nativeCreate(getClass().getClassLoader(), getApplicationContext()); - if (nativeVrWindowManager == 0) { - Log.e(TAG, "Failed to create native renderer"); - } - - // For development, testing and debugging. - IntentFilter filter = new IntentFilter(); - filter.addAction("com.google.vr.windowmanager.intent.SHOW"); - filter.addAction("com.google.vr.windowmanager.intent.HIDE"); - filter.addAction("com.google.vr.windowmanager.intent.ENTER_VR"); - filter.addAction("com.google.vr.windowmanager.intent.EXIT_VR"); - registerReceiver(debugReceiver, filter); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - return START_STICKY; - } - - @Override - public IBinder onBind(Intent intent) { - Log.i(TAG, "Ignoring bind request"); - return null; - } - - @Override - public void onDestroy() { - super.onDestroy(); - unregisterReceiver(debugReceiver); - destroyRenderer(); - } - - private void destroyRenderer() { - if (nativeVrWindowManager != 0) { - nativeDestroy(nativeVrWindowManager); - nativeVrWindowManager = 0; - } - } - - private native long nativeCreate(ClassLoader appClassLoader, Context context); - private native void nativeDestroy(long nativeVrWindowManager); - private native void nativeEnableDebug(long nativeVrWindowManager); - private native void nativeDisableDebug(long nativeVrWindowManager); - private native void nativeEnterVrMode(long nativeVrWindowManager); - private native void nativeExitVrMode(long nativeVrWindowManager); -} diff --git a/services/vr/vr_window_manager/render_thread.cpp b/services/vr/vr_window_manager/render_thread.cpp deleted file mode 100644 index b67a05196d..0000000000 --- a/services/vr/vr_window_manager/render_thread.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include <jni.h> -#include <log/log.h> -#include <future> - -#include "render_thread.h" -#include "shell_view.h" - -namespace android { -namespace dvr { - -RenderThread::RenderThread(JNIEnv* env, jobject class_loader, - jobject android_context) - : jvm_(nullptr), - class_loader_global_ref_(0), - android_context_global_ref_(0), - quit_(false) { - env->GetJavaVM(&jvm_); - - // Create global references so we can access these objects on the render - // thread - class_loader_global_ref_ = env->NewGlobalRef(class_loader); - android_context_global_ref_ = env->NewGlobalRef(android_context); - - std::promise<int> render_thread_init_result_promise; - thread_ = std::thread([this, &render_thread_init_result_promise] { - JNIEnv* render_thread_jni_env = nullptr; - jvm_->AttachCurrentThread(&render_thread_jni_env, nullptr); - RunRenderLoop(&render_thread_init_result_promise); - jvm_->DetachCurrentThread(); - }); - - // Wait to see if the render thread started successfully. If not bail. - int render_thread_init_result = - render_thread_init_result_promise.get_future().get(); - LOG_ALWAYS_FATAL_IF(render_thread_init_result != 0, - "Failed initializing render thread. result=%d", - render_thread_init_result); -} - -RenderThread::~RenderThread() { Quit(); } - -void RenderThread::Quit() { - if (thread_.joinable()) { - quit_ = true; - thread_.join(); - } - - JNIEnv* env = GetJniEnv(); - if (class_loader_global_ref_ != 0) { - env->DeleteGlobalRef(class_loader_global_ref_); - class_loader_global_ref_ = 0; - } - if (android_context_global_ref_ != 0) { - env->DeleteGlobalRef(android_context_global_ref_); - android_context_global_ref_ = 0; - } -} - -void RenderThread::EnableDebug(bool debug) { shell_view_.EnableDebug(debug); } - -void RenderThread::VrMode(bool mode) { shell_view_.VrMode(mode); } - -JNIEnv* RenderThread::GetJniEnv() { - JNIEnv* env; - jvm_->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); - return env; -} - -void RenderThread::RunRenderLoop( - std::promise<int>* init_result_promise) { - // TODO(steventhomas): Create local refs to work around b/33251144. Remove - // once that bug is fixed. - JNIEnv* env = GetJniEnv(); - jobject class_loader = env->NewLocalRef(class_loader_global_ref_); - jobject android_context = env->NewLocalRef(android_context_global_ref_); - - int init_result = shell_view_.Initialize(env, android_context, class_loader); - init_result_promise->set_value(init_result); - if (init_result == 0) { - while (!quit_) - shell_view_.DrawFrame(); - } else { - ALOGE("Failed to initialize ShellView"); - } - - env->DeleteLocalRef(class_loader); - env->DeleteLocalRef(android_context); -} - -} // namespace dvr -} // namespace android diff --git a/services/vr/vr_window_manager/render_thread.h b/services/vr/vr_window_manager/render_thread.h deleted file mode 100644 index e193643183..0000000000 --- a/services/vr/vr_window_manager/render_thread.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef VR_WINDOW_MANAGER_RENDER_THREAD_H_ -#define VR_WINDOW_MANAGER_RENDER_THREAD_H_ - -#include <atomic> -#include <future> -#include <jni.h> -#include <thread> - -#include "shell_view.h" - -namespace android { -namespace dvr { - -class RenderThread { - public: - RenderThread(JNIEnv* env, jobject class_loader, jobject android_context); - ~RenderThread(); - void Quit(); - void EnableDebug(bool debug); - void VrMode(bool mode); - - RenderThread(const RenderThread&) = delete; - void operator=(const RenderThread&) = delete; - - private: - // Called by both the main thread and render thread. Will return the correct - // JNIEnv for the current thread. - JNIEnv* GetJniEnv(); - - void RunRenderLoop(std::promise<int>* init_result_promise); - - // Accessed only by the main thread. - std::thread thread_; - - // The vars below are accessed by both the main thread and the render thread. - JavaVM* jvm_; - jobject class_loader_global_ref_; - jobject android_context_global_ref_; - std::atomic_bool quit_; - - ShellView shell_view_; -}; - -} // namespace dvr -} // namespace android - -#endif // VR_WINDOW_MANAGER_RENDER_THREAD_H_ diff --git a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png b/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png Binary files differdeleted file mode 100644 index 06f896dbc1..0000000000 --- a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png +++ /dev/null diff --git a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png b/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png Binary files differdeleted file mode 100644 index d336da3f4f..0000000000 --- a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png +++ /dev/null diff --git a/services/vr/vr_window_manager/res/values/styles.xml b/services/vr/vr_window_manager/res/values/styles.xml deleted file mode 100644 index 8a1a74b044..0000000000 --- a/services/vr/vr_window_manager/res/values/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> -<add-resource type="style" name="AppStyle"></add-resource> -<style name="AppStyle" - parent="@android:style/Theme.Holo.NoActionBar.Fullscreen"> - <item name="android:windowDisablePreview">true</item> -</style> -</resources> diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp index 29ade643fd..84b8467ccb 100644 --- a/services/vr/vr_window_manager/shell_view.cpp +++ b/services/vr/vr_window_manager/shell_view.cpp @@ -238,9 +238,8 @@ ShellView::ShellView() { ShellView::~ShellView() {} -int ShellView::Initialize(JNIEnv* env, jobject app_context, - jobject class_loader) { - int ret = Application::Initialize(env, app_context, class_loader); +int ShellView::Initialize() { + int ret = Application::Initialize(); if (ret) return ret; @@ -604,10 +603,7 @@ void ShellView::DrawReticle(const mat4& perspective, const mat4& eye_matrix, vec3 pointer_location = last_pose_.GetPosition(); quat view_quaternion = last_pose_.GetRotation(); - bool gvr_api_active = - controller_ && controller_api_status_ == gvr::kControllerApiOk; - - if (gvr_api_active || shmem_controller_active_) { + if (shmem_controller_active_) { view_quaternion = controller_orientation_; vec4 controller_location = controller_translate_ * vec4(0, 0, 0, 1); pointer_location = vec3(controller_location.x(), controller_location.y(), @@ -635,18 +631,6 @@ void ShellView::DrawReticle(const mat4& perspective, const mat4& eye_matrix, } buttons >>= 4; } - } else if (controller_) { - if (controller_state_->GetButtonDown(gvr::kControllerButtonClick)) - OnClick(true); - - if (controller_state_->GetButtonUp(gvr::kControllerButtonClick)) - OnClick(false); - - if (controller_state_->GetButtonDown(gvr::kControllerButtonApp)) - OnTouchpadButton(true, AMOTION_EVENT_BUTTON_BACK); - - if (controller_state_->GetButtonUp(gvr::kControllerButtonApp)) - OnTouchpadButton(false, AMOTION_EVENT_BUTTON_BACK); } } @@ -676,7 +660,7 @@ void ShellView::DrawReticle(const mat4& perspective, const mat4& eye_matrix, void ShellView::DrawController(const mat4& perspective, const mat4& eye_matrix, const mat4& head_matrix) { - if (!controller_ && !shmem_controller_active_) + if (!shmem_controller_active_) return; controller_program_->Use(); diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h index 14ad0f3cb8..39b5451aee 100644 --- a/services/vr/vr_window_manager/shell_view.h +++ b/services/vr/vr_window_manager/shell_view.h @@ -28,8 +28,7 @@ class ShellView : public Application, ShellView(); virtual ~ShellView(); - int Initialize(JNIEnv* env, jobject app_context, - jobject class_loader) override; + int Initialize() override; int AllocateResources() override; void DeallocateResources() override; diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp index b15d2628ee..d42d3ff333 100644 --- a/services/vr/vr_window_manager/surface_flinger_view.cpp +++ b/services/vr/vr_window_manager/surface_flinger_view.cpp @@ -1,6 +1,5 @@ #include "surface_flinger_view.h" -#include <binder/IServiceManager.h> #include <impl/vr_composer_view.h> #include <private/dvr/native_buffer.h> @@ -15,23 +14,33 @@ SurfaceFlingerView::SurfaceFlingerView() {} SurfaceFlingerView::~SurfaceFlingerView() {} bool SurfaceFlingerView::Initialize(HwcCallback::Client *client) { - const char instance[] = "DaydreamDisplay"; - composer_service_ = IVrComposerView::getService(instance); - if (composer_service_ == nullptr) { - ALOGE("Failed to initialize composer service"); + const char vr_hwcomposer_name[] = "vr_hwcomposer"; + vr_hwcomposer_ = HIDL_FETCH_IComposer(vr_hwcomposer_name); + if (!vr_hwcomposer_.get()) { + ALOGE("Failed to get vr_hwcomposer"); return false; } - if (!composer_service_->isRemote()) { - ALOGE("Composer service is not remote"); + if (vr_hwcomposer_->isRemote()) { + ALOGE("vr_hwcomposer service is remote"); return false; } + const android::status_t vr_hwcomposer_status = + vr_hwcomposer_->registerAsService(vr_hwcomposer_name); + if (vr_hwcomposer_status != OK) { + ALOGE("Failed to register vr_hwcomposer service"); + return false; + } + + vr_composer_view_ = + std::make_unique<VrComposerView>(std::make_unique<HwcCallback>(client)); + vr_composer_view_->Initialize(GetComposerViewFromIComposer( + vr_hwcomposer_.get())); + // TODO(dnicoara): Query this from the composer service. width_ = 1920; height_ = 1080; - - composer_observer_.reset(new HwcCallback(composer_service_.get(), client)); return true; } @@ -76,7 +85,7 @@ bool SurfaceFlingerView::GetTextures(const HwcCallback::Frame& frame, } void SurfaceFlingerView::ReleaseFrame() { - composer_service_->releaseFrame(); + vr_composer_view_->ReleaseFrame(); } } // namespace dvr diff --git a/services/vr/vr_window_manager/surface_flinger_view.h b/services/vr/vr_window_manager/surface_flinger_view.h index 2e36ec14f8..9c16192322 100644 --- a/services/vr/vr_window_manager/surface_flinger_view.h +++ b/services/vr/vr_window_manager/surface_flinger_view.h @@ -1,10 +1,10 @@ #ifndef APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_ #define APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_ -#include <utils/StrongPointer.h> - #include <memory> +#include <impl/vr_composer_view.h> + #include "hwc_callback.h" namespace android { @@ -39,9 +39,8 @@ class SurfaceFlingerView { void ReleaseFrame(); private: - sp<IVrComposerView> composer_service_; - std::unique_ptr<HwcCallback> composer_observer_; - + sp<IComposer> vr_hwcomposer_; + std::unique_ptr<VrComposerView> vr_composer_view_; int width_ = 0; int height_ = 0; diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp index c51ddee007..6636dc5606 100644 --- a/services/vr/vr_window_manager/vr_window_manager.cpp +++ b/services/vr/vr_window_manager/vr_window_manager.cpp @@ -1,33 +1,48 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> +#include <hwbinder/IPCThreadState.h> +#include <impl/vr_composer_view.h> +#include <impl/vr_hwc.h> #include "shell_view.h" #include "vr_window_manager_binder.h" +using namespace android; +using namespace android::dvr; + int main(int /* argc */, char** /* argv */) { + android::ProcessState::self()->startThreadPool(); + + // ShellView needs to be created after vr_hwcomposer. android::dvr::ShellView app; - const int app_status = app.Initialize(nullptr, nullptr, nullptr); + const int app_status = app.Initialize(); LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status); - android::service::vr::VrWindowManagerBinder service(app); - const int status = service.Initialize(); + // Create vr_wm_binder. + android::service::vr::VrWindowManagerBinder vr_wm_binder(app); + const int status = vr_wm_binder.Initialize(); LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status); - android::ProcessState::self()->startThreadPool(); - android::sp<android::IServiceManager> sm(android::defaultServiceManager()); - const android::status_t service_status = sm->addService( - android::service::vr::VrWindowManagerBinder::SERVICE_NAME(), &service, - false /*allowIsolated*/); - LOG_ALWAYS_FATAL_IF(service_status != android::OK, "service not added: %d", - static_cast<int>(service_status)); + const android::status_t vr_wm_binder_status = + sm->addService( + android::service::vr::VrWindowManagerBinder::SERVICE_NAME(), + &vr_wm_binder, false /*allowIsolated*/); + LOG_ALWAYS_FATAL_IF(vr_wm_binder_status != android::OK, + "vr_wm_binder service not added: %d", + static_cast<int>(vr_wm_binder_status)); + + app.SetControllerDataProvider(&vr_wm_binder); - app.SetControllerDataProvider(&service); + android::hardware::ProcessState::self()->startThreadPool(); - while (true) + while (true) { app.DrawFrame(); + } + android::hardware::IPCThreadState::self()->joinThreadPool(); android::IPCThreadState::self()->joinThreadPool(); + return 0; } diff --git a/services/vr/vr_window_manager/vr_window_manager_jni.cpp b/services/vr/vr_window_manager/vr_window_manager_jni.cpp deleted file mode 100644 index 49eaba1cd7..0000000000 --- a/services/vr/vr_window_manager/vr_window_manager_jni.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include <jni.h> -#include <log/log.h> - -#include <memory> - -#include "render_thread.h" - -#define JNI_METHOD(return_type, method_name) \ - JNIEXPORT return_type JNICALL \ - Java_com_google_vr_windowmanager_VrWindowManagerService_##method_name - -namespace { - -inline jlong jptr(android::dvr::RenderThread* native_vr_window_manager) { - return reinterpret_cast<intptr_t>(native_vr_window_manager); -} - -inline android::dvr::RenderThread* native(jlong ptr) { - return reinterpret_cast<android::dvr::RenderThread*>(ptr); -} - -} // namespace - -extern "C" { - -JNI_METHOD(jlong, nativeCreate)(JNIEnv* env, jclass /*clazz*/, - jobject class_loader, - jobject android_context) { - return jptr(new android::dvr::RenderThread( - env, class_loader, android_context)); -} - -JNI_METHOD(void, nativeDestroy) -(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) { - delete native(native_render_thread); -} - -JNI_METHOD(void, nativeEnableDebug) -(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) { - native(native_render_thread)->EnableDebug(true); -} - -JNI_METHOD(void, nativeDisableDebug) -(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) { - native(native_render_thread)->EnableDebug(false); -} - -JNI_METHOD(void, nativeEnterVrMode) -(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) { - native(native_render_thread)->VrMode(true); -} - -JNI_METHOD(void, nativeExitVrMode) -(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) { - native(native_render_thread)->VrMode(false); -} - -} // extern "C" diff --git a/services/vr/vr_window_manager/vr_wm.rc b/services/vr/vr_window_manager/vr_wm.rc index 143b91609a..951515be80 100644 --- a/services/vr/vr_window_manager/vr_wm.rc +++ b/services/vr/vr_window_manager/vr_wm.rc @@ -3,7 +3,3 @@ service vr_wm /system/bin/vr_wm user system group system graphics input cpuset /system - disabled - -on property:persist.daydream.vr_wm=1 - enable vr_wm diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api index 5a67d36430..eed44ad670 100644 --- a/vulkan/api/vulkan.api +++ b/vulkan/api/vulkan.api @@ -153,6 +153,8 @@ define NULL_HANDLE 0 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image" +@extension("VK_EXT_HDR_METADATA_SPEC_VERSION") define VK_EXT_HDR_METADATA_SPEC_VERSION 1 +@extension("VK_EXT_HDR_METADATA_EXTENSION_NAME") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" ///////////// @@ -2908,14 +2910,20 @@ class VkWin32SurfaceCreateInfoKHR { platform.HWND hwnd } +@internal class Gralloc1Usage { + u64 consumer + u64 producer +} + @extension("VK_ANDROID_native_buffer") class VkNativeBufferANDROID { VkStructureType sType const void* pNext platform.buffer_handle_t handle - int stride - int format - int usage + s32 stride + s32 format + s32 usage + Gralloc1Usage usage2 } @extension("VK_ANDROID_native_buffer") @@ -3297,6 +3305,24 @@ class VkObjectTablePushConstantEntryNVX { VkShaderStageFlags stageFlags } +@extension("VK_EXT_hdr_metadata") +class VkXYColorEXT { + f32 x + f32 y +} + +@extension("VK_EXT_hdr_metadata") +class VkHdrMetadataEXT { + VkXYColorEXT displayPrimaryRed + VkXYColorEXT displayPrimaryGreen + VkXYColorEXT displayPrimaryBlue + VkXYColorEXT whitePoint + f32 maxLuminance + f32 minLuminance + f32 maxContentLightLevel + f32 maxFrameAverageLightLevel +} + //////////////// @@ -5833,21 +5859,24 @@ cmd VkResult vkGetPhysicalDeviceWin32PresentationSupportKHR( } @extension("VK_ANDROID_native_buffer") +@optional cmd VkResult vkGetSwapchainGrallocUsageANDROID( VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, - int* grallocUsage) { + s32* grallocUsage) { return ? } @extension("VK_ANDROID_native_buffer") +@optional cmd VkResult vkGetSwapchainGrallocUsage2ANDROID( VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, - int* grallocUsage) { + u64* grallocConsumerUsage, + u64* grallocProducerUsage) { return ? } @@ -6138,6 +6167,14 @@ cmd VkResult vkGetSwapchainStatusKHR( return ? } +@extension("VK_EXT_hdr_metadata") +cmd void vkSetHdrMetadataEXT( + VkDevice device, + u32 swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata) { +} + //////////////// // Validation // diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc index 009472a510..24af950f6a 100644 --- a/vulkan/doc/implementors_guide/implementors_guide.adoc +++ b/vulkan/doc/implementors_guide/implementors_guide.adoc @@ -47,19 +47,7 @@ Our goal is to allow layers to be ported with only build-environment changes bet The +vk_wsi_swapchin+ and +vk_wsi_device_swapchain+ extensions are primarily be implemented by the platform and live in +libvulkan.so+. The +VkSwapchain+ object and all interaction with +ANativeWindow+ will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver's +vkGetDeviceProcAddr+ functions, after passing through any enabled layers. -Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling -[source,c] ----- -VkResult VKAPI vkGetSwapchainGrallocUsageANDROID( - VkDevice device, - VkFormat format, - VkImageUsageFlags imageUsage, - int* grallocUsage -); ----- -The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers. - -Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The additional usage bits are defined as +Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The swapchain usage bits are defined as [source,c] ---- typedef enum VkSwapchainImageUsageFlagBitsANDROID { @@ -69,7 +57,7 @@ typedef enum VkSwapchainImageUsageFlagBitsANDROID { typedef VkFlags VkSwapchainImageUsageFlagsANDROID; ---- -If the driver provides the +vkGetSwapchainGrallocUsage2ANDROID+ function, the platform will use it in preference to +vkGetSwapchainGrallocUsageANDROID+ when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. +vkGetSwapchainGrallocUsage2ANDROID+ behaves in the same way as +vkGetSwapchainGrallocUsageANDROID+, and is declared as +Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling [source,c] ---- VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID( @@ -77,6 +65,19 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID( VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, + uint64_t* grallocConsumerUsage, + uint64_t* grallocProducerUsage, +); +---- +The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocConsumerUsage+ and +*grallocProducerUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers. + +An older version of this function is deprecated but still supported for backwards compatibility; it will be used if +vkGetSwapchainGrallocUsage2ANDROID+ is not supported: +[source,c] +---- +VkResult VKAPI vkGetSwapchainGrallocUsageANDROID( + VkDevice device, + VkFormat format, + VkImageUsageFlags imageUsage, int* grallocUsage ); ---- @@ -95,7 +96,11 @@ typedef struct { // Gralloc format and usage requested when the buffer was allocated. int format; - int usage; + int usage; // deprecated + struct { + uint64_t consumer; + uint64_t producer; + } usage2; } VkNativeBufferANDROID; ---- @@ -200,3 +205,5 @@ If +image+ was created with +VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID+, then * Added VkSwapchainImageUsageFlagBitsANDROID * Added vkGetSwapchainGrallocUsage2ANDROID * Added VkSwapchainImageCreateInfoANDROID +. *2017-02-09* + * Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields.
\ No newline at end of file diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html index 4e74a7854d..9fecce5efa 100644 --- a/vulkan/doc/implementors_guide/implementors_guide.html +++ b/vulkan/doc/implementors_guide/implementors_guide.html @@ -730,7 +730,7 @@ asciidoc.install(2); /*]]>*/ </script> </head> -<body class="article"> +<body class="book"> <div id="header"> <h1>Vulkan on Android Implementor’s Guide</h1> <span id="revnumber">version 5</span> @@ -793,20 +793,7 @@ Injected layers, like framerate, social network, or game launcher overlays, whic <h2 id="_window_system_integration">2. Window System Integration</h2> <div class="sectionbody"> <div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions are primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver’s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div> -<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div> -<div class="listingblock"> -<div class="content"><!-- Generator: GNU source-highlight 3.1.6 -by Lorenzo Bettini -http://www.lorenzobettini.it -http://www.gnu.org/software/src-highlite --> -<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span> - <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span> - <span style="color: #008080">VkFormat</span> format<span style="color: #990000">,</span> - <span style="color: #008080">VkImageUsageFlags</span> imageUsage<span style="color: #990000">,</span> - <span style="color: #009900">int</span><span style="color: #990000">*</span> grallocUsage -<span style="color: #990000">);</span></tt></pre></div></div> -<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div> -<div class="paragraph"><p>Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The additional usage bits are defined as</p></div> +<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The swapchain usage bits are defined as</p></div> <div class="listingblock"> <div class="content"><!-- Generator: GNU source-highlight 3.1.6 by Lorenzo Bettini @@ -817,7 +804,7 @@ http://www.gnu.org/software/src-highlite --> VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM <span style="color: #990000">=</span> <span style="color: #993399">0x7FFFFFFF</span> <span style="color: #FF0000">}</span> VkSwapchainImageUsageFlagBitsANDROID<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="color: #008080">VkFlags</span> VkSwapchainImageUsageFlagsANDROID<span style="color: #990000">;</span></tt></pre></div></div> -<div class="paragraph"><p>If the driver provides the <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> function, the platform will use it in preference to <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span> when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> behaves in the same way as <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span>, and is declared as</p></div> +<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div> <div class="listingblock"> <div class="content"><!-- Generator: GNU source-highlight 3.1.6 by Lorenzo Bettini @@ -828,6 +815,20 @@ http://www.gnu.org/software/src-highlite --> <span style="color: #008080">VkFormat</span> format<span style="color: #990000">,</span> <span style="color: #008080">VkImageUsageFlags</span> imageUsage<span style="color: #990000">,</span> <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> swapchainImageUsage<span style="color: #990000">,</span> + uint64_t<span style="color: #990000">*</span> grallocConsumerUsage<span style="color: #990000">,</span> + uint64_t<span style="color: #990000">*</span> grallocProducerUsage<span style="color: #990000">,</span> +<span style="color: #990000">);</span></tt></pre></div></div> +<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocConsumerUsage</span> and <span class="monospaced">*grallocProducerUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div> +<div class="paragraph"><p>An older version of this function is deprecated but still supported for backwards compatibility; it will be used if <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> is not supported:</p></div> +<div class="listingblock"> +<div class="content"><!-- Generator: GNU source-highlight 3.1.6 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span> + <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span> + <span style="color: #008080">VkFormat</span> format<span style="color: #990000">,</span> + <span style="color: #008080">VkImageUsageFlags</span> imageUsage<span style="color: #990000">,</span> <span style="color: #009900">int</span><span style="color: #990000">*</span> grallocUsage <span style="color: #990000">);</span></tt></pre></div></div> <div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div> @@ -846,7 +847,11 @@ http://www.gnu.org/software/src-highlite --> <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span> <span style="color: #009900">int</span> format<span style="color: #990000">;</span> - <span style="color: #009900">int</span> usage<span style="color: #990000">;</span> + <span style="color: #009900">int</span> usage<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// deprecated</span></span> + <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span> + <span style="color: #008080">uint64_t</span> consumer<span style="color: #990000">;</span> + <span style="color: #008080">uint64_t</span> producer<span style="color: #990000">;</span> + <span style="color: #FF0000">}</span> usage2<span style="color: #990000">;</span> <span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div> <div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div> <div class="listingblock"> @@ -1044,6 +1049,18 @@ Added VkSwapchainImageCreateInfoANDROID </li> </ul></div> </li> +<li> +<p> +<strong>2017-02-09</strong> +</p> +<div class="ulist"><ul> +<li> +<p> +Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields. +</p> +</li> +</ul></div> +</li> </ol></div> </div> </div> @@ -1052,7 +1069,7 @@ Added VkSwapchainImageCreateInfoANDROID <div id="footer"> <div id="footer-text"> Version 5<br> -Last updated 2017-01-12 14:25:30 NZDT +Last updated 2017-02-09 22:40:30 PST </div> </div> </body> diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h index db23e79ef4..d7c5a079e0 100644 --- a/vulkan/include/vulkan/vk_android_native_buffer.h +++ b/vulkan/include/vulkan/vk_android_native_buffer.h @@ -27,6 +27,16 @@ extern "C" { #define VK_ANDROID_native_buffer 1 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11 +/* NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6 + * + * This version of the extension transitions from gralloc0 to gralloc1 usage + * flags (int -> 2x uint64_t). The WSI implementation will temporarily continue + * to fill out deprecated fields in VkNativeBufferANDROID, and will call the + * deprecated vkGetSwapchainGrallocUsageANDROID if the new + * vkGetSwapchainGrallocUsage2ANDROID is not supported. This transitionary + * backwards-compatibility support is temporary, and will likely be removed in + * (along with all gralloc0 support) in a future release. + */ #define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME "VK_ANDROID_native_buffer" @@ -50,7 +60,12 @@ typedef struct { // Gralloc format and usage requested when the buffer was allocated. int format; - int usage; + int usage; // DEPRECATED in SPEC_VERSION 6 + // -- Added in SPEC_VERSION 6 -- + struct { + uint64_t consumer; + uint64_t producer; + } usage2; } VkNativeBufferANDROID; typedef struct { @@ -60,24 +75,30 @@ typedef struct { VkSwapchainImageUsageFlagsANDROID usage; } VkSwapchainImageCreateInfoANDROID; +// -- DEPRECATED in SPEC_VERSION 6 -- typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage); -typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, int* grallocUsage); +// -- ADDED in SPEC_VERSION 6 -- +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage); typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence); typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd); #ifndef VK_NO_PROTOTYPES + +// -- DEPRECATED in SPEC_VERSION 6 -- VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageANDROID( VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage ); +// -- ADDED in SPEC_VERSION 6 -- VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID( VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, - int* grallocUsage + uint64_t* grallocConsumerUsage, + uint64_t* grallocProducerUsage ); VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID( VkDevice device, @@ -93,17 +114,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID( VkImage image, int* pNativeFenceFd ); -// -- DEPRECATED -- -VKAPI_ATTR VkResult VKAPI_CALL vkImportNativeFenceANDROID( - VkDevice device, - VkSemaphore semaphore, - int nativeFenceFd -); -VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalNativeFenceANDROID( - VkQueue queue, - int* pNativeFenceFd -); -// ---------------- #endif #ifdef __cplusplus diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h index 8d24aa738f..16f43e5e7c 100644 --- a/vulkan/include/vulkan/vulkan.h +++ b/vulkan/include/vulkan/vulkan.h @@ -6,7 +6,7 @@ extern "C" { #endif /* -** Copyright (c) 2015-2016 The Khronos Group Inc. +** Copyright (c) 2015-2017 The Khronos Group Inc. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -4608,6 +4608,39 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( VkDeviceGeneratedCommandsLimitsNVX* pLimits); #endif +#define VK_EXT_hdr_metadata 1 +#define VK_EXT_HDR_METADATA_SPEC_VERSION 0 +#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata" + +typedef struct VkXYColorEXT { + float x; + float y; +} VkXYColorEXT; + +typedef struct VkHdrMetadataEXT { + VkStructureType sType; + const void* pNext; + VkXYColorEXT displayPrimaryRed; + VkXYColorEXT displayPrimaryGreen; + VkXYColorEXT displayPrimaryBlue; + VkXYColorEXT whitePoint; + float maxLuminance; + float minLuminance; + float maxContentLightLevel; + float maxFrameAverageLightLevel; +} VkHdrMetadataEXT; + + +typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pMetadata); +#endif + #ifdef __cplusplus } #endif diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl index 501877c8b1..caf38bcb69 100644 --- a/vulkan/libvulkan/code-generator.tmpl +++ b/vulkan/libvulkan/code-generator.tmpl @@ -413,13 +413,14 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{AssertType $ "Function"}} {{$ext := GetAnnotation $ "extension"}} - {{$required := (Macro "IsRequiredFunction" $)}} {{if $ext}} - INIT_PROC_EXT({{Macro "BaseName" $ext}}, {{$required}}, § + INIT_PROC_EXT({{Macro "BaseName" $ext}}, § {{else}} - INIT_PROC({{$required}}, § + INIT_PROC(§ {{end}} + {{if GetAnnotation $ "optional"}}false{{else}}true{{end}}, § + {{if (Macro "IsInstanceDispatched" $)}} instance, § {{else}} @@ -432,25 +433,6 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{/* ------------------------------------------------------------------------------ - Emits true if a function /must/ be resolved. The only time this is not - the case is for extension-added functions added in a later revision of the - extension, and where we have to cope with drivers written against an older - revision. ------------------------------------------------------------------------------- -*/}} -{{define "IsRequiredFunction"}} - {{AssertType $ "Function"}} - - {{if eq $.Name "vkGetSwapchainGrallocUsage2ANDROID"}} - false - {{else}} - true - {{end}} -{{end}} - - -{{/* ------------------------------------------------------------------------------- Emits true if a function is exported and instance-dispatched. ------------------------------------------------------------------------------ */}} @@ -700,11 +682,12 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{define "driver.InterceptedExtensions"}} VK_ANDROID_native_buffer VK_EXT_debug_report +VK_EXT_hdr_metadata +VK_GOOGLE_display_timing VK_KHR_android_surface VK_KHR_incremental_present VK_KHR_surface VK_KHR_swapchain -VK_GOOGLE_display_timing VK_KHR_shared_presentable_image {{end}} @@ -981,6 +964,8 @@ VK_KHR_shared_presentable_image {{else if eq $.Name "vkCreateImage"}}true {{else if eq $.Name "vkDestroyImage"}}true + {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true + {{end}} {{$ext := GetAnnotation $ "extension"}} @@ -1143,8 +1128,9 @@ VK_KHR_shared_presentable_image {{/* ------------------------------------------------------------------------------ - Reports whether an extension is implemented entirely by the loader, - so drivers should not enumerate it. + Reports whether an extension has functions exported by the loader. + E.g. applications can directly link to an extension function. + Currently only support WSI extensions this way. ------------------------------------------------------------------------------ */}} {{define "IsExtensionExported"}} diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 991c3edef4..71bfecfd56 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -472,6 +472,9 @@ void CreateInfoWrapper::FilterExtension(const char* name) { hook_extensions_.set(ext_bit); // return now as these extensions do not require HAL support return; + case ProcHook::EXT_hdr_metadata: + hook_extensions_.set(ext_bit); + break; case ProcHook::EXTENSION_UNKNOWN: // HAL's extensions break; @@ -737,12 +740,14 @@ VkResult EnumerateDeviceExtensionProperties( uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { const InstanceData& data = GetData(physicalDevice); - static const std::array<VkExtensionProperties, 2> loader_extensions = {{ + static const std::array<VkExtensionProperties, 3> loader_extensions = {{ // WSI extensions {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION}, {VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME, VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION}, + {VK_EXT_HDR_METADATA_EXTENSION_NAME, + VK_EXT_HDR_METADATA_SPEC_VERSION}, }}; // enumerate our extensions first @@ -899,7 +904,29 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice, return VK_ERROR_INCOMPATIBLE_DRIVER; } + + // sanity check ANDROID_native_buffer implementation, whose set of + // entrypoints varies according to the spec version. + if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) && + !data->driver.GetSwapchainGrallocUsageANDROID && + !data->driver.GetSwapchainGrallocUsage2ANDROID) { + ALOGE("Driver's implementation of ANDROID_native_buffer is broken;" + " must expose at least one of " + "vkGetSwapchainGrallocUsageANDROID or " + "vkGetSwapchainGrallocUsage2ANDROID"); + + data->driver.DestroyDevice(dev, pAllocator); + FreeDeviceData(data, data_allocator); + + return VK_ERROR_INCOMPATIBLE_DRIVER; + } + + VkPhysicalDeviceProperties properties; + instance_data.driver.GetPhysicalDeviceProperties(physicalDevice, + &properties); + data->driver_device = dev; + data->driver_version = properties.driverVersion; *pDevice = dev; diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h index e05843997c..5383f59b58 100644 --- a/vulkan/libvulkan/driver.h +++ b/vulkan/libvulkan/driver.h @@ -102,6 +102,7 @@ struct DeviceData { VkDevice driver_device; DeviceDriverTable driver; + uint32_t driver_version; }; bool Debuggable(); diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 689a2284f9..59964fb2c9 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -102,6 +102,14 @@ VKAPI_ATTR VkResult checkedGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR } } +VKAPI_ATTR void checkedSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) { + if (GetData(device).hook_extensions[ProcHook::EXT_hdr_metadata]) { + SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata); + } else { + Logger(device).Err(device, "VK_EXT_hdr_metadata not enabled. vkSetHdrMetadataEXT not executed."); + } +} + // clang-format on const ProcHook g_proc_hooks[] = { @@ -330,6 +338,13 @@ const ProcHook g_proc_hooks[] = { nullptr, nullptr, }, + { + "vkSetHdrMetadataEXT", + ProcHook::DEVICE, + ProcHook::EXT_hdr_metadata, + reinterpret_cast<PFN_vkVoidFunction>(SetHdrMetadataEXT), + reinterpret_cast<PFN_vkVoidFunction>(checkedSetHdrMetadataEXT), + }, // clang-format on }; @@ -349,11 +364,12 @@ ProcHook::Extension GetProcHookExtension(const char* name) { // clang-format off if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer; if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report; + if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata; + if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing; if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface; if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present; if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface; if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain; - if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing; if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image; // clang-format on return ProcHook::EXTENSION_UNKNOWN; @@ -387,6 +403,7 @@ bool InitDriverTable(VkInstance instance, INIT_PROC(true, instance, DestroyInstance); INIT_PROC(true, instance, EnumeratePhysicalDevices); INIT_PROC(true, instance, GetInstanceProcAddr); + INIT_PROC(true, instance, GetPhysicalDeviceProperties); INIT_PROC(true, instance, CreateDevice); INIT_PROC(true, instance, EnumerateDeviceExtensionProperties); INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT); @@ -410,7 +427,7 @@ bool InitDriverTable(VkDevice dev, INIT_PROC(true, dev, CreateImage); INIT_PROC(true, dev, DestroyImage); INIT_PROC(true, dev, AllocateCommandBuffers); - INIT_PROC_EXT(ANDROID_native_buffer, true, dev, GetSwapchainGrallocUsageANDROID); + INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsageANDROID); INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID); INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID); INIT_PROC_EXT(ANDROID_native_buffer, true, dev, QueueSignalReleaseImageANDROID); diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 9f3b7054a1..273e796d84 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -35,11 +35,12 @@ struct ProcHook { enum Extension { ANDROID_native_buffer, EXT_debug_report, + EXT_hdr_metadata, + GOOGLE_display_timing, KHR_android_surface, KHR_incremental_present, KHR_surface, KHR_swapchain, - GOOGLE_display_timing, KHR_shared_presentable_image, EXTENSION_CORE, // valid bit @@ -60,6 +61,7 @@ struct InstanceDriverTable { PFN_vkDestroyInstance DestroyInstance; PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices; PFN_vkGetInstanceProcAddr GetInstanceProcAddr; + PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties; PFN_vkCreateDevice CreateDevice; PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties; PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT; diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index f4ee375c81..b1e3d61cf1 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -20,7 +20,7 @@ #include <gui/BufferQueue.h> #include <sync/sync.h> #include <utils/StrongPointer.h> -#include <utils/SortedVector.h> +#include <utils/Vector.h> #include "driver.h" @@ -108,19 +108,11 @@ int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) { class TimingInfo { public: - TimingInfo() - : vals_{0, 0, 0, 0, 0}, - timestamp_desired_present_time_(0), - timestamp_actual_present_time_(0), - timestamp_render_complete_time_(0), - timestamp_composition_latch_time_(0) {} - TimingInfo(const VkPresentTimeGOOGLE* qp) + TimingInfo() = default; + TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId) : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0}, - timestamp_desired_present_time_(0), - timestamp_actual_present_time_(0), - timestamp_render_complete_time_(0), - timestamp_composition_latch_time_(0) {} - bool ready() { + native_frame_id_(nativeFrameId) {} + bool ready() const { return (timestamp_desired_present_time_ && timestamp_actual_present_time_ && timestamp_render_complete_time_ && @@ -148,27 +140,20 @@ class TimingInfo { vals_.earliestPresentTime = early_time; vals_.presentMargin = margin; } - void get_values(VkPastPresentationTimingGOOGLE* values) { *values = vals_; } + void get_values(VkPastPresentationTimingGOOGLE* values) const { + *values = vals_; + } public: - VkPastPresentationTimingGOOGLE vals_; + VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 }; - uint64_t timestamp_desired_present_time_; - uint64_t timestamp_actual_present_time_; - uint64_t timestamp_render_complete_time_; - uint64_t timestamp_composition_latch_time_; + uint64_t native_frame_id_ { 0 }; + uint64_t timestamp_desired_present_time_ { 0 }; + uint64_t timestamp_actual_present_time_ { 0 }; + uint64_t timestamp_render_complete_time_ { 0 }; + uint64_t timestamp_composition_latch_time_ { 0 }; }; -static inline int compare_type(const TimingInfo& lhs, const TimingInfo& rhs) { - // TODO(ianelliott): Change this from presentID to the frame ID once - // brianderson lands the appropriate patch: - if (lhs.vals_.presentID < rhs.vals_.presentID) - return -1; - if (lhs.vals_.presentID > rhs.vals_.presentID) - return 1; - return 0; -} - // ---------------------------------------------------------------------------- struct Surface { @@ -191,11 +176,13 @@ enum { MAX_TIMING_INFOS = 10 }; enum { MIN_NUM_FRAMES_AGO = 5 }; struct Swapchain { - Swapchain(Surface& surface_, uint32_t num_images_) + Swapchain(Surface& surface_, + uint32_t num_images_, + VkPresentModeKHR present_mode) : surface(surface_), num_images(num_images_), + mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR), frame_timestamps_enabled(false) { - timing.clear(); ANativeWindow* window = surface.window.get(); int64_t rdur; native_window_get_refresh_cycle_duration( @@ -206,6 +193,7 @@ struct Swapchain { Surface& surface; uint32_t num_images; + bool mailbox_mode; bool frame_timestamps_enabled; uint64_t refresh_duration; @@ -221,7 +209,7 @@ struct Swapchain { bool dequeued; } images[android::BufferQueue::NUM_BUFFER_SLOTS]; - android::SortedVector<TimingInfo> timing; + android::Vector<TimingInfo> timing; }; VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) { @@ -293,73 +281,64 @@ void OrphanSwapchain(VkDevice device, Swapchain* swapchain) { } uint32_t get_num_ready_timings(Swapchain& swapchain) { + if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) { + return 0; + } + uint32_t num_ready = 0; - uint32_t num_timings = static_cast<uint32_t>(swapchain.timing.size()); - uint32_t frames_ago = num_timings; + const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1; for (uint32_t i = 0; i < num_timings; i++) { - TimingInfo* ti = &swapchain.timing.editItemAt(i); - if (ti) { - if (ti->ready()) { - // This TimingInfo is ready to be reported to the user. Add it - // to the num_ready. - num_ready++; - } else { - // This TimingInfo is not yet ready to be reported to the user, - // and so we should look for any available timestamps that - // might make it ready. - int64_t desired_present_time = 0; - int64_t render_complete_time = 0; - int64_t composition_latch_time = 0; - int64_t actual_present_time = 0; - for (uint32_t f = MIN_NUM_FRAMES_AGO; f < frames_ago; f++) { - // Obtain timestamps: - int ret = native_window_get_frame_timestamps( - swapchain.surface.window.get(), f, - &desired_present_time, &render_complete_time, - &composition_latch_time, - NULL, //&first_composition_start_time, - NULL, //&last_composition_start_time, - NULL, //&composition_finish_time, - // TODO(ianelliott): Maybe ask if this one is - // supported, at startup time (since it may not be - // supported): - &actual_present_time, - NULL, //&display_retire_time, - NULL, //&dequeue_ready_time, - NULL /*&reads_done_time*/); - if (ret) { - break; - } else if (!ret) { - // We obtained at least one valid timestamp. See if it - // is for the present represented by this TimingInfo: - if (static_cast<uint64_t>(desired_present_time) == - ti->vals_.desiredPresentTime) { - // Record the timestamp(s) we received, and then - // see if this TimingInfo is ready to be reported - // to the user: - ti->timestamp_desired_present_time_ = - static_cast<uint64_t>(desired_present_time); - ti->timestamp_actual_present_time_ = - static_cast<uint64_t>(actual_present_time); - ti->timestamp_render_complete_time_ = - static_cast<uint64_t>(render_complete_time); - ti->timestamp_composition_latch_time_ = - static_cast<uint64_t>(composition_latch_time); - - if (ti->ready()) { - // The TimingInfo has received enough - // timestamps, and should now use those - // timestamps to calculate the info that should - // be reported to the user: - // - ti->calculate(swapchain.refresh_duration); - num_ready++; - } - break; - } - } - } - } + TimingInfo& ti = swapchain.timing.editItemAt(i); + if (ti.ready()) { + // This TimingInfo is ready to be reported to the user. Add it + // to the num_ready. + num_ready++; + continue; + } + // This TimingInfo is not yet ready to be reported to the user, + // and so we should look for any available timestamps that + // might make it ready. + int64_t desired_present_time = 0; + int64_t render_complete_time = 0; + int64_t composition_latch_time = 0; + int64_t actual_present_time = 0; + // Obtain timestamps: + int ret = native_window_get_frame_timestamps( + swapchain.surface.window.get(), ti.native_frame_id_, + &desired_present_time, &render_complete_time, + &composition_latch_time, + NULL, //&first_composition_start_time, + NULL, //&last_composition_start_time, + NULL, //&composition_finish_time, + // TODO(ianelliott): Maybe ask if this one is + // supported, at startup time (since it may not be + // supported): + &actual_present_time, + NULL, //&display_retire_time, + NULL, //&dequeue_ready_time, + NULL /*&reads_done_time*/); + + if (ret != android::NO_ERROR) { + continue; + } + + // Record the timestamp(s) we received, and then see if this TimingInfo + // is ready to be reported to the user: + ti.timestamp_desired_present_time_ = + static_cast<uint64_t>(desired_present_time); + ti.timestamp_actual_present_time_ = + static_cast<uint64_t>(actual_present_time); + ti.timestamp_render_complete_time_ = + static_cast<uint64_t>(render_complete_time); + ti.timestamp_composition_latch_time_ = + static_cast<uint64_t>(composition_latch_time); + + if (ti.ready()) { + // The TimingInfo has received enough timestamps, and should now + // use those timestamps to calculate the info that should be + // reported to the user: + ti.calculate(swapchain.refresh_duration); + num_ready++; } } return num_ready; @@ -369,29 +348,35 @@ uint32_t get_num_ready_timings(Swapchain& swapchain) { void copy_ready_timings(Swapchain& swapchain, uint32_t* count, VkPastPresentationTimingGOOGLE* timings) { - uint32_t num_copied = 0; - uint32_t num_timings = static_cast<uint32_t>(swapchain.timing.size()); - if (*count < num_timings) { - num_timings = *count; + if (swapchain.timing.empty()) { + *count = 0; + return; } - for (uint32_t i = 0; i < num_timings; i++) { - TimingInfo* ti = &swapchain.timing.editItemAt(i); - if (ti && ti->ready()) { - ti->get_values(&timings[num_copied]); + + size_t last_ready = swapchain.timing.size() - 1; + while (!swapchain.timing[last_ready].ready()) { + if (last_ready == 0) { + *count = 0; + return; + } + last_ready--; + } + + uint32_t num_copied = 0; + size_t num_to_remove = 0; + for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) { + const TimingInfo& ti = swapchain.timing[i]; + if (ti.ready()) { + ti.get_values(&timings[num_copied]); num_copied++; - // We only report the values for a given present once, so remove - // them from swapchain.timing: - // - // TODO(ianelliott): SEE WHAT HAPPENS TO THE LOOP WHEN THE - // FOLLOWING IS DONE: - swapchain.timing.removeAt(i); - i--; - num_timings--; - if (*count == num_copied) { - break; - } } + num_to_remove++; } + + // Discard old frames that aren't ready if newer frames are ready. + // We don't expect to get the timing info for those old frames. + swapchain.timing.removeItemsAt(0, num_to_remove); + *count = num_copied; } @@ -812,13 +797,35 @@ VkResult CreateSwapchainKHR(VkDevice device, int gralloc_usage = 0; if (dispatch.GetSwapchainGrallocUsage2ANDROID) { - result = dispatch.GetSwapchainGrallocUsage2ANDROID( - device, create_info->imageFormat, create_info->imageUsage, - swapchain_image_usage, &gralloc_usage); + uint64_t consumer_usage, producer_usage; + if (GetData(device).driver_version == 256587285) { + // HACK workaround for loader/driver mismatch during transition to + // vkGetSwapchainGrallocUsage2ANDROID. + typedef VkResult(VKAPI_PTR * + PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK)( + VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, + uint64_t * grallocConsumerUsage, + uint64_t * grallocProducerUsage); + auto get_swapchain_gralloc_usage = + reinterpret_cast<PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK>( + dispatch.GetSwapchainGrallocUsage2ANDROID); + result = get_swapchain_gralloc_usage( + device, create_info->imageFormat, create_info->imageUsage, + &consumer_usage, &producer_usage); + } else { + result = dispatch.GetSwapchainGrallocUsage2ANDROID( + device, create_info->imageFormat, create_info->imageUsage, + swapchain_image_usage, &consumer_usage, &producer_usage); + } if (result != VK_SUCCESS) { ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result); return VK_ERROR_INITIALIZATION_FAILED; } + // TODO: This is the same translation done by Gralloc1On0Adapter. + // Remove it once ANativeWindow has been updated to take gralloc1-style + // usages. + gralloc_usage = + static_cast<int>(consumer_usage) | static_cast<int>(producer_usage); } else if (dispatch.GetSwapchainGrallocUsageANDROID) { result = dispatch.GetSwapchainGrallocUsageANDROID( device, create_info->imageFormat, create_info->imageUsage, @@ -827,8 +834,6 @@ VkResult CreateSwapchainKHR(VkDevice device, ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result); return VK_ERROR_INITIALIZATION_FAILED; } - } else { - gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; } err = native_window_set_usage(surface.window.get(), gralloc_usage); if (err != 0) { @@ -857,7 +862,8 @@ VkResult CreateSwapchainKHR(VkDevice device, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!mem) return VK_ERROR_OUT_OF_HOST_MEMORY; - Swapchain* swapchain = new (mem) Swapchain(surface, num_images); + Swapchain* swapchain = + new (mem) Swapchain(surface, num_images, create_info->presentMode); // -- Dequeue all buffers and create a VkImage for each -- // Any failures during or after this must cancel the dequeued buffers. @@ -918,6 +924,12 @@ VkResult CreateSwapchainKHR(VkDevice device, image_native_buffer.stride = img.buffer->stride; image_native_buffer.format = img.buffer->format; image_native_buffer.usage = img.buffer->usage; + // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage. + // For now, this is the same translation Gralloc1On0Adapter does. + image_native_buffer.usage2.consumer = + static_cast<uint64_t>(img.buffer->usage); + image_native_buffer.usage2.producer = + static_cast<uint64_t>(img.buffer->usage); result = dispatch.CreateImage(device, &image_create, nullptr, &img.image); @@ -1153,7 +1165,8 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { *SwapchainFromHandle(present_info->pSwapchains[sc]); uint32_t image_idx = present_info->pImageIndices[sc]; Swapchain::Image& img = swapchain.images[image_idx]; - const VkPresentRegionKHR* region = (regions) ? ®ions[sc] : nullptr; + const VkPresentRegionKHR* region = + (regions && !swapchain.mailbox_mode) ? ®ions[sc] : nullptr; const VkPresentTimeGOOGLE* time = (times) ? ×[sc] : nullptr; VkResult swapchain_result = VK_SUCCESS; VkResult result; @@ -1219,13 +1232,20 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { native_window_enable_frame_timestamps(window, true); swapchain.frame_timestamps_enabled = true; } - // Record this presentID and desiredPresentTime so it can - // be later correlated to this present. - TimingInfo timing_record(time); - swapchain.timing.add(timing_record); - uint32_t num_timings = - static_cast<uint32_t>(swapchain.timing.size()); - if (num_timings > MAX_TIMING_INFOS) { + + // Record the nativeFrameId so it can be later correlated to + // this present. + uint64_t nativeFrameId = 0; + err = native_window_get_next_frame_id( + window, &nativeFrameId); + if (err != android::NO_ERROR) { + ALOGE("Failed to get next native frame ID."); + } + + // Add a new timing record with the user's presentID and + // the nativeFrameId. + swapchain.timing.push_back(TimingInfo(time, nativeFrameId)); + while (swapchain.timing.size() > MAX_TIMING_INFOS) { swapchain.timing.removeAt(0); } if (time->desiredPresentTime) { @@ -1331,5 +1351,18 @@ VkResult GetSwapchainStatusKHR( return result; } +VKAPI_ATTR void SetHdrMetadataEXT( + VkDevice device, + uint32_t swapchainCount, + const VkSwapchainKHR* pSwapchains, + const VkHdrMetadataEXT* pHdrMetadataEXTs) { + // TODO: courtneygo: implement actual function + (void)device; + (void)swapchainCount; + (void)pSwapchains; + (void)pHdrMetadataEXTs; + return; +} + } // namespace driver } // namespace vulkan diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h index 91d72193c1..4d9f18f301 100644 --- a/vulkan/libvulkan/swapchain.h +++ b/vulkan/libvulkan/swapchain.h @@ -37,6 +37,7 @@ VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* prese VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); VKAPI_ATTR VkResult GetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain); +VKAPI_ATTR void SetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pHdrMetadataEXTs); // clang-format on } // namespace driver diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp index 55f7f19d7c..e03ee0a27a 100644 --- a/vulkan/nulldrv/null_driver.cpp +++ b/vulkan/nulldrv/null_driver.cpp @@ -906,9 +906,11 @@ VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice, VkFormat, VkImageUsageFlags, VkSwapchainImageUsageFlagsANDROID, - int* grallocUsage) { + uint64_t* grallocConsumerUsage, + uint64_t* grallocProducerUsage) { // The null driver never reads or writes the gralloc buffer - *grallocUsage = 0; + *grallocConsumerUsage = 0; + *grallocProducerUsage = 0; return VK_SUCCESS; } diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h index cfc14ddffa..d73bf14411 100644 --- a/vulkan/nulldrv/null_driver_gen.h +++ b/vulkan/nulldrv/null_driver_gen.h @@ -165,8 +165,8 @@ VKAPI_ATTR void CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRender VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents); VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer); VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); -VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage); -VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, int* grallocUsage); +VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int32_t* grallocUsage); +VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage); VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence); VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd); VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); |