Files
Xenia-Canary/src/xenia/hid/input_system.cc
chss95cs@gmail.com eb8154908c atomic cas use prefetchw if available
remove useless memorybarrier
remove double membarrier in wait pm4 cmd
add int64 cvar
use int64 cvar for x64 feature mask
Rework some functions that were frontend bound according to vtune placing some of their code in different noinline functions, profiling after indicating l1 cache misses decreased and perf of func increased
remove long vpinsrd dep chain code for conversion.h, instead do normal load+bswap or movbe if avail
Much faster entry table via split_map, code size could be improved though
GetResolveInfo was very large and had impact on icache, mark callees as noinline + msvc pragma optimize small
use log2 shifts instead of integer divides in memory
minor optimizations in PhysicalHeap::EnableAccessCallbacks, the majority of time in the function is spent looping, NOT calling Protect! Someone should optimize this function and rework the algo completely
remove wonky scheduling log message, it was spammy and unhelpful
lock count was unnecessary for criticalsection mutex, criticalsection is already a recursive mutex
brief notes i gotta run
2022-09-17 04:04:53 -07:00

145 lines
4.5 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/hid/input_system.h"
#include "xenia/base/profiling.h"
#include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_driver.h"
namespace xe {
namespace hid {
DEFINE_bool(vibration, true, "Toggle controller vibration.", "HID");
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {}
InputSystem::~InputSystem() = default;
X_STATUS InputSystem::Setup() { return X_STATUS_SUCCESS; }
void InputSystem::AddDriver(std::unique_ptr<InputDriver> driver) {
drivers_.push_back(std::move(driver));
}
void InputSystem::UpdateUsedSlot(uint8_t slot, bool connected) {
if (slot == 0xFF) {
slot = 0;
}
if (connected) {
connected_slot |= (1 << slot);
} else {
connected_slot &= ~(1 << slot);
}
}
X_RESULT InputSystem::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetCapabilities(user_index, flags, out_caps);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::GetState(uint32_t user_index, X_INPUT_STATE* out_state) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetState(user_index, out_state);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::SetState(uint32_t user_index,
X_INPUT_VIBRATION* vibration) {
SCOPE_profile_cpu_f("hid");
X_INPUT_VIBRATION modified_vibration = ModifyVibrationLevel(vibration);
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->SetState(user_index, &modified_vibration);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) {
SCOPE_profile_cpu_f("hid");
bool any_connected = false;
for (auto& driver : drivers_) {
X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke);
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true;
}
if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) {
UpdateUsedSlot(user_index, any_connected);
return result;
}
}
UpdateUsedSlot(user_index, any_connected);
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
}
void InputSystem::ToggleVibration() {
OVERRIDE_bool(vibration, !cvars::vibration);
// Send instant update to vibration state to prevent awaiting for next tick.
X_INPUT_VIBRATION vibration = X_INPUT_VIBRATION();
for (uint8_t user_index = 0; user_index < 4; user_index++) {
SetState(user_index, &vibration);
}
}
X_INPUT_VIBRATION InputSystem::ModifyVibrationLevel(
X_INPUT_VIBRATION* vibration) {
X_INPUT_VIBRATION modified_vibration = *vibration;
if (cvars::vibration) {
return modified_vibration;
}
// TODO(Gliniak): Use modifier instead of boolean value.
modified_vibration.left_motor_speed = 0;
modified_vibration.right_motor_speed = 0;
return modified_vibration;
}
std::unique_lock<xe_mutex> InputSystem::lock() {
return std::unique_lock<xe_mutex>{lock_};
}
} // namespace hid
} // namespace xe