12f18b292ff155af7df35930474857b507dbf18feTony Barbour/* 22f18b292ff155af7df35930474857b507dbf18feTony Barbour * Copyright (C) 2016 Google, Inc. 32f18b292ff155af7df35930474857b507dbf18feTony Barbour * 443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Licensed under the Apache License, Version 2.0 (the "License"); 543b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * you may not use this file except in compliance with the License. 643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * You may obtain a copy of the License at 72f18b292ff155af7df35930474857b507dbf18feTony Barbour * 843b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * http://www.apache.org/licenses/LICENSE-2.0 92f18b292ff155af7df35930474857b507dbf18feTony Barbour * 1043b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Unless required by applicable law or agreed to in writing, software 1143b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * distributed under the License is distributed on an "AS IS" BASIS, 1243b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1343b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * See the License for the specific language governing permissions and 1443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * limitations under the License. 152f18b292ff155af7df35930474857b507dbf18feTony Barbour */ 162f18b292ff155af7df35930474857b507dbf18feTony Barbour 172f18b292ff155af7df35930474857b507dbf18feTony Barbour#include <cassert> 182f18b292ff155af7df35930474857b507dbf18feTony Barbour#include <dlfcn.h> 192f18b292ff155af7df35930474857b507dbf18feTony Barbour#include <time.h> 202f18b292ff155af7df35930474857b507dbf18feTony Barbour#include <android/log.h> 212f18b292ff155af7df35930474857b507dbf18feTony Barbour 222f18b292ff155af7df35930474857b507dbf18feTony Barbour#include "Helpers.h" 232f18b292ff155af7df35930474857b507dbf18feTony Barbour#include "Game.h" 242f18b292ff155af7df35930474857b507dbf18feTony Barbour#include "ShellAndroid.h" 252f18b292ff155af7df35930474857b507dbf18feTony Barbour 262f18b292ff155af7df35930474857b507dbf18feTony Barbournamespace { 272f18b292ff155af7df35930474857b507dbf18feTony Barbour 282f18b292ff155af7df35930474857b507dbf18feTony Barbour// copied from ShellXCB.cpp 292f18b292ff155af7df35930474857b507dbf18feTony Barbourclass PosixTimer { 302f18b292ff155af7df35930474857b507dbf18feTony Barbourpublic: 312f18b292ff155af7df35930474857b507dbf18feTony Barbour PosixTimer() 322f18b292ff155af7df35930474857b507dbf18feTony Barbour { 332f18b292ff155af7df35930474857b507dbf18feTony Barbour reset(); 342f18b292ff155af7df35930474857b507dbf18feTony Barbour } 352f18b292ff155af7df35930474857b507dbf18feTony Barbour 362f18b292ff155af7df35930474857b507dbf18feTony Barbour void reset() 372f18b292ff155af7df35930474857b507dbf18feTony Barbour { 382f18b292ff155af7df35930474857b507dbf18feTony Barbour clock_gettime(CLOCK_MONOTONIC, &start_); 392f18b292ff155af7df35930474857b507dbf18feTony Barbour } 402f18b292ff155af7df35930474857b507dbf18feTony Barbour 412f18b292ff155af7df35930474857b507dbf18feTony Barbour double get() const 422f18b292ff155af7df35930474857b507dbf18feTony Barbour { 432f18b292ff155af7df35930474857b507dbf18feTony Barbour struct timespec now; 442f18b292ff155af7df35930474857b507dbf18feTony Barbour clock_gettime(CLOCK_MONOTONIC, &now); 452f18b292ff155af7df35930474857b507dbf18feTony Barbour 462f18b292ff155af7df35930474857b507dbf18feTony Barbour constexpr long one_s_in_ns = 1000 * 1000 * 1000; 472f18b292ff155af7df35930474857b507dbf18feTony Barbour constexpr double one_s_in_ns_d = static_cast<double>(one_s_in_ns); 482f18b292ff155af7df35930474857b507dbf18feTony Barbour 492f18b292ff155af7df35930474857b507dbf18feTony Barbour time_t s = now.tv_sec - start_.tv_sec; 502f18b292ff155af7df35930474857b507dbf18feTony Barbour long ns; 512f18b292ff155af7df35930474857b507dbf18feTony Barbour if (now.tv_nsec > start_.tv_nsec) { 522f18b292ff155af7df35930474857b507dbf18feTony Barbour ns = now.tv_nsec - start_.tv_nsec; 532f18b292ff155af7df35930474857b507dbf18feTony Barbour } else { 542f18b292ff155af7df35930474857b507dbf18feTony Barbour assert(s > 0); 552f18b292ff155af7df35930474857b507dbf18feTony Barbour s--; 562f18b292ff155af7df35930474857b507dbf18feTony Barbour ns = one_s_in_ns - (start_.tv_nsec - now.tv_nsec); 572f18b292ff155af7df35930474857b507dbf18feTony Barbour } 582f18b292ff155af7df35930474857b507dbf18feTony Barbour 592f18b292ff155af7df35930474857b507dbf18feTony Barbour return static_cast<double>(s) + static_cast<double>(ns) / one_s_in_ns_d; 602f18b292ff155af7df35930474857b507dbf18feTony Barbour } 612f18b292ff155af7df35930474857b507dbf18feTony Barbour 622f18b292ff155af7df35930474857b507dbf18feTony Barbourprivate: 632f18b292ff155af7df35930474857b507dbf18feTony Barbour struct timespec start_; 642f18b292ff155af7df35930474857b507dbf18feTony Barbour}; 652f18b292ff155af7df35930474857b507dbf18feTony Barbour 662f18b292ff155af7df35930474857b507dbf18feTony Barbour} // namespace 672f18b292ff155af7df35930474857b507dbf18feTony Barbour 682f18b292ff155af7df35930474857b507dbf18feTony BarbourShellAndroid::ShellAndroid(android_app &app, Game &game) : Shell(game), app_(app) 692f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 702f18b292ff155af7df35930474857b507dbf18feTony Barbour instance_extensions_.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); 712f18b292ff155af7df35930474857b507dbf18feTony Barbour 722f18b292ff155af7df35930474857b507dbf18feTony Barbour app_dummy(); 732f18b292ff155af7df35930474857b507dbf18feTony Barbour app_.userData = this; 742f18b292ff155af7df35930474857b507dbf18feTony Barbour app_.onAppCmd = on_app_cmd; 752f18b292ff155af7df35930474857b507dbf18feTony Barbour app_.onInputEvent = on_input_event; 762f18b292ff155af7df35930474857b507dbf18feTony Barbour 772f18b292ff155af7df35930474857b507dbf18feTony Barbour init_vk(); 782f18b292ff155af7df35930474857b507dbf18feTony Barbour} 792f18b292ff155af7df35930474857b507dbf18feTony Barbour 802f18b292ff155af7df35930474857b507dbf18feTony BarbourShellAndroid::~ShellAndroid() 812f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 822f18b292ff155af7df35930474857b507dbf18feTony Barbour cleanup_vk(); 832f18b292ff155af7df35930474857b507dbf18feTony Barbour dlclose(lib_handle_); 842f18b292ff155af7df35930474857b507dbf18feTony Barbour} 852f18b292ff155af7df35930474857b507dbf18feTony Barbour 862f18b292ff155af7df35930474857b507dbf18feTony Barbourvoid ShellAndroid::log(LogPriority priority, const char *msg) 872f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 882f18b292ff155af7df35930474857b507dbf18feTony Barbour int prio; 892f18b292ff155af7df35930474857b507dbf18feTony Barbour 902f18b292ff155af7df35930474857b507dbf18feTony Barbour switch (priority) { 912f18b292ff155af7df35930474857b507dbf18feTony Barbour case LOG_DEBUG: 922f18b292ff155af7df35930474857b507dbf18feTony Barbour prio = ANDROID_LOG_DEBUG; 932f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 942f18b292ff155af7df35930474857b507dbf18feTony Barbour case LOG_INFO: 952f18b292ff155af7df35930474857b507dbf18feTony Barbour prio = ANDROID_LOG_INFO; 962f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 972f18b292ff155af7df35930474857b507dbf18feTony Barbour case LOG_WARN: 982f18b292ff155af7df35930474857b507dbf18feTony Barbour prio = ANDROID_LOG_WARN; 992f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1002f18b292ff155af7df35930474857b507dbf18feTony Barbour case LOG_ERR: 1012f18b292ff155af7df35930474857b507dbf18feTony Barbour prio = ANDROID_LOG_ERROR; 1022f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1032f18b292ff155af7df35930474857b507dbf18feTony Barbour default: 1042f18b292ff155af7df35930474857b507dbf18feTony Barbour prio = ANDROID_LOG_UNKNOWN; 1052f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1062f18b292ff155af7df35930474857b507dbf18feTony Barbour } 1072f18b292ff155af7df35930474857b507dbf18feTony Barbour 1082f18b292ff155af7df35930474857b507dbf18feTony Barbour __android_log_write(prio, settings_.name.c_str(), msg); 1092f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1102f18b292ff155af7df35930474857b507dbf18feTony Barbour 1112f18b292ff155af7df35930474857b507dbf18feTony BarbourPFN_vkGetInstanceProcAddr ShellAndroid::load_vk() 1122f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1132f18b292ff155af7df35930474857b507dbf18feTony Barbour const char filename[] = "libvulkan.so"; 1142f18b292ff155af7df35930474857b507dbf18feTony Barbour void *handle = nullptr, *symbol = nullptr; 1152f18b292ff155af7df35930474857b507dbf18feTony Barbour 1162f18b292ff155af7df35930474857b507dbf18feTony Barbour handle = dlopen(filename, RTLD_LAZY); 1172f18b292ff155af7df35930474857b507dbf18feTony Barbour if (handle) 1182f18b292ff155af7df35930474857b507dbf18feTony Barbour symbol = dlsym(handle, "vkGetInstanceProcAddr"); 1192f18b292ff155af7df35930474857b507dbf18feTony Barbour if (!symbol) { 1202f18b292ff155af7df35930474857b507dbf18feTony Barbour if (handle) 1212f18b292ff155af7df35930474857b507dbf18feTony Barbour dlclose(handle); 1222f18b292ff155af7df35930474857b507dbf18feTony Barbour 1232f18b292ff155af7df35930474857b507dbf18feTony Barbour throw std::runtime_error(dlerror()); 1242f18b292ff155af7df35930474857b507dbf18feTony Barbour } 1252f18b292ff155af7df35930474857b507dbf18feTony Barbour 1262f18b292ff155af7df35930474857b507dbf18feTony Barbour lib_handle_ = handle; 1272f18b292ff155af7df35930474857b507dbf18feTony Barbour 1282f18b292ff155af7df35930474857b507dbf18feTony Barbour return reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol); 1292f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1302f18b292ff155af7df35930474857b507dbf18feTony Barbour 1312f18b292ff155af7df35930474857b507dbf18feTony BarbourVkSurfaceKHR ShellAndroid::create_surface(VkInstance instance) 1322f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1332f18b292ff155af7df35930474857b507dbf18feTony Barbour VkAndroidSurfaceCreateInfoKHR surface_info = {}; 1342f18b292ff155af7df35930474857b507dbf18feTony Barbour surface_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; 1352f18b292ff155af7df35930474857b507dbf18feTony Barbour surface_info.window = app_.window; 1362f18b292ff155af7df35930474857b507dbf18feTony Barbour 1372f18b292ff155af7df35930474857b507dbf18feTony Barbour VkSurfaceKHR surface; 1382f18b292ff155af7df35930474857b507dbf18feTony Barbour vk::assert_success(vk::CreateAndroidSurfaceKHR(instance, &surface_info, nullptr, &surface)); 1392f18b292ff155af7df35930474857b507dbf18feTony Barbour 1402f18b292ff155af7df35930474857b507dbf18feTony Barbour return surface; 1412f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1422f18b292ff155af7df35930474857b507dbf18feTony Barbour 1432f18b292ff155af7df35930474857b507dbf18feTony Barbourvoid ShellAndroid::on_app_cmd(int32_t cmd) 1442f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1452f18b292ff155af7df35930474857b507dbf18feTony Barbour switch (cmd) { 1462f18b292ff155af7df35930474857b507dbf18feTony Barbour case APP_CMD_INIT_WINDOW: 1472f18b292ff155af7df35930474857b507dbf18feTony Barbour create_context(); 1482f18b292ff155af7df35930474857b507dbf18feTony Barbour resize_swapchain(0, 0); 1492f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1502f18b292ff155af7df35930474857b507dbf18feTony Barbour case APP_CMD_TERM_WINDOW: 1512f18b292ff155af7df35930474857b507dbf18feTony Barbour destroy_context(); 1522f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1532f18b292ff155af7df35930474857b507dbf18feTony Barbour case APP_CMD_WINDOW_RESIZED: 1542f18b292ff155af7df35930474857b507dbf18feTony Barbour resize_swapchain(0, 0); 1552f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1562f18b292ff155af7df35930474857b507dbf18feTony Barbour case APP_CMD_STOP: 1572f18b292ff155af7df35930474857b507dbf18feTony Barbour ANativeActivity_finish(app_.activity); 1582f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1592f18b292ff155af7df35930474857b507dbf18feTony Barbour default: 1602f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1612f18b292ff155af7df35930474857b507dbf18feTony Barbour } 1622f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1632f18b292ff155af7df35930474857b507dbf18feTony Barbour 1642f18b292ff155af7df35930474857b507dbf18feTony Barbourint32_t ShellAndroid::on_input_event(const AInputEvent *event) 1652f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1662f18b292ff155af7df35930474857b507dbf18feTony Barbour if (AInputEvent_getType(event) != AINPUT_EVENT_TYPE_MOTION) 1672f18b292ff155af7df35930474857b507dbf18feTony Barbour return false; 1682f18b292ff155af7df35930474857b507dbf18feTony Barbour 1692f18b292ff155af7df35930474857b507dbf18feTony Barbour bool handled = false; 1702f18b292ff155af7df35930474857b507dbf18feTony Barbour 1712f18b292ff155af7df35930474857b507dbf18feTony Barbour switch (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) { 1722f18b292ff155af7df35930474857b507dbf18feTony Barbour case AMOTION_EVENT_ACTION_UP: 1732f18b292ff155af7df35930474857b507dbf18feTony Barbour game_.on_key(Game::KEY_SPACE); 1742f18b292ff155af7df35930474857b507dbf18feTony Barbour handled = true; 1752f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1762f18b292ff155af7df35930474857b507dbf18feTony Barbour default: 1772f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 1782f18b292ff155af7df35930474857b507dbf18feTony Barbour } 1792f18b292ff155af7df35930474857b507dbf18feTony Barbour 1802f18b292ff155af7df35930474857b507dbf18feTony Barbour return handled; 1812f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1822f18b292ff155af7df35930474857b507dbf18feTony Barbour 1832f18b292ff155af7df35930474857b507dbf18feTony Barbourvoid ShellAndroid::quit() 1842f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1852f18b292ff155af7df35930474857b507dbf18feTony Barbour ANativeActivity_finish(app_.activity); 1862f18b292ff155af7df35930474857b507dbf18feTony Barbour} 1872f18b292ff155af7df35930474857b507dbf18feTony Barbour 1882f18b292ff155af7df35930474857b507dbf18feTony Barbourvoid ShellAndroid::run() 1892f18b292ff155af7df35930474857b507dbf18feTony Barbour{ 1902f18b292ff155af7df35930474857b507dbf18feTony Barbour PosixTimer timer; 1912f18b292ff155af7df35930474857b507dbf18feTony Barbour 1922f18b292ff155af7df35930474857b507dbf18feTony Barbour double current_time = timer.get(); 1932f18b292ff155af7df35930474857b507dbf18feTony Barbour 1942f18b292ff155af7df35930474857b507dbf18feTony Barbour while (true) { 1952f18b292ff155af7df35930474857b507dbf18feTony Barbour struct android_poll_source *source; 1962f18b292ff155af7df35930474857b507dbf18feTony Barbour while (true) { 1972f18b292ff155af7df35930474857b507dbf18feTony Barbour int timeout = (settings_.animate && app_.window) ? 0 : -1; 1982f18b292ff155af7df35930474857b507dbf18feTony Barbour if (ALooper_pollAll(timeout, nullptr, nullptr, 1992f18b292ff155af7df35930474857b507dbf18feTony Barbour reinterpret_cast<void **>(&source)) < 0) 2002f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 2012f18b292ff155af7df35930474857b507dbf18feTony Barbour 2022f18b292ff155af7df35930474857b507dbf18feTony Barbour if (source) 2032f18b292ff155af7df35930474857b507dbf18feTony Barbour source->process(&app_, source); 2042f18b292ff155af7df35930474857b507dbf18feTony Barbour } 2052f18b292ff155af7df35930474857b507dbf18feTony Barbour 2062f18b292ff155af7df35930474857b507dbf18feTony Barbour if (app_.destroyRequested) 2072f18b292ff155af7df35930474857b507dbf18feTony Barbour break; 2082f18b292ff155af7df35930474857b507dbf18feTony Barbour 2092f18b292ff155af7df35930474857b507dbf18feTony Barbour if (!app_.window) 2102f18b292ff155af7df35930474857b507dbf18feTony Barbour continue; 2112f18b292ff155af7df35930474857b507dbf18feTony Barbour 2122f18b292ff155af7df35930474857b507dbf18feTony Barbour acquire_back_buffer(); 2132f18b292ff155af7df35930474857b507dbf18feTony Barbour 2142f18b292ff155af7df35930474857b507dbf18feTony Barbour double t = timer.get(); 2152f18b292ff155af7df35930474857b507dbf18feTony Barbour add_game_time(static_cast<float>(t - current_time)); 2162f18b292ff155af7df35930474857b507dbf18feTony Barbour 2172f18b292ff155af7df35930474857b507dbf18feTony Barbour present_back_buffer(); 2182f18b292ff155af7df35930474857b507dbf18feTony Barbour 2192f18b292ff155af7df35930474857b507dbf18feTony Barbour current_time = t; 2202f18b292ff155af7df35930474857b507dbf18feTony Barbour } 2212f18b292ff155af7df35930474857b507dbf18feTony Barbour} 222