From 24aa429488190245890c54fd076956a2d536fcad Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 7 Jul 2019 22:23:24 -0400 Subject: [PATCH] android: frontend: Add base project. --- src/CMakeLists.txt | 4 + src/citra_android/jni/CMakeLists.txt | 37 + src/citra_android/jni/button_manager.cpp | 318 +++++++++ src/citra_android/jni/button_manager.h | 135 ++++ src/citra_android/jni/config.cpp | 223 ++++++ src/citra_android/jni/config.h | 26 + src/citra_android/jni/default_ini.h | 259 +++++++ .../jni/emu_window/emu_window.cpp | 87 +++ src/citra_android/jni/emu_window/emu_window.h | 59 ++ src/citra_android/jni/game_info.cpp | 113 +++ src/citra_android/jni/game_info.h | 17 + src/citra_android/jni/native.cpp | 475 +++++++++++++ src/citra_android/jni/native.h | 186 +++++ .../jni/ndk_helper/CMakeLists.txt | 28 + .../jni/ndk_helper/GLContext.cpp | 271 +++++++ src/citra_android/jni/ndk_helper/GLContext.h | 114 +++ src/citra_android/jni/ndk_helper/gl3stub.c | 421 +++++++++++ src/citra_android/jni/ndk_helper/gl3stub.cpp | 421 +++++++++++ src/citra_android/jni/ndk_helper/gl3stub.h | 661 ++++++++++++++++++ 19 files changed, 3855 insertions(+) create mode 100644 src/citra_android/jni/CMakeLists.txt create mode 100644 src/citra_android/jni/button_manager.cpp create mode 100644 src/citra_android/jni/button_manager.h create mode 100644 src/citra_android/jni/config.cpp create mode 100644 src/citra_android/jni/config.h create mode 100644 src/citra_android/jni/default_ini.h create mode 100644 src/citra_android/jni/emu_window/emu_window.cpp create mode 100644 src/citra_android/jni/emu_window/emu_window.h create mode 100644 src/citra_android/jni/game_info.cpp create mode 100644 src/citra_android/jni/game_info.h create mode 100644 src/citra_android/jni/native.cpp create mode 100644 src/citra_android/jni/native.h create mode 100644 src/citra_android/jni/ndk_helper/CMakeLists.txt create mode 100644 src/citra_android/jni/ndk_helper/GLContext.cpp create mode 100644 src/citra_android/jni/ndk_helper/GLContext.h create mode 100644 src/citra_android/jni/ndk_helper/gl3stub.c create mode 100644 src/citra_android/jni/ndk_helper/gl3stub.cpp create mode 100644 src/citra_android/jni/ndk_helper/gl3stub.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1ada1b3eb..9aeae6e91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,6 +103,10 @@ add_subdirectory(network) add_subdirectory(input_common) add_subdirectory(tests) +if(ANDROID) + add_subdirectory(citra_android/jni) +endif() + if (ENABLE_SDL2) add_subdirectory(citra) endif() diff --git a/src/citra_android/jni/CMakeLists.txt b/src/citra_android/jni/CMakeLists.txt new file mode 100644 index 000000000..01cce41f9 --- /dev/null +++ b/src/citra_android/jni/CMakeLists.txt @@ -0,0 +1,37 @@ +add_subdirectory(ndk_helper) + +add_library(main SHARED + button_manager.cpp + button_manager.h + config.cpp + config.h + default_ini.h + emu_window/emu_window.cpp + emu_window/emu_window.h + game_info.cpp + game_info.h + native.cpp + native.h +) + +target_link_libraries(main +PRIVATE + common + core + input_common + network + glad + inih +) + +target_link_libraries(main +PRIVATE + android + log + ndk_helper + "-Wl,--no-warn-mismatch" + "-Wl,--whole-archive" + "-Wl,--no-whole-archive" +) + +set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} main) diff --git a/src/citra_android/jni/button_manager.cpp b/src/citra_android/jni/button_manager.cpp new file mode 100644 index 000000000..f8f4890c1 --- /dev/null +++ b/src/citra_android/jni/button_manager.cpp @@ -0,0 +1,318 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include "citra_android/jni/button_manager.h" +#include "common/logging/log.h" +#include "common/math_util.h" +#include "common/param_package.h" +#include "input_common/main.h" +#include "input_common/sdl/sdl.h" + +namespace InputManager { + +static std::shared_ptr button; +static std::shared_ptr analog; + +// Button Handler +class KeyButton final : public Input::ButtonDevice { +public: + explicit KeyButton(std::shared_ptr button_list_) : button_list(button_list_) {} + + ~KeyButton(); + + bool GetStatus() const override { + return status.load(); + } + + friend class ButtonList; + +private: + std::shared_ptr button_list; + std::atomic status{false}; +}; + +struct KeyButtonPair { + int button_id; + KeyButton* key_button; +}; + +class ButtonList { +public: + void AddButton(int button_id, KeyButton* key_button) { + std::lock_guard guard(mutex); + list.push_back(KeyButtonPair{button_id, key_button}); + } + + void RemoveButton(const KeyButton* key_button) { + std::lock_guard guard(mutex); + list.remove_if( + [key_button](const KeyButtonPair& pair) { return pair.key_button == key_button; }); + } + + bool ChangeButtonStatus(int button_id, bool pressed) { + std::lock_guard guard(mutex); + for (const KeyButtonPair& pair : list) { + if (pair.button_id == button_id) { + pair.key_button->status.store(pressed); + return true; + } + } + // If we don't find the button don't consume the button press event + return false; + } + + void ChangeAllButtonStatus(bool pressed) { + std::lock_guard guard(mutex); + for (const KeyButtonPair& pair : list) { + pair.key_button->status.store(pressed); + } + } + +private: + std::mutex mutex; + std::list list; +}; + +KeyButton::~KeyButton() { + button_list->RemoveButton(this); +} + +// Analog Button +class AnalogButton final : public Input::ButtonDevice { +public: + explicit AnalogButton(std::shared_ptr button_list_, float threshold_, + bool trigger_if_greater_) + : button_list(button_list_), threshold(threshold_), + trigger_if_greater(trigger_if_greater_) {} + + ~AnalogButton(); + + bool GetStatus() const override { + if (trigger_if_greater) + return axis_val.load() > threshold; + return axis_val.load() < threshold; + } + + friend class AnalogButtonList; + +private: + std::shared_ptr button_list; + std::atomic axis_val{0.0f}; + float threshold; + bool trigger_if_greater; +}; + +struct AnalogButtonPair { + int axis_id; + AnalogButton* key_button; +}; + +class AnalogButtonList { +public: + void AddAnalogButton(int button_id, AnalogButton* key_button) { + std::lock_guard guard(mutex); + list.push_back(AnalogButtonPair{button_id, key_button}); + } + + void RemoveButton(const AnalogButton* key_button) { + std::lock_guard guard(mutex); + list.remove_if( + [key_button](const AnalogButtonPair& pair) { return pair.key_button == key_button; }); + } + + bool ChangeAxisValue(int axis_id, float axis) { + std::lock_guard guard(mutex); + for (const AnalogButtonPair& pair : list) { + if (pair.axis_id == axis_id) { + pair.key_button->axis_val.store(axis); + return true; + } + } + // If we don't find the button don't consume the button press event + return false; + } + +private: + std::mutex mutex; + std::list list; +}; + +AnalogButton::~AnalogButton() { + button_list->RemoveButton(this); +} + +// Joystick Handler +class Joystick final : public Input::AnalogDevice { +public: + explicit Joystick(std::shared_ptr analog_list_) : analog_list(analog_list_) {} + + ~Joystick(); + + std::tuple GetStatus() const override { + return std::make_tuple(x_axis.load(), y_axis.load()); + } + + friend class AnalogList; + +private: + std::shared_ptr analog_list; + std::atomic x_axis{0.0f}; + std::atomic y_axis{0.0f}; +}; + +struct AnalogPair { + int analog_id; + Joystick* key_button; +}; + +class AnalogList { +public: + void AddButton(int analog_id, Joystick* key_button) { + std::lock_guard guard(mutex); + list.push_back(AnalogPair{analog_id, key_button}); + } + + void RemoveButton(const Joystick* key_button) { + std::lock_guard guard(mutex); + list.remove_if( + [key_button](const AnalogPair& pair) { return pair.key_button == key_button; }); + } + + bool ChangeJoystickStatus(int analog_id, float x, float y) { + std::lock_guard guard(mutex); + for (const AnalogPair& pair : list) { + if (pair.analog_id == analog_id) { + pair.key_button->x_axis.store(x); + pair.key_button->y_axis.store(y); + return true; + } + } + return false; + } + +private: + std::mutex mutex; + std::list list; +}; + +AnalogFactory::AnalogFactory() : analog_list{std::make_shared()} {} + +Joystick::~Joystick() { + analog_list->RemoveButton(this); +} + +ButtonFactory::ButtonFactory() + : button_list{std::make_shared()}, analog_button_list{ + std::make_shared()} {} + +std::unique_ptr ButtonFactory::Create(const Common::ParamPackage& params) { + if (params.Has("axis")) { + const int axis_id = params.Get("axis", 0); + const float threshold = params.Get("threshold", 0.5f); + const std::string direction_name = params.Get("direction", ""); + bool trigger_if_greater; + if (direction_name == "+") { + trigger_if_greater = true; + } else if (direction_name == "-") { + trigger_if_greater = false; + } else { + trigger_if_greater = true; + LOG_ERROR(Input, "Unknown direction {}", direction_name); + } + std::unique_ptr analog_button = + std::make_unique(analog_button_list, threshold, trigger_if_greater); + analog_button_list->AddAnalogButton(axis_id, analog_button.get()); + return std::move(analog_button); + } + + int button_id = params.Get("code", 0); + std::unique_ptr key_button = std::make_unique(button_list); + button_list->AddButton(button_id, key_button.get()); + return std::move(key_button); +} + +bool ButtonFactory::PressKey(int button_id) { + return button_list->ChangeButtonStatus(button_id, true); +} + +bool ButtonFactory::ReleaseKey(int button_id) { + return button_list->ChangeButtonStatus(button_id, false); +} + +bool ButtonFactory::AnalogButtonEvent(int axis_id, float axis_val) { + return analog_button_list->ChangeAxisValue(axis_id, axis_val); +} + +std::unique_ptr AnalogFactory::Create(const Common::ParamPackage& params) { + int analog_id = params.Get("code", 0); + std::unique_ptr analog = std::make_unique(analog_list); + analog_list->AddButton(analog_id, analog.get()); + return std::move(analog); +} + +bool AnalogFactory::MoveJoystick(int analog_id, float x, float y) { + return analog_list->ChangeJoystickStatus(analog_id, x, y); +} + +ButtonFactory* ButtonHandler() { + return button.get(); +} + +AnalogFactory* AnalogHandler() { + return analog.get(); +} + +std::string GenerateButtonParamPackage(int button) { + Common::ParamPackage param{ + {"engine", "gamepad"}, + {"code", std::to_string(button)}, + }; + return param.Serialize(); +} + +std::string GenerateAnalogButtonParamPackage(int axis, float axis_val) { + Common::ParamPackage param{ + {"engine", "gamepad"}, + {"axis", std::to_string(axis)}, + }; + if (axis_val > 0) { + param.Set("direction", "+"); + param.Set("threshold", "0.5"); + } else { + param.Set("direction", "-"); + param.Set("threshold", "-0.5"); + } + + return param.Serialize(); +} + +std::string GenerateAnalogParamPackage(int axis_id) { + Common::ParamPackage param{ + {"engine", "gamepad"}, + {"code", std::to_string(axis_id)}, + }; + return param.Serialize(); +} + +void Init() { + button = std::make_shared(); + analog = std::make_shared(); + Input::RegisterFactory("gamepad", button); + Input::RegisterFactory("gamepad", analog); +} + +void Shutdown() { + Input::UnregisterFactory("gamepad"); + button.reset(); + analog.reset(); +} + +} // namespace InputManager diff --git a/src/citra_android/jni/button_manager.h b/src/citra_android/jni/button_manager.h new file mode 100644 index 000000000..6c6e4236c --- /dev/null +++ b/src/citra_android/jni/button_manager.h @@ -0,0 +1,135 @@ +// Copyright 2013 Dolphin Emulator Project / 2017 Citra Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include "core/frontend/input.h" + +namespace InputManager { + +enum ButtonType { + // 3DS Controls + N3DS_BUTTON_A = 700, + N3DS_BUTTON_B = 701, + N3DS_BUTTON_X = 702, + N3DS_BUTTON_Y = 703, + N3DS_BUTTON_START = 704, + N3DS_BUTTON_SELECT = 705, + N3DS_BUTTON_HOME = 706, + N3DS_BUTTON_ZL = 707, + N3DS_BUTTON_ZR = 708, + N3DS_DPAD_UP = 709, + N3DS_DPAD_DOWN = 710, + N3DS_DPAD_LEFT = 711, + N3DS_DPAD_RIGHT = 712, + N3DS_CIRCLEPAD = 713, + N3DS_CIRCLEPAD_UP = 714, + N3DS_CIRCLEPAD_DOWN = 715, + N3DS_CIRCLEPAD_LEFT = 716, + N3DS_CIRCLEPAD_RIGHT = 717, + N3DS_STICK_C = 718, + N3DS_STICK_C_UP = 719, + N3DS_STICK_C_DOWN = 720, + N3DS_STICK_C_LEFT = 771, + N3DS_STICK_C_RIGHT = 772, + N3DS_TRIGGER_L = 773, + N3DS_TRIGGER_R = 774, +}; + +class ButtonList; +class AnalogButtonList; +class AnalogList; + +/** + * A button device factory representing a gamepad. It receives input events and forward them + * to all button devices it created. + */ +class ButtonFactory final : public Input::Factory { +public: + ButtonFactory(); + + /** + * Creates a button device from a gamepad button + * @param params contains parameters for creating the device: + * - "code": the code of the key to bind with the button + */ + std::unique_ptr Create(const Common::ParamPackage& params) override; + + /** + * Sets the status of all buttons bound with the key to pressed + * @param key_code the code of the key to press + * @return whether the key event is consumed or not + */ + bool PressKey(int button_id); + + /** + * Sets the status of all buttons bound with the key to released + * @param key_code the code of the key to release + * @return whether the key event is consumed or not + */ + bool ReleaseKey(int button_id); + + /** + * Sets the status of all buttons bound with the key to released + * @param axis_id the code of the axis + * @param axis_val the value of the axis + * @return whether the key event is consumed or not + */ + bool AnalogButtonEvent(int axis_id, float axis_val); + + void ReleaseAllKeys(); + +private: + std::shared_ptr button_list; + std::shared_ptr analog_button_list; +}; + +/** + * An analog device factory representing a gamepad(virtual or physical). It receives input events + * and forward them to all analog devices it created. + */ +class AnalogFactory final : public Input::Factory { +public: + AnalogFactory(); + + /** + * Creates an analog device from the gamepad joystick + * @param params contains parameters for creating the device: + * - "code": the code of the key to bind with the button + */ + std::unique_ptr Create(const Common::ParamPackage& params) override; + + /** + * Sets the status of all buttons bound with the key to pressed + * @param key_code the code of the analog stick + * @param x the x-axis value of the analog stick + * @param y the y-axis value of the analog stick + */ + bool MoveJoystick(int analog_id, float x, float y); + +private: + std::shared_ptr analog_list; +}; + +/// Initializes and registers all built-in input device factories. +void Init(); + +/// Deregisters all built-in input device factories and shuts them down. +void Shutdown(); + +/// Gets the gamepad button device factory. +ButtonFactory* ButtonHandler(); + +/// Gets the gamepad analog device factory. +AnalogFactory* AnalogHandler(); + +std::string GenerateButtonParamPackage(int type); + +std::string GenerateAnalogButtonParamPackage(int axis, float axis_val); + +std::string GenerateAnalogParamPackage(int type); +} // namespace InputManager \ No newline at end of file diff --git a/src/citra_android/jni/config.cpp b/src/citra_android/jni/config.cpp new file mode 100644 index 000000000..7c2e143d9 --- /dev/null +++ b/src/citra_android/jni/config.cpp @@ -0,0 +1,223 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include + +#include "citra_android/jni/button_manager.h" +#include "citra_android/jni/config.h" +#include "citra_android/jni/default_ini.h" +#include "common/file_util.h" +#include "common/logging/log.h" +#include "common/param_package.h" +#include "core/hle/service/service.h" +#include "core/settings.h" +#include "input_common/main.h" +#include "input_common/udp/client.h" + +Config::Config() { + // TODO: Don't hardcode the path; let the frontend decide where to put the config files. + sdl2_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "config.ini"; + sdl2_config = std::make_unique(sdl2_config_loc); + + Reload(); +} + +Config::~Config() = default; + +bool Config::LoadINI(const std::string& default_contents, bool retry) { + const char* location = this->sdl2_config_loc.c_str(); + if (sdl2_config->ParseError() < 0) { + if (retry) { + LOG_WARNING(Config, "Failed to load %s. Creating file from defaults...", location); + FileUtil::CreateFullPath(location); + FileUtil::WriteStringToFile(true, default_contents, location); + sdl2_config = std::make_unique(location); // Reopen file + + return LoadINI(default_contents, false); + } + LOG_ERROR(Config, "Failed."); + return false; + } + LOG_INFO(Config, "Successfully loaded %s", location); + return true; +} + +static const std::array default_buttons = { + InputManager::N3DS_BUTTON_A, InputManager::N3DS_BUTTON_B, InputManager::N3DS_BUTTON_X, + InputManager::N3DS_BUTTON_Y, InputManager::N3DS_DPAD_UP, InputManager::N3DS_DPAD_DOWN, + InputManager::N3DS_DPAD_LEFT, InputManager::N3DS_DPAD_RIGHT, InputManager::N3DS_TRIGGER_L, + InputManager::N3DS_TRIGGER_R, InputManager::N3DS_BUTTON_START, InputManager::N3DS_BUTTON_SELECT, + InputManager::N3DS_BUTTON_ZL, InputManager::N3DS_BUTTON_ZR, InputManager::N3DS_BUTTON_HOME, +}; + +static const std::array default_analogs{{ + InputManager::N3DS_CIRCLEPAD, + InputManager::N3DS_STICK_C, +}}; + +void Config::ReadValues() { + // Controls + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + std::string default_param = InputManager::GenerateButtonParamPackage(default_buttons[i]); + Settings::values.current_input_profile.buttons[i] = + sdl2_config->Get("Controls", Settings::NativeButton::mapping[i], default_param); + if (Settings::values.current_input_profile.buttons[i].empty()) + Settings::values.current_input_profile.buttons[i] = default_param; + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + std::string default_param = InputManager::GenerateAnalogParamPackage(default_analogs[i]); + Settings::values.current_input_profile.analogs[i] = + sdl2_config->Get("Controls", Settings::NativeAnalog::mapping[i], default_param); + if (Settings::values.current_input_profile.analogs[i].empty()) + Settings::values.current_input_profile.analogs[i] = default_param; + } + + Settings::values.current_input_profile.motion_device = + sdl2_config->Get("Controls", "motion_device", + "engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0"); + Settings::values.current_input_profile.touch_device = + sdl2_config->Get("Controls", "touch_device", "engine:emu_window"); + Settings::values.current_input_profile.udp_input_address = + sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR); + Settings::values.current_input_profile.udp_input_port = static_cast(sdl2_config->GetInteger( + "Controls", "udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT)); + + // Core + Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); + + // Renderer + Settings::values.use_gles = sdl2_config->GetBoolean("Renderer", "use_gles", true); + Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true); + Settings::values.use_hw_shader = sdl2_config->GetBoolean("Renderer", "use_hw_shader", true); + Settings::values.shaders_accurate_gs = + sdl2_config->GetBoolean("Renderer", "shaders_accurate_gs", true); + Settings::values.shaders_accurate_mul = + sdl2_config->GetBoolean("Renderer", "shaders_accurate_mul", false); + Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true); + Settings::values.resolution_factor = + static_cast(sdl2_config->GetInteger("Renderer", "resolution_factor", 1)); + Settings::values.use_frame_limit = sdl2_config->GetBoolean("Renderer", "use_frame_limit", true); + Settings::values.frame_limit = + static_cast(sdl2_config->GetInteger("Renderer", "frame_limit", 100)); + + Settings::values.toggle_3d = sdl2_config->GetBoolean("Renderer", "toggle_3d", false); + Settings::values.factor_3d = + static_cast(sdl2_config->GetInteger("Renderer", "factor_3d", 0)); + + Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 0.0); + Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 0.0); + Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 0.0); + + // Layout + Settings::values.layout_option = + static_cast(sdl2_config->GetInteger("Layout", "layout_option", 0)); + Settings::values.swap_screen = sdl2_config->GetBoolean("Layout", "swap_screen", false); + Settings::values.custom_layout = sdl2_config->GetBoolean("Layout", "custom_layout", false); + Settings::values.custom_top_left = + static_cast(sdl2_config->GetInteger("Layout", "custom_top_left", 0)); + Settings::values.custom_top_top = + static_cast(sdl2_config->GetInteger("Layout", "custom_top_top", 0)); + Settings::values.custom_top_right = + static_cast(sdl2_config->GetInteger("Layout", "custom_top_right", 400)); + Settings::values.custom_top_bottom = + static_cast(sdl2_config->GetInteger("Layout", "custom_top_bottom", 240)); + Settings::values.custom_bottom_left = + static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_left", 40)); + Settings::values.custom_bottom_top = + static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_top", 240)); + Settings::values.custom_bottom_right = + static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360)); + Settings::values.custom_bottom_bottom = + static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480)); + + // Audio + Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); + Settings::values.enable_audio_stretching = + sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); + Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); + Settings::values.volume = sdl2_config->GetReal("Audio", "volume", 1); + + // Data Storage + Settings::values.use_virtual_sd = + sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); + + // System + Settings::values.is_new_3ds = sdl2_config->GetBoolean("System", "is_new_3ds", false); + Settings::values.region_value = + sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT); + Settings::values.init_clock = + static_cast(sdl2_config->GetInteger("System", "init_clock", 0)); + { + std::tm t; + t.tm_sec = 1; + t.tm_min = 0; + t.tm_hour = 0; + t.tm_mday = 1; + t.tm_mon = 0; + t.tm_year = 100; + t.tm_isdst = 0; + std::istringstream string_stream( + sdl2_config->Get("System", "init_time", "2000-01-01 00:00:01")); + string_stream >> std::get_time(&t, "%Y-%m-%d %H:%M:%S"); + if (string_stream.fail()) { + LOG_ERROR(Config, "Failed To parse init_time. Using 2000-01-01 00:00:01"); + } + Settings::values.init_time = + std::chrono::duration_cast( + std::chrono::system_clock::from_time_t(std::mktime(&t)).time_since_epoch()) + .count(); + } + + // Camera + using namespace Service::CAM; + Settings::values.camera_name[OuterRightCamera] = + sdl2_config->Get("Camera", "camera_outer_right_name", "blank"); + Settings::values.camera_config[OuterRightCamera] = + sdl2_config->Get("Camera", "camera_outer_right_config", ""); + Settings::values.camera_flip[OuterRightCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_right_flip", 0); + Settings::values.camera_name[InnerCamera] = + sdl2_config->Get("Camera", "camera_inner_name", "blank"); + Settings::values.camera_config[InnerCamera] = + sdl2_config->Get("Camera", "camera_inner_config", ""); + Settings::values.camera_flip[InnerCamera] = + sdl2_config->GetInteger("Camera", "camera_inner_flip", 0); + Settings::values.camera_name[OuterLeftCamera] = + sdl2_config->Get("Camera", "camera_outer_left_name", "blank"); + Settings::values.camera_config[OuterLeftCamera] = + sdl2_config->Get("Camera", "camera_outer_left_config", ""); + Settings::values.camera_flip[OuterLeftCamera] = + sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0); + + // Miscellaneous + Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); + + // Debugging + Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); + Settings::values.gdbstub_port = + static_cast(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); + + for (const auto& service_module : Service::service_module_map) { + bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false); + Settings::values.lle_modules.emplace(service_module.name, use_lle); + } + + // Web Service + Settings::values.enable_telemetry = + sdl2_config->GetBoolean("WebService", "enable_telemetry", true); + Settings::values.web_api_url = + sdl2_config->GetString("WebService", "web_api_url", "https://api.citra-emu.org"); + Settings::values.citra_username = sdl2_config->GetString("WebService", "citra_username", ""); + Settings::values.citra_token = sdl2_config->GetString("WebService", "citra_token", ""); +} + +void Config::Reload() { + LoadINI(DefaultINI::sdl2_config_file); + ReadValues(); +} diff --git a/src/citra_android/jni/config.h b/src/citra_android/jni/config.h new file mode 100644 index 000000000..ca5ab8c07 --- /dev/null +++ b/src/citra_android/jni/config.h @@ -0,0 +1,26 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +class INIReader; + +class Config { + std::unique_ptr sdl2_config; + std::string sdl2_config_loc; + + bool LoadINI(const std::string& default_contents = "", bool retry = true); + + void ReadValues(); + +public: + Config(); + + ~Config(); + + void Reload(); +}; diff --git a/src/citra_android/jni/default_ini.h b/src/citra_android/jni/default_ini.h new file mode 100644 index 000000000..ad3c67882 --- /dev/null +++ b/src/citra_android/jni/default_ini.h @@ -0,0 +1,259 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace DefaultINI { + +const char* sdl2_config_file = R"( +[Controls] +# The input devices and parameters for each 3DS native input +# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." +# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values + +# for button input, the following devices are available: +# - "keyboard" (default) for keyboard input. Required parameters: +# - "code": the code of the key to bind +# - "sdl" for joystick input using SDL. Required parameters: +# - "joystick": the index of the joystick to bind +# - "button"(optional): the index of the button to bind +# - "hat"(optional): the index of the hat to bind as direction buttons +# - "axis"(optional): the index of the axis to bind +# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right" +# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is +# triggered if the axis value crosses +# - "direction"(only used for axis): "+" means the button is triggered when the axis value +# is greater than the threshold; "-" means the button is triggered when the axis value +# is smaller than the threshold +button_a= +button_b= +button_x= +button_y= +button_up= +button_down= +button_left= +button_right= +button_l= +button_r= +button_start= +button_select= +button_zl= +button_zr= +button_home= + +# for analog input, the following devices are available: +# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: +# - "up", "down", "left", "right": sub-devices for each direction. +# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00" +# - "modifier": sub-devices as a modifier. +# - "modifier_scale": a float number representing the applied modifier scale to the analog input. +# Must be in range of 0.0-1.0. Defaults to 0.5 +# - "sdl" for joystick input using SDL. Required parameters: +# - "joystick": the index of the joystick to bind +# - "axis_x": the index of the axis to bind as x-axis (default to 0) +# - "axis_y": the index of the axis to bind as y-axis (default to 1) +circle_pad= +c_stick= + +# for motion input, the following devices are available: +# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: +# - "update_period": update period in milliseconds (default to 100) +# - "sensitivity": the coefficient converting mouse movement to tilting angle (default to 0.01) +# - "tilt_clamp": the max value of the tilt angle in degrees (default to 90) +# - "cemuhookudp" reads motion input from a udp server that uses cemuhook's udp protocol +motion_device= + +# for touch input, the following devices are available: +# - "emu_window" (default) for emulating touch input from mouse input to the emulation window. No parameters required +# - "cemuhookudp" reads touch input from a udp server that uses cemuhook's udp protocol +# - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system +touch_device= engine:emu_window + +# Most desktop operating systems do not expose a way to poll the motion state of the controllers +# so as a way around it, cemuhook created a udp client/server protocol to broadcast the data directly +# from a controller device to the client program. Citra has a client that can connect and read +# from any cemuhook compatible motion program. + +# IPv4 address of the udp input server (Default "127.0.0.1") +udp_input_address= + +# Port of the udp input server. (Default 26760) +udp_input_port= + +# The pad to request data on. Should be between 0 (Pad 1) and 3 (Pad 4). (Default 0) +udp_pad_index= + +[Core] +# Whether to use the Just-In-Time (JIT) compiler for CPU emulation +# 0: Interpreter (slow), 1 (default): JIT (fast) +use_cpu_jit = + +[Renderer] +# Whether to use software or hardware rendering. +# 0: Software, 1 (default): Hardware +use_hw_renderer = + +# Whether to use hardware shaders to emulate 3DS shaders +# 0: Software, 1 (default): Hardware +use_hw_shader = + +# Whether to use accurate multiplication in hardware shaders +# 0: Off (Default. Faster, but causes issues in some games) 1: On (Slower, but correct) +shaders_accurate_mul = + +# Whether to fallback to software for geometry shaders +# 0: Off (Faster, but causes issues in some games) 1: On (Default. Slower, but correct) +shaders_accurate_gs = + +# Whether to use the Just-In-Time (JIT) compiler for shader emulation +# 0: Interpreter (slow), 1 (default): JIT (fast) +use_shader_jit = + +# Resolution scale factor +# 0: Auto (scales resolution to window size), 1: Native 3DS screen resolution, Otherwise a scale +# factor for the 3DS resolution +resolution_factor = + +# Whether to enable V-Sync (caps the framerate at 60FPS) or not. +# 0 (default): Off, 1: On +use_vsync = + +# Turns on the frame limiter, which will limit frames output to the target game speed +# 0: Off, 1: On (default) +use_frame_limit = + +# Limits the speed of the game to run no faster than this value as a percentage of target speed +# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) +frame_limit = + +# The clear color for the renderer. What shows up on the sides of the bottom screen. +# Must be in range of 0.0-1.0. Defaults to 0.0 for all. +bg_red = +bg_blue = +bg_green = + +# Toggles Stereoscopic 3D +# 0 (default): Off, 1: On +toggle_3d = + +# Change 3D Intensity +# 0 - 100: Intensity. 0 (default) +factor_3d = + +[Layout] +# Layout for the screen inside the render window. +# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side +layout_option = + +# Toggle custom layout (using the settings below) on or off. +# 0 (default): Off, 1: On +custom_layout = + +# Screen placement when using Custom layout option +# 0x, 0y is the top left corner of the render window. +custom_top_left = +custom_top_top = +custom_top_right = +custom_top_bottom = +custom_bottom_left = +custom_bottom_top = +custom_bottom_right = +custom_bottom_bottom = + +# Swaps the prominent screen with the other screen. +# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen. +# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent +swap_screen = + +[Audio] +# Which audio output engine to use. +# auto (default): Auto-select, null: No audio output, sdl2: SDL2 (if available) +output_engine = + +# Whether or not to enable the audio-stretching post-processing effect. +# This effect adjusts audio speed to match emulation speed and helps prevent audio stutter, +# at the cost of increasing audio latency. +# 0: No, 1 (default): Yes +enable_audio_stretching = + +# Which audio device to use. +# auto (default): Auto-select +output_device = + +# Output volume. +# 1.0 (default): 100%, 0.0; mute +volume = + +[Data Storage] +# Whether to create a virtual SD card. +# 1 (default): Yes, 0: No +use_virtual_sd = + +[System] +# The system model that Citra will try to emulate +# 0: Old 3DS (default), 1: New 3DS +is_new_3ds = + +# The system region that Citra will use during emulation +# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan +region_value = + +# The clock to use when citra starts +# 0: System clock (default), 1: fixed time +init_clock = + +# Time used when init_clock is set to fixed_time in the format %Y-%m-%d %H:%M:%S +# set to fixed time. Default 2000-01-01 00:00:01 +# Note: 3DS can only handle times later then Jan 1 2000 +init_time = + +[Camera] +# Which camera engine to use for the right outer camera +# blank (default): a dummy camera that always returns black image +camera_outer_right_name = + +# A config string for the right outer camera. Its meaning is defined by the camera engine +camera_outer_right_config = + +# The image flip to apply +# 0: None (default), 1: Horizontal, 2: Vertical, 3: Reverse +camera_outer_right_flip = + +# ... for the left outer camera +camera_outer_left_name = +camera_outer_left_config = +camera_outer_left_flip = + +# ... for the inner camera +camera_inner_name = +camera_inner_config = +camera_inner_flip = + +[Miscellaneous] +# A filter which removes logs below a certain logging level. +# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical +log_filter = *:Info + +[Debugging] +# Port for listening to GDB connections. +use_gdbstub=false +gdbstub_port=24689 +# To LLE a service module add "LLE\=true" + +[WebService] +# Whether or not to enable telemetry +# 0: No, 1 (default): Yes +enable_telemetry = +# Endpoint URL for submitting telemetry data +telemetry_endpoint_url = https://services.citra-emu.org/api/telemetry +# Endpoint URL to verify the username and token +verify_endpoint_url = https://services.citra-emu.org/api/profile +# Endpoint URL for announcing public rooms +announce_multiplayer_room_endpoint_url = https://services.citra-emu.org/api/multiplayer/rooms +# Username and token for Citra Web Service +# See https://services.citra-emu.org/ for more info +citra_username = +citra_token = +)"; +} diff --git a/src/citra_android/jni/emu_window/emu_window.cpp b/src/citra_android/jni/emu_window/emu_window.cpp new file mode 100644 index 000000000..6965f43fe --- /dev/null +++ b/src/citra_android/jni/emu_window/emu_window.cpp @@ -0,0 +1,87 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include "citra_android/jni/button_manager.h" +#include "citra_android/jni/emu_window/emu_window.h" +#include "citra_android/jni/ndk_helper/GLContext.h" +#include "common/logging/log.h" +#include "common/scm_rev.h" +#include "common/string_util.h" +#include "core/3ds.h" +#include "core/settings.h" +#include "input_common/keyboard.h" +#include "input_common/main.h" +#include "input_common/motion_emu.h" +#include "network/network.h" + +void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { + render_window = surface; +} + +void EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) { + if (pressed) { + TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); + } else { + TouchReleased(); + } +} + +void EmuWindow_Android::OnTouchMoved(int x, int y) { + TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); +} + +void EmuWindow_Android::OnFramebufferSizeChanged() { + int width, height; + width = gl_context->GetScreenWidth(); + height = gl_context->GetScreenHeight(); + UpdateCurrentFramebufferLayout(width, height); +} + +EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface) { + LOG_DEBUG(Frontend, "Initializing Emuwindow"); + + Network::Init(); + gl_context = ndk_helper::GLContext::GetInstance(); + render_window = surface; + + LOG_INFO(Frontend, "InitDisplay"); + gl_context->Init(render_window); + + if (!gladLoadGLES2Loader(reinterpret_cast(eglGetProcAddress))) { + LOG_CRITICAL(Frontend, "Failed to initialize GL functions: %d", eglGetError()); + } + + OnFramebufferSizeChanged(); + DoneCurrent(); +} + +EmuWindow_Android::~EmuWindow_Android() { + gl_context->Invalidate(); + Network::Shutdown(); +} + +void EmuWindow_Android::SwapBuffers() { + + if (EGL_SUCCESS != gl_context->Swap()) + LOG_ERROR(Frontend, "Swap failed"); +} + +void EmuWindow_Android::PollEvents() { + if (render_window != gl_context->GetANativeWindow()) { + MakeCurrent(); + OnFramebufferSizeChanged(); + } +} + +void EmuWindow_Android::MakeCurrent() { + gl_context->Resume(render_window); +} + +void EmuWindow_Android::DoneCurrent() { + gl_context->Suspend(); +} diff --git a/src/citra_android/jni/emu_window/emu_window.h b/src/citra_android/jni/emu_window/emu_window.h new file mode 100644 index 000000000..4e7a8686d --- /dev/null +++ b/src/citra_android/jni/emu_window/emu_window.h @@ -0,0 +1,59 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "citra_android/jni/ndk_helper/GLContext.h" +#include "core/frontend/emu_window.h" + +class EmuWindow_Android : public Frontend::EmuWindow { +public: + EmuWindow_Android(ANativeWindow* surface); + ~EmuWindow_Android(); + + /// Swap buffers to display the next frame + void SwapBuffers() override; + + /// Polls window events + void PollEvents() override; + + /// Makes the graphics context current for the caller thread + void MakeCurrent() override; + + /// Releases the GL context from the caller thread + void DoneCurrent() override; + + /// Called by the onSurfaceChanges() method to change the surface + void OnSurfaceChanged(ANativeWindow* surface); + + /// Handles touch event that occur.(Touched or released) + void OnTouchEvent(int x, int y, bool pressed); + + /// Handles movement of touch pointer + void OnTouchMoved(int x, int y); + +private: + /// Called by PollEvents when a key is pressed or released. + void OnKeyEvent(int key, u8 state); + + /// Called by PollEvents when the mouse moves. + void OnMouseMotion(s32 x, s32 y); + + /// Called by PollEvents when a mouse button is pressed or released + void OnMouseButton(u32 button, u8 state, s32 x, s32 y); + + /// Called when any event that may change the surface(Rotation) + void OnFramebufferSizeChanged(); + + /// Internal render window + ANativeWindow* render_window; + + /// Initialise the EGL context associated with the window + bool InitDisplay(); + + /// A helper class for handling the EGL context + ndk_helper::GLContext* gl_context; +}; diff --git a/src/citra_android/jni/game_info.cpp b/src/citra_android/jni/game_info.cpp new file mode 100644 index 000000000..48d47cf6d --- /dev/null +++ b/src/citra_android/jni/game_info.cpp @@ -0,0 +1,113 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include + +#include "citra_android/jni/game_info.h" +#include "common/string_util.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/fs/archive.h" +#include "core/loader/loader.h" +#include "core/loader/smdh.h" + +namespace GameInfo { +std::vector GetSMDHData(std::string physical_name) { + std::unique_ptr loader = Loader::GetLoader(physical_name); + if (!loader) + LOG_ERROR(Frontend, "Failed to obtain loader"); + + u64 program_id = 0; + loader->ReadProgramId(program_id); + + std::vector smdh = [program_id, &loader]() -> std::vector { + std::vector original_smdh; + loader->ReadIcon(original_smdh); + + if (program_id < 0x00040000'00000000 || program_id > 0x00040000'FFFFFFFF) + return original_smdh; + + std::string update_path = Service::AM::GetTitleContentPath( + Service::FS::MediaType::SDMC, program_id + 0x0000000E'00000000); + + if (!FileUtil::Exists(update_path)) + return original_smdh; + + std::unique_ptr update_loader = Loader::GetLoader(update_path); + + if (!update_loader) + return original_smdh; + + std::vector update_smdh; + update_loader->ReadIcon(update_smdh); + return update_smdh; + }(); + + return smdh; +} + +char16_t* GetTitle(std::string physical_name) { + Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English; + std::vector smdh_data = GetSMDHData(physical_name); + + if (!Loader::IsValidSMDH(smdh_data)) { + // SMDH is not valid, Return the file name; + LOG_ERROR(Frontend, "SMDH is Invalid"); + return nullptr; + } + + Loader::SMDH smdh; + memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); + + // Get the title from SMDH in UTF-16 format + char16_t* title; + title = reinterpret_cast(smdh.titles[static_cast(language)].long_title.data()); + + LOG_INFO(Frontend, "Title: %s", Common::UTF16ToUTF8(title).data()); + + return title; +} + +char16_t* GetPublisher(std::string physical_name) { + Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English; + std::vector smdh_data = GetSMDHData(physical_name); + + if (!Loader::IsValidSMDH(smdh_data)) { + // SMDH is not valid, return null + LOG_ERROR(Frontend, "SMDH is Invalid"); + return nullptr; + } + + Loader::SMDH smdh; + memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); + + // Get the Publisher's name from SMDH in UTF-16 format + char16_t* publisher; + publisher = + reinterpret_cast(smdh.titles[static_cast(language)].publisher.data()); + + LOG_INFO(Frontend, "Publisher: %s", Common::UTF16ToUTF8(publisher).data()); + + return publisher; +} + +std::vector GetIcon(std::string physical_name) { + std::vector smdh_data = GetSMDHData(physical_name); + + if (!Loader::IsValidSMDH(smdh_data)) { + // SMDH is not valid, return null + LOG_ERROR(Frontend, "SMDH is Invalid"); + return std::vector(0, 0); + } + + Loader::SMDH smdh; + memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); + + // Always get a 48x48(large) icon + std::vector icon_data = smdh.GetIcon(true); + return icon_data; +} + +} // namespace GameInfo \ No newline at end of file diff --git a/src/citra_android/jni/game_info.h b/src/citra_android/jni/game_info.h new file mode 100644 index 000000000..56880c5fe --- /dev/null +++ b/src/citra_android/jni/game_info.h @@ -0,0 +1,17 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/common_types.h" + +namespace GameInfo { +std::vector GetSMDHData(std::string physical_name); + +char16_t* GetTitle(std::string physical_name); + +char16_t* GetPublisher(std::string physical_name); + +std::vector GetIcon(std::string physical_name); +} // namespace GameInfo \ No newline at end of file diff --git a/src/citra_android/jni/native.cpp b/src/citra_android/jni/native.cpp new file mode 100644 index 000000000..e1c913170 --- /dev/null +++ b/src/citra_android/jni/native.cpp @@ -0,0 +1,475 @@ +#include +#include +#include +#include +#include + +// This needs to be included before getopt.h because the latter #defines symbols used by it +#include "common/microprofile.h" + +#include + +#include +#include + +#include "citra_android/jni/button_manager.h" +#include "citra_android/jni/config.h" +#include "citra_android/jni/emu_window/emu_window.h" +#include "citra_android/jni/game_info.h" +#include "citra_android/jni/native.h" +#include "common/common_paths.h" +#include "common/file_util.h" +#include "common/logging/backend.h" +#include "common/logging/filter.h" +#include "common/logging/log.h" +#include "common/scm_rev.h" +#include "common/scope_exit.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/file_sys/cia_container.h" +#include "core/frontend/applets/default_applets.h" +#include "core/gdbstub/gdbstub.h" +#include "core/hle/service/am/am.h" +#include "core/loader/loader.h" +#include "core/movie.h" +#include "core/settings.h" +#include "network/network.h" +#include "../../common/file_util.h" + +JavaVM* g_java_vm; + +namespace { +ANativeWindow* s_surf; + +jclass s_jni_class; +jmethodID s_jni_method_alert; + +EmuWindow_Android* emu; + +std::atomic is_running{false}; +std::atomic pause_emulation{false}; + +std::mutex running_mutex; +std::condition_variable running_cv; +} // Anonymous namespace + +/** + * Cache the JavaVM so that we can call into it later. + */ +jint JNI_OnLoad(JavaVM* vm, void* reserved) { + g_java_vm = vm; + + // Initialise Logger + Log::Filter log_filter; + log_filter.ParseFilterString(Settings::values.log_filter); + Log::SetGlobalFilter(log_filter); + + Log::AddBackend(std::make_unique()); + FileUtil::CreateFullPath(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); + Log::AddBackend( + std::make_unique(FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + LOG_FILE)); + + LOG_INFO(Frontend, "Logging backend initialised"); + + return JNI_VERSION_1_6; +} + +static int RunCitra(const std::string& filepath) { + LOG_INFO(Frontend, "Citra is Starting"); + + Config config; + + MicroProfileOnThreadCreate("EmuThread"); + SCOPE_EXIT({ MicroProfileShutdown(); }); + + if (filepath.empty()) { + LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); + return -1; + } + + // Register frontend applets + Frontend::RegisterDefaultApplets(); + + Settings::Apply(); + InputManager::Init(); + emu = new EmuWindow_Android(s_surf); + Core::System& system{Core::System::GetInstance()}; + + SCOPE_EXIT({ + system.Shutdown(); + InputManager::Shutdown(); + emu->~EmuWindow_Android(); + }); + + const Core::System::ResultStatus load_result{system.Load(*emu, filepath)}; + + switch (load_result) { + case Core::System::ResultStatus::ErrorGetLoader: + LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath); + return -1; + case Core::System::ResultStatus::ErrorLoader: + LOG_CRITICAL(Frontend, "Failed to load ROM!"); + return -1; + case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: + LOG_CRITICAL(Frontend, "The game that you are trying to load must be decrypted before " + "being used with Citra. \n\n For more information on dumping and " + "decrypting games, please refer to: " + "https://citra-emu.org/wiki/dumping-game-cartridges/"); + return -1; + case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat: + LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported."); + return -1; + case Core::System::ResultStatus::ErrorNotInitialized: + LOG_CRITICAL(Frontend, "CPUCore not initialized"); + return -1; + case Core::System::ResultStatus::ErrorSystemMode: + LOG_CRITICAL(Frontend, "Failed to determine system mode!"); + return -1; + case Core::System::ResultStatus::ErrorVideoCore: + LOG_CRITICAL(Frontend, "VideoCore not initialized"); + return -1; + case Core::System::ResultStatus::Success: + break; // Expected case + } + + auto& telemetry_session = Core::System::GetInstance().TelemetrySession(); + telemetry_session.AddField(Telemetry::FieldType::App, "Frontend", "SDL"); + + is_running = true; + pause_emulation = false; + + while (is_running) { + if (!pause_emulation) { + system.RunLoop(); + } else { + std::unique_lock lock(running_mutex); + running_cv.wait(lock, [] { return !pause_emulation || !is_running; }); + } + } + + return 0; +} + +static std::string GetJString(JNIEnv* env, jstring jstr) { + std::string result = ""; + if (!jstr) + return result; + + const char* s = env->GetStringUTFChars(jstr, nullptr); + result = s; + env->ReleaseStringUTFChars(jstr, s); + return result; +} + +void Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, jobject obj, + jobject surf) { + s_surf = ANativeWindow_fromSurface(env, surf); + + if (is_running) { + emu->OnSurfaceChanged(s_surf); + } + + LOG_INFO(Frontend, "Surface changed"); +} + +void Java_org_citra_citra_1android_NativeLibrary_SurfaceDestroyed(JNIEnv* env, jobject obj) {} + +void Java_org_citra_citra_1android_NativeLibrary_CacheClassesAndMethods(JNIEnv* env, jobject obj) { + // This class reference is only valid for the lifetime of this method. + jclass localClass = env->FindClass("org/citra/citra_android/NativeLibrary"); + + // This reference, however, is valid until we delete it. + s_jni_class = reinterpret_cast(env->NewGlobalRef(localClass)); + + // TODO Find a place for this. + // So we don't leak a reference to NativeLibrary.class. + // env->DeleteGlobalRef(s_jni_class); + + // Method signature taken from javap -s + // Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class + s_jni_method_alert = env->GetStaticMethodID(s_jni_class, "displayAlertMsg", + "(Ljava/lang/String;Ljava/lang/String;Z)Z"); +} + +void Java_org_citra_citra_1android_NativeLibrary_SetUserDirectory(JNIEnv* env, jobject obj, + jstring jDirectory) { + FileUtil::SetCurrentDir(GetJString(env, jDirectory)); +} + +void Java_org_citra_citra_1android_NativeLibrary_UnPauseEmulation(JNIEnv* env, jobject obj) { + pause_emulation = false; + running_cv.notify_all(); +} + +void Java_org_citra_citra_1android_NativeLibrary_PauseEmulation(JNIEnv* env, jobject obj) { + pause_emulation = true; +} + +void Java_org_citra_citra_1android_NativeLibrary_StopEmulation(JNIEnv* env, jobject obj) { + is_running = false; + pause_emulation = false; + running_cv.notify_all(); +} + +jboolean Java_org_citra_citra_1android_NativeLibrary_IsRunning(JNIEnv* env, jobject obj) { + return static_cast(is_running); +} + +jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadEvent(JNIEnv* env, jobject obj, + jstring jDevice, jint button, + jint pressed) { + bool consumed; + if (pressed) { + consumed = InputManager::ButtonHandler()->PressKey(button); + } else { + consumed = InputManager::ButtonHandler()->ReleaseKey(button); + } + + return static_cast(consumed); +} + +jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadMoveEvent(JNIEnv* env, jobject obj, + jstring jDevice, jint Axis, + jfloat x, jfloat y) { + // Citra uses an inverted y axis sent by the frontend + y = -y; + InputManager::AnalogHandler()->MoveJoystick(Axis, x, y); + return static_cast(InputManager::AnalogHandler()->MoveJoystick(Axis, x, y)); +} + +jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadAxisEvent(JNIEnv* env, jobject obj, + jstring jDevice, + jint axis_id, + jfloat axis_val) { + return static_cast( + InputManager::ButtonHandler()->AnalogButtonEvent(axis_id,axis_val)); +} + +void Java_org_citra_citra_1android_NativeLibrary_onTouchEvent(JNIEnv* env, jobject obj, jfloat x, + jfloat y, jboolean pressed) { + LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y); + emu->OnTouchEvent((int)x, (int)y, (bool)pressed); +} + +void Java_org_citra_citra_1android_NativeLibrary_onTouchMoved(JNIEnv* env, jobject obj, jfloat x, + jfloat y) { + LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y); + emu->OnTouchMoved((int)x, (int)y); +} + +jintArray Java_org_citra_citra_1android_NativeLibrary_GetBanner(JNIEnv* env, jobject obj, + jstring jFilepath) { + std::string filepath = GetJString(env, jFilepath); + + std::vector icon_data = GameInfo::GetIcon(filepath); + if (icon_data.size() == 0) { + return 0; + } + + jintArray Banner = env->NewIntArray(icon_data.size()); + env->SetIntArrayRegion(Banner, 0, icon_data.size(), reinterpret_cast(icon_data.data())); + + return Banner; +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetTitle(JNIEnv* env, jobject obj, + jstring jFilepath) { + std::string filepath = GetJString(env, jFilepath); + + char16_t* Title = GameInfo::GetTitle(filepath); + + if (!Title) { + return env->NewStringUTF(""); + } + + return env->NewStringUTF(Common::UTF16ToUTF8(Title).data()); +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetDescription(JNIEnv* env, jobject obj, + jstring jFilename) { + return jFilename; +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetGameId(JNIEnv* env, jobject obj, + jstring jFilename) { + return jFilename; +} + +jint Java_org_citra_citra_1android_NativeLibrary_GetCountry(JNIEnv* env, jobject obj, + jstring jFilename) { + return 0; +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetCompany(JNIEnv* env, jobject obj, + jstring jFilepath) { + std::string filepath = GetJString(env, jFilepath); + + char16_t* Publisher = GameInfo::GetPublisher(filepath); + + if (!Publisher) { + return nullptr; + } + + return env->NewStringUTF(Common::UTF16ToUTF8(Publisher).data()); +} + +jlong Java_org_citra_citra_1android_NativeLibrary_GetFilesize(JNIEnv* env, jobject obj, + jstring jFilename) { + return 0; +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetVersionString(JNIEnv* env, jobject obj) { + return nullptr; +} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetGitRevision(JNIEnv* env, jobject obj) { + return nullptr; +} + +void Java_org_citra_citra_1android_NativeLibrary_SaveScreenShot(JNIEnv* env, jobject obj) {} + +void Java_org_citra_citra_1android_NativeLibrary_eglBindAPI(JNIEnv* env, jobject obj, jint api) {} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetConfig(JNIEnv* env, jobject obj, + jstring jFile, jstring jSection, + jstring jKey, jstring jDefault) { + return nullptr; +} + +void Java_org_citra_citra_1android_NativeLibrary_SetConfig(JNIEnv* env, jobject obj, jstring jFile, + jstring jSection, jstring jKey, + jstring jValue) {} + +void Java_org_citra_citra_1android_NativeLibrary_SetFilename(JNIEnv* env, jobject obj, + jstring jFile) {} + +void Java_org_citra_citra_1android_NativeLibrary_SaveState(JNIEnv* env, jobject obj, jint slot, + jboolean wait) {} + +void Java_org_citra_citra_1android_NativeLibrary_SaveStateAs(JNIEnv* env, jobject obj, jstring path, + jboolean wait) {} + +void Java_org_citra_citra_1android_NativeLibrary_LoadState(JNIEnv* env, jobject obj, jint slot) {} + +void Java_org_citra_citra_1android_NativeLibrary_LoadStateAs(JNIEnv* env, jobject obj, + jstring path) {} + +void Java_org_citra_citra_1android_services_DirectoryInitializationService_CreateUserDirectories( + JNIEnv* env, jobject obj) {} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetUserDirectory(JNIEnv* env, jobject obj) { + + return nullptr; +} + +void Java_org_citra_citra_1android_NativeLibrary_CreateConfigFile() { + new Config(); +} + +jint Java_org_citra_citra_1android_NativeLibrary_DefaultCPUCore(JNIEnv* env, jobject obj) { + return 0; +} + +void Java_org_citra_citra_1android_NativeLibrary_SetProfiling(JNIEnv* env, jobject obj, + jboolean enable) {} + +void Java_org_citra_citra_1android_NativeLibrary_WriteProfileResults(JNIEnv* env, jobject obj) {} + +void Java_org_citra_citra_1android_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( + JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate) {} + +jstring Java_org_citra_citra_1android_NativeLibrary_GetUserSetting(JNIEnv* env, jclass type, + jstring gameID_, + jstring Section_, jstring Key_) { + const char* gameID = env->GetStringUTFChars(gameID_, 0); + const char* Section = env->GetStringUTFChars(Section_, 0); + const char* Key = env->GetStringUTFChars(Key_, 0); + + // TODO + + env->ReleaseStringUTFChars(gameID_, gameID); + env->ReleaseStringUTFChars(Section_, Section); + env->ReleaseStringUTFChars(Key_, Key); + + return env->NewStringUTF(""); +} + +void Java_org_citra_citra_1android_NativeLibrary_SetUserSetting(JNIEnv* env, jclass type, + jstring gameID_, jstring Section_, + jstring Key_, jstring Value_) { + const char* gameID = env->GetStringUTFChars(gameID_, 0); + const char* Section = env->GetStringUTFChars(Section_, 0); + const char* Key = env->GetStringUTFChars(Key_, 0); + const char* Value = env->GetStringUTFChars(Value_, 0); + + // TODO + + env->ReleaseStringUTFChars(gameID_, gameID); + env->ReleaseStringUTFChars(Section_, Section); + env->ReleaseStringUTFChars(Key_, Key); + env->ReleaseStringUTFChars(Value_, Value); +} + +void Java_org_citra_citra_1android_NativeLibrary_InitGameIni(JNIEnv* env, jclass type, + jstring gameID_) { + const char* gameID = env->GetStringUTFChars(gameID_, 0); + + // TODO + + env->ReleaseStringUTFChars(gameID_, gameID); +} + +void Java_org_citra_citra_1android_NativeLibrary_ChangeDisc(JNIEnv* env, jclass type, + jstring path_) { + const char* path = env->GetStringUTFChars(path_, 0); + + // TODO + + env->ReleaseStringUTFChars(path_, path); +} + +void Java_org_citra_citra_1android_NativeLibrary_RefreshWiimotes(JNIEnv* env, jclass type) { + + // TODO +} + +jint Java_org_citra_citra_1android_NativeLibrary_GetPlatform(JNIEnv* env, jclass type, + jstring filename_) { + return 0; +} + +jdoubleArray Java_org_citra_citra_1android_NativeLibrary_GetPerfStats(JNIEnv* env, jclass type) { + auto& core = Core::System::GetInstance(); + jdoubleArray jstats = env->NewDoubleArray(4); + + if (core.IsPoweredOn()) { + auto results = core.GetAndResetPerfStats(); + + // Converting the structure into an array makes it easier to pass it to the frontend + double stats[4] = {results.system_fps, results.game_fps, results.frametime, + results.emulation_speed}; + + + env->SetDoubleArrayRegion(jstats, 0, 4, stats); + } + + return jstats; +} + +void Java_org_citra_citra_1android_services_DirectoryInitializationService_SetSysDirectory( + JNIEnv* env, jclass type, jstring path_) { + const char* path = env->GetStringUTFChars(path_, 0); + + env->ReleaseStringUTFChars(path_, path); +} + +void Java_org_citra_citra_1android_NativeLibrary_Run__Ljava_lang_String_2(JNIEnv* env, jclass type, + jstring path_) { + const std::string path = GetJString(env, path_); + + if (is_running) { + is_running = false; + running_cv.notify_all(); + } + RunCitra(path); +} \ No newline at end of file diff --git a/src/citra_android/jni/native.h b/src/citra_android/jni/native.h new file mode 100644 index 000000000..96a630ec5 --- /dev/null +++ b/src/citra_android/jni/native.h @@ -0,0 +1,186 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// Initialise and run the emulator +static int RunCitra(const std::string& path); + +// Function calls from the Java side +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_UnPauseEmulation(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_PauseEmulation(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_StopEmulation(JNIEnv* env, + jobject obj); + +JNIEXPORT jboolean JNICALL Java_org_citra_citra_1android_NativeLibrary_IsRunning(JNIEnv* env, + jobject obj); + +JNIEXPORT jboolean JNICALL Java_org_citra_citra_1android_NativeLibrary_onGamePadEvent( + JNIEnv* env, jobject obj, jstring jDevice, jint Button, jint Action); + +JNIEXPORT jboolean JNICALL Java_org_citra_citra_1android_NativeLibrary_onGamePadMoveEvent( + JNIEnv* env, jobject obj, jstring jDevice, jint Axis, jfloat x, jfloat y); + +JNIEXPORT jboolean JNICALL Java_org_citra_citra_1android_NativeLibrary_onGamePadAxisEvent( + JNIEnv* env, jobject obj, jstring jDevice, jint axis_id, jfloat axis_val); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_onTouchEvent(JNIEnv* env, + jobject obj, + jfloat x, jfloat y, + jboolean pressed); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_onTouchMoved(JNIEnv* env, + jobject obj, + jfloat x, jfloat y); + +JNIEXPORT jintArray JNICALL Java_org_citra_citra_1android_NativeLibrary_GetBanner(JNIEnv* env, + jobject obj, + jstring jFile); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetTitle(JNIEnv* env, + jobject obj, + jstring jFilename); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetDescription( + JNIEnv* env, jobject obj, jstring jFilename); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetGameId(JNIEnv* env, + jobject obj, + jstring jFilename); + +JNIEXPORT jint JNICALL Java_org_citra_citra_1android_NativeLibrary_GetCountry(JNIEnv* env, + jobject obj, + jstring jFilename); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetCompany(JNIEnv* env, + jobject obj, + jstring jFilename); + +JNIEXPORT jlong JNICALL Java_org_citra_citra_1android_NativeLibrary_GetFilesize(JNIEnv* env, + jobject obj, + jstring jFilename); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetVersionString(JNIEnv* env, + jobject obj); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetGitRevision(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SaveScreenShot(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_eglBindAPI(JNIEnv* env, + jobject obj, + jint api); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetConfig( + JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetConfig( + JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jValue); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetFilename(JNIEnv* env, + jobject obj, + jstring jFile); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SaveState(JNIEnv* env, + jobject obj, jint slot, + jboolean wait); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SaveStateAs(JNIEnv* env, + jobject obj, + jstring path, + jboolean wait); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_LoadState(JNIEnv* env, + jobject obj, + jint slot); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_LoadStateAs(JNIEnv* env, + jobject obj, + jstring path); + +JNIEXPORT void JNICALL +Java_org_citra_citra_1android_services_DirectoryInitializationService_CreateUserDirectories( + JNIEnv* env, jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetUserDirectory( + JNIEnv* env, jobject obj, jstring jDirectory); + +JNIEXPORT void JNICALL +Java_org_citra_citra_1android_services_DirectoryInitializationService_SetSysDirectory( + JNIEnv* env, jclass type, jstring path_); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetUserDirectory(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetSysDirectory(JNIEnv* env, + jobject obj, + jstring path); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_CreateConfigFile(); + +JNIEXPORT jint JNICALL Java_org_citra_citra_1android_NativeLibrary_DefaultCPUCore(JNIEnv* env, + jobject obj); +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetProfiling(JNIEnv* env, + jobject obj, + jboolean enable); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_WriteProfileResults(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL +Java_org_citra_citra_1android_NativeLibrary_CacheClassesAndMethods(JNIEnv* env, jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_Run__Ljava_lang_String_2( + JNIEnv* env, jclass type, jstring path_); + +JNIEXPORT void JNICALL +Java_org_citra_citra_1android_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( + JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, + jobject obj, + jobject surf); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SurfaceDestroyed(JNIEnv* env, + jobject obj); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_InitGameIni(JNIEnv* env, + jclass type, + jstring gameID_); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_SetUserSetting( + JNIEnv* env, jclass type, jstring gameID_, jstring Section_, jstring Key_, jstring Value_); + +JNIEXPORT jstring JNICALL Java_org_citra_citra_1android_NativeLibrary_GetUserSetting( + JNIEnv* env, jclass type, jstring gameID_, jstring Section_, jstring Key_); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_ChangeDisc(JNIEnv* env, + jclass type, + jstring path_); + +JNIEXPORT void JNICALL Java_org_citra_citra_1android_NativeLibrary_RefreshWiimotes(JNIEnv* env, + jclass type); + +JNIEXPORT jint JNICALL Java_org_citra_citra_1android_NativeLibrary_GetPlatform(JNIEnv* env, + jclass type, + jstring filename_); + +JNIEXPORT jint JNICALL Java_org_citra_citra_1android_NativeLibrary_GetPlatform(JNIEnv* env, + jclass type, + jstring filename_); + +JNIEXPORT jdoubleArray JNICALL +Java_org_citra_citra_1android_NativeLibrary_GetPerfStats(JNIEnv* env, jclass type); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/citra_android/jni/ndk_helper/CMakeLists.txt b/src/citra_android/jni/ndk_helper/CMakeLists.txt new file mode 100644 index 000000000..a9bed74af --- /dev/null +++ b/src/citra_android/jni/ndk_helper/CMakeLists.txt @@ -0,0 +1,28 @@ +# build native_app_glue as a static lib +cmake_minimum_required(VERSION 3.4.1) + +add_library(ndk_helper + STATIC + gl3stub.cpp + GLContext.cpp + +) +set_target_properties(ndk_helper + PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO + INTERFACE_INCLUDE_DIRECTORIES $ +) +target_include_directories(ndk_helper + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(ndk_helper + PUBLIC + common + GLESv2 + EGL + atomic +) diff --git a/src/citra_android/jni/ndk_helper/GLContext.cpp b/src/citra_android/jni/ndk_helper/GLContext.cpp new file mode 100644 index 000000000..1695de811 --- /dev/null +++ b/src/citra_android/jni/ndk_helper/GLContext.cpp @@ -0,0 +1,271 @@ +/* + * Copyright 2013 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. + */ + +//-------------------------------------------------------------------------------- +// GLContext.cpp +//-------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------- +// includes +//-------------------------------------------------------------------------------- +#include +#include +#include + +#include "gl3stub.h" +#include "common/logging/log.h" +#include "GLContext.h" + +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// eGLContext +//-------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// Ctor +//-------------------------------------------------------------------------------- +GLContext::GLContext() + : window_(nullptr), + display_(EGL_NO_DISPLAY), + surface_(EGL_NO_SURFACE), + context_(EGL_NO_CONTEXT), + screen_width_(0), + screen_height_(0), + gles_initialized_(false), + egl_context_initialized_(false), + es3_supported_(false) {} + +void GLContext::InitGLES() { + if (gles_initialized_) return; + // + // Initialize OpenGL ES 3 if available + // + const char* versionStr = (const char*)glGetString(GL_VERSION); + if (strstr(versionStr, "OpenGL ES 3.") && gl3stubInit()) { + es3_supported_ = true; + gl_version_ = 3.0f; + } else { + gl_version_ = 2.0f; + } + + gles_initialized_ = true; +} + +//-------------------------------------------------------------------------------- +// Dtor +//-------------------------------------------------------------------------------- +GLContext::~GLContext() { Terminate(); } + +bool GLContext::Init(ANativeWindow* window) { + if (egl_context_initialized_) return true; + + // + // Initialize EGL + // + LOG_INFO(Frontend, "GLContext Init()"); + window_ = window; + InitEGLSurface(); + InitEGLContext(); + InitGLES(); + + egl_context_initialized_ = true; + + return true; +} + +bool GLContext::InitEGLSurface() { + display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(display_, 0, 0); + + /* + * Here specify the attributes of the desired configuration. + * Below, we select an EGLConfig with at least 8 bits per color + * component compatible with on-screen windows + */ + const EGLint attribs[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, // Request opengl ES2.0 + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_BLUE_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_RED_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_NONE}; + color_size_ = 8; + depth_size_ = 24; + + EGLint num_configs; + eglChooseConfig(display_, attribs, &config_, 1, &num_configs); + + if (!num_configs) { + // Fall back to 16bit depth buffer + const EGLint attribs[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, // Request opengl ES2.0 + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_BLUE_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_RED_SIZE, + 8, + EGL_DEPTH_SIZE, + 16, + EGL_NONE}; + eglChooseConfig(display_, attribs, &config_, 1, &num_configs); + depth_size_ = 16; + } + + if (!num_configs) { + LOG_ERROR(Frontend, "Unable to retrieve EGL config"); + return false; + } + + surface_ = eglCreateWindowSurface(display_, config_, window_, NULL); + eglQuerySurface(display_, surface_, EGL_WIDTH, &screen_width_); + eglQuerySurface(display_, surface_, EGL_HEIGHT, &screen_height_); + + return true; +} + +bool GLContext::InitEGLContext() { + const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, + 2, // Request opengl ES2.0 + EGL_NONE}; + context_ = eglCreateContext(display_, config_, NULL, context_attribs); + + if (eglMakeCurrent(display_, surface_, surface_, context_) == EGL_FALSE) { + LOG_WARNING(Frontend, "Unable to eglMakeCurrent"); + return false; + } + + context_valid_ = true; + return true; +} + +EGLint GLContext::Swap() { + bool b = static_cast(eglSwapBuffers(display_, surface_)); + if (!b) { + EGLint err = eglGetError(); + if (err == EGL_BAD_SURFACE) { + // Recreate surface + InitEGLSurface(); + return EGL_SUCCESS; // Still consider glContext is valid + } else if (err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT) { + // Context has been lost!! + context_valid_ = false; + Terminate(); + InitEGLContext(); + } + return err; + } + return EGL_SUCCESS; +} + +void GLContext::Terminate() { + if (display_ != EGL_NO_DISPLAY) { + eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (context_ != EGL_NO_CONTEXT) { + eglDestroyContext(display_, context_); + } + + if (surface_ != EGL_NO_SURFACE) { + eglDestroySurface(display_, surface_); + } + eglTerminate(display_); + } + + display_ = EGL_NO_DISPLAY; + context_ = EGL_NO_CONTEXT; + surface_ = EGL_NO_SURFACE; + window_ = nullptr; + context_valid_ = false; +} + +EGLint GLContext::Resume(ANativeWindow* window) { + if (egl_context_initialized_ == false) { + Init(window); + return EGL_SUCCESS; + } + + int32_t original_widhth = screen_width_; + int32_t original_height = screen_height_; + + // Create surface + window_ = window; + surface_ = eglCreateWindowSurface(display_, config_, window_, NULL); + eglQuerySurface(display_, surface_, EGL_WIDTH, &screen_width_); + eglQuerySurface(display_, surface_, EGL_HEIGHT, &screen_height_); + + if (screen_width_ != original_widhth || screen_height_ != original_height) { + // Screen resized + LOG_INFO(Frontend,"Screen resized"); + } + + if (eglMakeCurrent(display_, surface_, surface_, context_) == EGL_TRUE) + return EGL_SUCCESS; + + EGLint err = eglGetError(); + LOG_ERROR(Frontend,"Unable to eglMakeCurrent {}", err); + + if (err == EGL_CONTEXT_LOST) { + // Recreate context + LOG_INFO(Frontend,"Re-creating egl context"); + InitEGLContext(); + } else { + // Recreate surface + Terminate(); + InitEGLSurface(); + InitEGLContext(); + } + + return err; +} + +void GLContext::Suspend() { + if (surface_ != EGL_NO_SURFACE) { + eglDestroySurface(display_, surface_); + surface_ = EGL_NO_SURFACE; + } +} + +bool GLContext::Invalidate() { + Terminate(); + + egl_context_initialized_ = false; + return true; +} + +bool GLContext::CheckExtension(const char* extension) { + if (extension == NULL) return false; + + std::string extensions = std::string((char*)glGetString(GL_EXTENSIONS)); + std::string str = std::string(extension); + str.append(" "); + + size_t pos = 0; + if (extensions.find(extension, pos) != std::string::npos) { + return true; + } + + return false; +} + +} // namespace ndkHelper diff --git a/src/citra_android/jni/ndk_helper/GLContext.h b/src/citra_android/jni/ndk_helper/GLContext.h new file mode 100644 index 000000000..f679a3464 --- /dev/null +++ b/src/citra_android/jni/ndk_helper/GLContext.h @@ -0,0 +1,114 @@ +/* + * Copyright 2013 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. + */ + +//-------------------------------------------------------------------------------- +// GLContext.h +//-------------------------------------------------------------------------------- +#ifndef GLCONTEXT_H_ +#define GLCONTEXT_H_ + +#include +#include +#include + + +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// Constants +//-------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// Class +//-------------------------------------------------------------------------------- + +/****************************************************************** + * OpenGL context handler + * The class handles OpenGL and EGL context based on Android activity life cycle + * The caller needs to call corresponding methods for each activity life cycle + *events as it's done in sample codes. + * + * Also the class initializes OpenGL ES3 when the compatible driver is installed + *in the device. + * getGLVersion() returns 3.0~ when the device supports OpenGLES3.0 + * + * Thread safety: OpenGL context is expecting used within dedicated single + *thread, + * thus GLContext class is not designed as a thread-safe + */ +class GLContext { + private: + // EGL configurations + ANativeWindow* window_; + EGLDisplay display_; + EGLSurface surface_; + EGLContext context_; + EGLConfig config_; + + // Screen parameters + int32_t screen_width_; + int32_t screen_height_; + int32_t color_size_; + int32_t depth_size_; + + // Flags + bool gles_initialized_; + bool egl_context_initialized_; + bool es3_supported_; + float gl_version_; + bool context_valid_; + + void InitGLES(); + void Terminate(); + bool InitEGLSurface(); + bool InitEGLContext(); + + GLContext(GLContext const&); + void operator=(GLContext const&); + GLContext(); + virtual ~GLContext(); + + public: + static GLContext* GetInstance() { + // Singleton + static GLContext instance; + + return &instance; + } + + bool Init(ANativeWindow* window); + EGLint Swap(); + bool Invalidate(); + + void Suspend(); + EGLint Resume(ANativeWindow* window); + + ANativeWindow* GetANativeWindow(void) const { return window_; }; + int32_t GetScreenWidth() const { return screen_width_; } + int32_t GetScreenHeight() const { return screen_height_; } + + int32_t GetBufferColorSize() const { return color_size_; } + int32_t GetBufferDepthSize() const { return depth_size_; } + float GetGLVersion() const { return gl_version_; } + bool CheckExtension(const char* extension); + + EGLDisplay GetDisplay() const { return display_; } + EGLSurface GetSurface() const { return surface_; } +}; + +} // namespace ndkHelper + +#endif /* GLCONTEXT_H_ */ diff --git a/src/citra_android/jni/ndk_helper/gl3stub.c b/src/citra_android/jni/ndk_helper/gl3stub.c new file mode 100644 index 000000000..d918b2c0d --- /dev/null +++ b/src/citra_android/jni/ndk_helper/gl3stub.c @@ -0,0 +1,421 @@ +/* + * Copyright 2013 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 +#include "gl3stub.h" + +GLboolean gl3stubInit() { +#define FIND_PROC(s) s = (void*)eglGetProcAddress(#s); + FIND_PROC(glReadBuffer); + FIND_PROC(glDrawRangeElements); + FIND_PROC(glTexImage3D); + FIND_PROC(glTexSubImage3D); + FIND_PROC(glCopyTexSubImage3D); + FIND_PROC(glCompressedTexImage3D); + FIND_PROC(glCompressedTexSubImage3D); + FIND_PROC(glGenQueries); + FIND_PROC(glDeleteQueries); + FIND_PROC(glIsQuery); + FIND_PROC(glBeginQuery); + FIND_PROC(glEndQuery); + FIND_PROC(glGetQueryiv); + FIND_PROC(glGetQueryObjectuiv); + FIND_PROC(glUnmapBuffer); + FIND_PROC(glGetBufferPointerv); + FIND_PROC(glDrawBuffers); + FIND_PROC(glUniformMatrix2x3fv); + FIND_PROC(glUniformMatrix3x2fv); + FIND_PROC(glUniformMatrix2x4fv); + FIND_PROC(glUniformMatrix4x2fv); + FIND_PROC(glUniformMatrix3x4fv); + FIND_PROC(glUniformMatrix4x3fv); + FIND_PROC(glBlitFramebuffer); + FIND_PROC(glRenderbufferStorageMultisample); + FIND_PROC(glFramebufferTextureLayer); + FIND_PROC(glMapBufferRange); + FIND_PROC(glFlushMappedBufferRange); + FIND_PROC(glBindVertexArray); + FIND_PROC(glDeleteVertexArrays); + FIND_PROC(glGenVertexArrays); + FIND_PROC(glIsVertexArray); + FIND_PROC(glGetIntegeri_v); + FIND_PROC(glBeginTransformFeedback); + FIND_PROC(glEndTransformFeedback); + FIND_PROC(glBindBufferRange); + FIND_PROC(glBindBufferBase); + FIND_PROC(glTransformFeedbackVaryings); + FIND_PROC(glGetTransformFeedbackVarying); + FIND_PROC(glVertexAttribIPointer); + FIND_PROC(glGetVertexAttribIiv); + FIND_PROC(glGetVertexAttribIuiv); + FIND_PROC(glVertexAttribI4i); + FIND_PROC(glVertexAttribI4ui); + FIND_PROC(glVertexAttribI4iv); + FIND_PROC(glVertexAttribI4uiv); + FIND_PROC(glGetUniformuiv); + FIND_PROC(glGetFragDataLocation); + FIND_PROC(glUniform1ui); + FIND_PROC(glUniform2ui); + FIND_PROC(glUniform3ui); + FIND_PROC(glUniform4ui); + FIND_PROC(glUniform1uiv); + FIND_PROC(glUniform2uiv); + FIND_PROC(glUniform3uiv); + FIND_PROC(glUniform4uiv); + FIND_PROC(glClearBufferiv); + FIND_PROC(glClearBufferuiv); + FIND_PROC(glClearBufferfv); + FIND_PROC(glClearBufferfi); + FIND_PROC(glGetStringi); + FIND_PROC(glCopyBufferSubData); + FIND_PROC(glGetUniformIndices); + FIND_PROC(glGetActiveUniformsiv); + FIND_PROC(glGetUniformBlockIndex); + FIND_PROC(glGetActiveUniformBlockiv); + FIND_PROC(glGetActiveUniformBlockName); + FIND_PROC(glUniformBlockBinding); + FIND_PROC(glDrawArraysInstanced); + FIND_PROC(glDrawElementsInstanced); + FIND_PROC(glFenceSync); + FIND_PROC(glIsSync); + FIND_PROC(glDeleteSync); + FIND_PROC(glClientWaitSync); + FIND_PROC(glWaitSync); + FIND_PROC(glGetInteger64v); + FIND_PROC(glGetSynciv); + FIND_PROC(glGetInteger64i_v); + FIND_PROC(glGetBufferParameteri64v); + FIND_PROC(glGenSamplers); + FIND_PROC(glDeleteSamplers); + FIND_PROC(glIsSampler); + FIND_PROC(glBindSampler); + FIND_PROC(glSamplerParameteri); + FIND_PROC(glSamplerParameteriv); + FIND_PROC(glSamplerParameterf); + FIND_PROC(glSamplerParameterfv); + FIND_PROC(glGetSamplerParameteriv); + FIND_PROC(glGetSamplerParameterfv); + FIND_PROC(glVertexAttribDivisor); + FIND_PROC(glBindTransformFeedback); + FIND_PROC(glDeleteTransformFeedbacks); + FIND_PROC(glGenTransformFeedbacks); + FIND_PROC(glIsTransformFeedback); + FIND_PROC(glPauseTransformFeedback); + FIND_PROC(glResumeTransformFeedback); + FIND_PROC(glGetProgramBinary); + FIND_PROC(glProgramBinary); + FIND_PROC(glProgramParameteri); + FIND_PROC(glInvalidateFramebuffer); + FIND_PROC(glInvalidateSubFramebuffer); + FIND_PROC(glTexStorage2D); + FIND_PROC(glTexStorage3D); + FIND_PROC(glGetInternalformativ); +#undef FIND_PROC + + if (!glReadBuffer || !glDrawRangeElements || !glTexImage3D || + !glTexSubImage3D || !glCopyTexSubImage3D || !glCompressedTexImage3D || + !glCompressedTexSubImage3D || !glGenQueries || !glDeleteQueries || + !glIsQuery || !glBeginQuery || !glEndQuery || !glGetQueryiv || + !glGetQueryObjectuiv || !glUnmapBuffer || !glGetBufferPointerv || + !glDrawBuffers || !glUniformMatrix2x3fv || !glUniformMatrix3x2fv || + !glUniformMatrix2x4fv || !glUniformMatrix4x2fv || !glUniformMatrix3x4fv || + !glUniformMatrix4x3fv || !glBlitFramebuffer || + !glRenderbufferStorageMultisample || !glFramebufferTextureLayer || + !glMapBufferRange || !glFlushMappedBufferRange || !glBindVertexArray || + !glDeleteVertexArrays || !glGenVertexArrays || !glIsVertexArray || + !glGetIntegeri_v || !glBeginTransformFeedback || + !glEndTransformFeedback || !glBindBufferRange || !glBindBufferBase || + !glTransformFeedbackVaryings || !glGetTransformFeedbackVarying || + !glVertexAttribIPointer || !glGetVertexAttribIiv || + !glGetVertexAttribIuiv || !glVertexAttribI4i || !glVertexAttribI4ui || + !glVertexAttribI4iv || !glVertexAttribI4uiv || !glGetUniformuiv || + !glGetFragDataLocation || !glUniform1ui || !glUniform2ui || + !glUniform3ui || !glUniform4ui || !glUniform1uiv || !glUniform2uiv || + !glUniform3uiv || !glUniform4uiv || !glClearBufferiv || + !glClearBufferuiv || !glClearBufferfv || !glClearBufferfi || + !glGetStringi || !glCopyBufferSubData || !glGetUniformIndices || + !glGetActiveUniformsiv || !glGetUniformBlockIndex || + !glGetActiveUniformBlockiv || !glGetActiveUniformBlockName || + !glUniformBlockBinding || !glDrawArraysInstanced || + !glDrawElementsInstanced || !glFenceSync || !glIsSync || !glDeleteSync || + !glClientWaitSync || !glWaitSync || !glGetInteger64v || !glGetSynciv || + !glGetInteger64i_v || !glGetBufferParameteri64v || !glGenSamplers || + !glDeleteSamplers || !glIsSampler || !glBindSampler || + !glSamplerParameteri || !glSamplerParameteriv || !glSamplerParameterf || + !glSamplerParameterfv || !glGetSamplerParameteriv || + !glGetSamplerParameterfv || !glVertexAttribDivisor || + !glBindTransformFeedback || !glDeleteTransformFeedbacks || + !glGenTransformFeedbacks || !glIsTransformFeedback || + !glPauseTransformFeedback || !glResumeTransformFeedback || + !glGetProgramBinary || !glProgramBinary || !glProgramParameteri || + !glInvalidateFramebuffer || !glInvalidateSubFramebuffer || + !glTexStorage2D || !glTexStorage3D || !glGetInternalformativ) { + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Function pointer definitions */ GL_APICALL void (*GL_APIENTRY glReadBuffer)( + GLenum mode); +GL_APICALL void (*GL_APIENTRY glDrawRangeElements)(GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, + const GLvoid* indices); +GL_APICALL void (*GL_APIENTRY glTexImage3D)(GLenum target, GLint level, + GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLint border, GLenum format, + GLenum type, const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, const GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, GLenum pname, + GLuint* params); +GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, GLenum pname, + GLvoid** params); +GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, const GLenum* bufs); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length); +GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)(GLsizei n, + const GLuint* arrays); +GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, GLuint* arrays); +GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, GLuint index, + GLint* data); +GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)(GLenum primitiveMode); +GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, GLuint index, + GLuint buffer); +GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)(GLuint index, GLint size, + GLenum type, + GLsizei stride, + const GLvoid* pointer); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, GLenum pname, + GLuint* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, GLint y, + GLint z, GLint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, GLuint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, const GLint* v); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, GLint location, + GLuint* params); +GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)(GLuint program, + const GLchar* name); +GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, GLint drawbuffer, + const GLint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, GLint drawbuffer, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, GLint drawbuffer, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, + GLsizei instanceCount); +GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid* indices, + GLsizei instanceCount); +GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, GLint64* params); +GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, GLsizei* length, + GLint* values); +GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, GLuint index, + GLint64* data); +GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, GLuint* samplers); +GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, GLuint sampler); +GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, GLenum pname, + GLint param); +GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, GLenum pname, + GLfloat param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)(GLuint sampler, + GLenum pname, + const GLfloat* param); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)(GLsizei n, + const GLuint* ids); +GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, GLenum pname, + GLint value); +GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage3D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height, + GLsizei depth); +GL_APICALL void (*GL_APIENTRY glGetInternalformativ)(GLenum target, + GLenum internalformat, + GLenum pname, + GLsizei bufSize, + GLint* params); diff --git a/src/citra_android/jni/ndk_helper/gl3stub.cpp b/src/citra_android/jni/ndk_helper/gl3stub.cpp new file mode 100644 index 000000000..cb3575b4f --- /dev/null +++ b/src/citra_android/jni/ndk_helper/gl3stub.cpp @@ -0,0 +1,421 @@ +/* + * Copyright 2013 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 +#include "gl3stub.h" + +GLboolean gl3stubInit() { +#define FIND_PROC(s) s = (decltype(s))eglGetProcAddress(#s); + FIND_PROC(glReadBuffer); + FIND_PROC(glDrawRangeElements); + FIND_PROC(glTexImage3D); + FIND_PROC(glTexSubImage3D); + FIND_PROC(glCopyTexSubImage3D); + FIND_PROC(glCompressedTexImage3D); + FIND_PROC(glCompressedTexSubImage3D); + FIND_PROC(glGenQueries); + FIND_PROC(glDeleteQueries); + FIND_PROC(glIsQuery); + FIND_PROC(glBeginQuery); + FIND_PROC(glEndQuery); + FIND_PROC(glGetQueryiv); + FIND_PROC(glGetQueryObjectuiv); + FIND_PROC(glUnmapBuffer); + FIND_PROC(glGetBufferPointerv); + FIND_PROC(glDrawBuffers); + FIND_PROC(glUniformMatrix2x3fv); + FIND_PROC(glUniformMatrix3x2fv); + FIND_PROC(glUniformMatrix2x4fv); + FIND_PROC(glUniformMatrix4x2fv); + FIND_PROC(glUniformMatrix3x4fv); + FIND_PROC(glUniformMatrix4x3fv); + FIND_PROC(glBlitFramebuffer); + FIND_PROC(glRenderbufferStorageMultisample); + FIND_PROC(glFramebufferTextureLayer); + FIND_PROC(glMapBufferRange); + FIND_PROC(glFlushMappedBufferRange); + FIND_PROC(glBindVertexArray); + FIND_PROC(glDeleteVertexArrays); + FIND_PROC(glGenVertexArrays); + FIND_PROC(glIsVertexArray); + FIND_PROC(glGetIntegeri_v); + FIND_PROC(glBeginTransformFeedback); + FIND_PROC(glEndTransformFeedback); + FIND_PROC(glBindBufferRange); + FIND_PROC(glBindBufferBase); + FIND_PROC(glTransformFeedbackVaryings); + FIND_PROC(glGetTransformFeedbackVarying); + FIND_PROC(glVertexAttribIPointer); + FIND_PROC(glGetVertexAttribIiv); + FIND_PROC(glGetVertexAttribIuiv); + FIND_PROC(glVertexAttribI4i); + FIND_PROC(glVertexAttribI4ui); + FIND_PROC(glVertexAttribI4iv); + FIND_PROC(glVertexAttribI4uiv); + FIND_PROC(glGetUniformuiv); + FIND_PROC(glGetFragDataLocation); + FIND_PROC(glUniform1ui); + FIND_PROC(glUniform2ui); + FIND_PROC(glUniform3ui); + FIND_PROC(glUniform4ui); + FIND_PROC(glUniform1uiv); + FIND_PROC(glUniform2uiv); + FIND_PROC(glUniform3uiv); + FIND_PROC(glUniform4uiv); + FIND_PROC(glClearBufferiv); + FIND_PROC(glClearBufferuiv); + FIND_PROC(glClearBufferfv); + FIND_PROC(glClearBufferfi); + FIND_PROC(glGetStringi); + FIND_PROC(glCopyBufferSubData); + FIND_PROC(glGetUniformIndices); + FIND_PROC(glGetActiveUniformsiv); + FIND_PROC(glGetUniformBlockIndex); + FIND_PROC(glGetActiveUniformBlockiv); + FIND_PROC(glGetActiveUniformBlockName); + FIND_PROC(glUniformBlockBinding); + FIND_PROC(glDrawArraysInstanced); + FIND_PROC(glDrawElementsInstanced); + FIND_PROC(glFenceSync); + FIND_PROC(glIsSync); + FIND_PROC(glDeleteSync); + FIND_PROC(glClientWaitSync); + FIND_PROC(glWaitSync); + FIND_PROC(glGetInteger64v); + FIND_PROC(glGetSynciv); + FIND_PROC(glGetInteger64i_v); + FIND_PROC(glGetBufferParameteri64v); + FIND_PROC(glGenSamplers); + FIND_PROC(glDeleteSamplers); + FIND_PROC(glIsSampler); + FIND_PROC(glBindSampler); + FIND_PROC(glSamplerParameteri); + FIND_PROC(glSamplerParameteriv); + FIND_PROC(glSamplerParameterf); + FIND_PROC(glSamplerParameterfv); + FIND_PROC(glGetSamplerParameteriv); + FIND_PROC(glGetSamplerParameterfv); + FIND_PROC(glVertexAttribDivisor); + FIND_PROC(glBindTransformFeedback); + FIND_PROC(glDeleteTransformFeedbacks); + FIND_PROC(glGenTransformFeedbacks); + FIND_PROC(glIsTransformFeedback); + FIND_PROC(glPauseTransformFeedback); + FIND_PROC(glResumeTransformFeedback); + FIND_PROC(glGetProgramBinary); + FIND_PROC(glProgramBinary); + FIND_PROC(glProgramParameteri); + FIND_PROC(glInvalidateFramebuffer); + FIND_PROC(glInvalidateSubFramebuffer); + FIND_PROC(glTexStorage2D); + FIND_PROC(glTexStorage3D); + FIND_PROC(glGetInternalformativ); +#undef FIND_PROC + + if (!glReadBuffer || !glDrawRangeElements || !glTexImage3D || + !glTexSubImage3D || !glCopyTexSubImage3D || !glCompressedTexImage3D || + !glCompressedTexSubImage3D || !glGenQueries || !glDeleteQueries || + !glIsQuery || !glBeginQuery || !glEndQuery || !glGetQueryiv || + !glGetQueryObjectuiv || !glUnmapBuffer || !glGetBufferPointerv || + !glDrawBuffers || !glUniformMatrix2x3fv || !glUniformMatrix3x2fv || + !glUniformMatrix2x4fv || !glUniformMatrix4x2fv || !glUniformMatrix3x4fv || + !glUniformMatrix4x3fv || !glBlitFramebuffer || + !glRenderbufferStorageMultisample || !glFramebufferTextureLayer || + !glMapBufferRange || !glFlushMappedBufferRange || !glBindVertexArray || + !glDeleteVertexArrays || !glGenVertexArrays || !glIsVertexArray || + !glGetIntegeri_v || !glBeginTransformFeedback || + !glEndTransformFeedback || !glBindBufferRange || !glBindBufferBase || + !glTransformFeedbackVaryings || !glGetTransformFeedbackVarying || + !glVertexAttribIPointer || !glGetVertexAttribIiv || + !glGetVertexAttribIuiv || !glVertexAttribI4i || !glVertexAttribI4ui || + !glVertexAttribI4iv || !glVertexAttribI4uiv || !glGetUniformuiv || + !glGetFragDataLocation || !glUniform1ui || !glUniform2ui || + !glUniform3ui || !glUniform4ui || !glUniform1uiv || !glUniform2uiv || + !glUniform3uiv || !glUniform4uiv || !glClearBufferiv || + !glClearBufferuiv || !glClearBufferfv || !glClearBufferfi || + !glGetStringi || !glCopyBufferSubData || !glGetUniformIndices || + !glGetActiveUniformsiv || !glGetUniformBlockIndex || + !glGetActiveUniformBlockiv || !glGetActiveUniformBlockName || + !glUniformBlockBinding || !glDrawArraysInstanced || + !glDrawElementsInstanced || !glFenceSync || !glIsSync || !glDeleteSync || + !glClientWaitSync || !glWaitSync || !glGetInteger64v || !glGetSynciv || + !glGetInteger64i_v || !glGetBufferParameteri64v || !glGenSamplers || + !glDeleteSamplers || !glIsSampler || !glBindSampler || + !glSamplerParameteri || !glSamplerParameteriv || !glSamplerParameterf || + !glSamplerParameterfv || !glGetSamplerParameteriv || + !glGetSamplerParameterfv || !glVertexAttribDivisor || + !glBindTransformFeedback || !glDeleteTransformFeedbacks || + !glGenTransformFeedbacks || !glIsTransformFeedback || + !glPauseTransformFeedback || !glResumeTransformFeedback || + !glGetProgramBinary || !glProgramBinary || !glProgramParameteri || + !glInvalidateFramebuffer || !glInvalidateSubFramebuffer || + !glTexStorage2D || !glTexStorage3D || !glGetInternalformativ) { + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Function pointer definitions */ GL_APICALL void (*GL_APIENTRY glReadBuffer)( + GLenum mode); +GL_APICALL void (*GL_APIENTRY glDrawRangeElements)(GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, + const GLvoid* indices); +GL_APICALL void (*GL_APIENTRY glTexImage3D)(GLenum target, GLint level, + GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLint border, GLenum format, + GLenum type, const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, const GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, GLenum pname, + GLuint* params); +GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, GLenum pname, + GLvoid** params); +GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, const GLenum* bufs); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length); +GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)(GLsizei n, + const GLuint* arrays); +GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, GLuint* arrays); +GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, GLuint index, + GLint* data); +GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)(GLenum primitiveMode); +GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, GLuint index, + GLuint buffer); +GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)(GLuint index, GLint size, + GLenum type, + GLsizei stride, + const GLvoid* pointer); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, GLenum pname, + GLuint* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, GLint y, + GLint z, GLint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, GLuint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, const GLint* v); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, GLint location, + GLuint* params); +GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)(GLuint program, + const GLchar* name); +GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, GLint drawbuffer, + const GLint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, GLint drawbuffer, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, GLint drawbuffer, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, + GLsizei instanceCount); +GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid* indices, + GLsizei instanceCount); +GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, GLint64* params); +GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, GLsizei* length, + GLint* values); +GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, GLuint index, + GLint64* data); +GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, GLuint* samplers); +GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, GLuint sampler); +GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, GLenum pname, + GLint param); +GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, GLenum pname, + GLfloat param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)(GLuint sampler, + GLenum pname, + const GLfloat* param); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)(GLsizei n, + const GLuint* ids); +GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, GLenum pname, + GLint value); +GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage3D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height, + GLsizei depth); +GL_APICALL void (*GL_APIENTRY glGetInternalformativ)(GLenum target, + GLenum internalformat, + GLenum pname, + GLsizei bufSize, + GLint* params); diff --git a/src/citra_android/jni/ndk_helper/gl3stub.h b/src/citra_android/jni/ndk_helper/gl3stub.h new file mode 100644 index 000000000..4d2885367 --- /dev/null +++ b/src/citra_android/jni/ndk_helper/gl3stub.h @@ -0,0 +1,661 @@ +#ifndef __gl3_h_ +#define __gl3_h_ + +/* + * stub gl3.h for dynamic loading, based on: + * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ + * + * Changes: + * - Added #include + * - Removed duplicate OpenGL ES 2.0 declarations + * - Converted OpenGL ES 3.0 function prototypes to function pointer + * declarations + * - Added gl3stubInit() declaration + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ** Copyright (c) 2007-2013 The Khronos Group Inc. + ** + ** Permission is hereby granted, free of charge, to any person obtaining a + ** copy of this software and/or associated documentation files (the + ** "Materials"), to deal in the Materials without restriction, including + ** without limitation the rights to use, copy, modify, merge, publish, + ** distribute, sublicense, and/or sell copies of the Materials, and to + ** permit persons to whom the Materials are furnished to do so, subject to + ** the following conditions: + ** + ** The above copyright notice and this permission notice shall be included + ** in all copies or substantial portions of the Materials. + ** + ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +/* + * This files is for apps that want to use ES3 if present, + * but continue to work on pre-API-18 devices. They can't just link to -lGLESv3 + *since + * that library doesn't exist on pre-API-18 devices. + * The function dynamically check if OpenGLES3.0 APIs are present and fill in if + *there are. + * Also the header defines some extra variables for OpenGLES3.0. + * + */ + +/* Call this function before calling any OpenGL ES 3.0 functions. It will + * return GL_TRUE if the OpenGL ES 3.0 was successfully initialized, GL_FALSE + * otherwise. */ +GLboolean gl3stubInit(); + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +typedef unsigned short GLhalf; +#if __ANDROID_API__ <= 19 +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync* GLsync; +#endif + +/*------------------------------------------------------------------------- + * Token definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_3_0 1 + +/* OpenGL ES 3.0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER +#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +/*------------------------------------------------------------------------- + * Entrypoint definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +extern GL_APICALL void (*GL_APIENTRY glReadBuffer)(GLenum mode); +extern GL_APICALL void (*GL_APIENTRY glDrawRangeElements)( + GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const GLvoid* indices); +extern GL_APICALL void (*GL_APIENTRY glTexImage3D)( + GLenum target, GLint level, GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, + const GLvoid* pixels); +extern GL_APICALL void (*GL_APIENTRY glTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const GLvoid* pixels); +extern GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +extern GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +extern GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +extern GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, + const GLuint* ids); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +extern GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +extern GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +extern GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, + GLenum pname, + GLuint* params); +extern GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +extern GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, + GLenum pname, + GLvoid** params); +extern GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, + const GLenum* bufs); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +extern GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +extern GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +extern GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)( + GLenum target, GLintptr offset, GLsizeiptr length); +extern GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +extern GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)( + GLsizei n, const GLuint* arrays); +extern GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, + GLuint* arrays); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +extern GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, + GLuint index, + GLint* data); +extern GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)( + GLenum primitiveMode); +extern GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, + GLuint index, + GLuint buffer, + GLintptr offset, + GLsizeiptr size); +extern GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, + GLuint index, + GLuint buffer); +extern GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +extern GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)( + GLuint index, GLint size, GLenum type, GLsizei stride, + const GLvoid* pointer); +extern GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, + GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, + GLenum pname, + GLuint* params); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, + GLint y, GLint z, + GLint w); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, + GLuint w); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, + const GLint* v); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +extern GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, + GLint location, + GLuint* params); +extern GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)( + GLuint program, const GLchar* name); +extern GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +extern GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +extern GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +extern GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, + GLuint v3); +extern GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, + GLint drawbuffer, + const GLint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, + GLint drawbuffer, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, + GLint drawbuffer, + const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil); +extern GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +extern GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +extern GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +extern GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +extern GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +extern GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)( + GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +extern GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)( + GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, + GLsizei instanceCount); +extern GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +extern GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +extern GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, + GLbitfield flags, + GLuint64 timeout); +extern GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +extern GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, + GLint64* params); +extern GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, + GLsizei* length, + GLint* values); +extern GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, + GLuint index, + GLint64* data); +extern GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +extern GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, + GLuint* samplers); +extern GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +extern GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, + GLuint sampler); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, + GLenum pname, + GLint param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, + GLenum pname, + GLfloat param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)( + GLuint sampler, GLenum pname, const GLfloat* param); +extern GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +extern GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +extern GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)( + GLsizei n, const GLuint* ids); +extern GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, + GLuint* ids); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +extern GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +extern GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +extern GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, + GLenum pname, + GLint value); +extern GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +extern GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glTexStorage3D)( + GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth); +extern GL_APICALL void (*GL_APIENTRY glGetInternalformativ)( + GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, + GLint* params); + +#ifdef __cplusplus +} +#endif + +#endif