Compare commits

..

6 Commits

Author SHA1 Message Date
german e46f0e084c Implement full mouse support 2020-11-25 23:59:30 -06:00
Rodrigo Locatti 1889b641d9 Merge pull request #4308 from ReinUsesLisp/maxwell-3d-funcs
maxwell_3d: Move code to separate functions and insert instead of push_back
2020-11-20 01:57:22 -03:00
bunnei 6971d08893 Merge pull request #4948 from lioncash/page-resize
virtual_buffer: Do nothing on resize() calls with same sizes
2020-11-19 12:39:38 -08:00
Lioncash 412044960a virtual_buffer: Do nothing on resize() calls with same sizes
Prevents us from churning memory by freeing and reallocating a memory
block that would have already been adequate as is.
2020-11-19 07:54:03 -05:00
ReinUsesLisp 622830f4e1 maxwell_3d: Use insert instead of loop push_back
This reduces the overhead of bounds checking on each element.
It won't reduce the cost of allocation because usually this vector's
capacity is usually large enough to hold whatever we push to it.
2020-11-11 19:52:19 -03:00
ReinUsesLisp 9ea8cffe35 maxwell_3d: Move code to separate functions
Deduplicate some code and put it in separate functions so it's easier to
understand and profile.
2020-11-11 19:52:19 -03:00
18 changed files with 1009 additions and 525 deletions
+6 -1
View File
@@ -43,9 +43,14 @@ public:
}
void resize(std::size_t count) {
const auto new_size = count * sizeof(T);
if (new_size == alloc_size) {
return;
}
FreeMemoryPages(base_ptr, alloc_size);
alloc_size = count * sizeof(T);
alloc_size = new_size;
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
}
+7 -2
View File
@@ -161,10 +161,15 @@ using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common
using MotionDevice = InputDevice<MotionStatus>;
/**
* A touch device is an input device that returns a tuple of two floats and a bool. The floats are
* A touch status is an object that returns a tuple of two floats and a bool. The floats are
* x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed.
*/
using TouchDevice = InputDevice<std::tuple<float, float, bool>>;
using TouchStatus = std::tuple<float, float, bool>;
/**
* A touch device is an input device that returns a touch status object
*/
using TouchDevice = InputDevice<TouchStatus>;
/**
* A mouse device is an input device that returns a tuple of two floats and four ints.
+4 -2
View File
@@ -5,8 +5,6 @@ add_library(input_common STATIC
keyboard.h
main.cpp
main.h
motion_emu.cpp
motion_emu.h
motion_from_button.cpp
motion_from_button.h
motion_input.cpp
@@ -19,6 +17,10 @@ add_library(input_common STATIC
gcadapter/gc_adapter.h
gcadapter/gc_poller.cpp
gcadapter/gc_poller.h
mouse/mouse_input.cpp
mouse/mouse_input.h
mouse/mouse_poller.cpp
mouse/mouse_poller.h
sdl/sdl.cpp
sdl/sdl.h
udp/client.cpp
+63 -10
View File
@@ -10,8 +10,9 @@
#include "input_common/gcadapter/gc_poller.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "input_common/motion_from_button.h"
#include "input_common/mouse/mouse_input.h"
#include "input_common/mouse/mouse_poller.h"
#include "input_common/touch_from_button.h"
#include "input_common/udp/client.h"
#include "input_common/udp/udp.h"
@@ -37,8 +38,6 @@ struct InputSubsystem::Impl {
std::make_shared<AnalogFromButton>());
Input::RegisterFactory<Input::MotionDevice>("keyboard",
std::make_shared<MotionFromButton>());
motion_emu = std::make_shared<MotionEmu>();
Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
std::make_shared<TouchFromButtonFactory>());
@@ -51,6 +50,16 @@ struct InputSubsystem::Impl {
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion);
udptouch = std::make_shared<UDPTouchFactory>(udp);
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch);
mouse = std::make_shared<MouseInput::Mouse>();
mousebuttons = std::make_shared<MouseButtonFactory>(mouse);
Input::RegisterFactory<Input::ButtonDevice>("mouse", mousebuttons);
mouseanalog = std::make_shared<MouseAnalogFactory>(mouse);
Input::RegisterFactory<Input::AnalogDevice>("mouse", mouseanalog);
mousemotion = std::make_shared<MouseMotionFactory>(mouse);
Input::RegisterFactory<Input::MotionDevice>("mouse", mousemotion);
mousetouch = std::make_shared<MouseTouchFactory>(mouse);
Input::RegisterFactory<Input::TouchDevice>("mouse", mousetouch);
}
void Shutdown() {
@@ -58,8 +67,6 @@ struct InputSubsystem::Impl {
Input::UnregisterFactory<Input::MotionDevice>("keyboard");
keyboard.reset();
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
motion_emu.reset();
Input::UnregisterFactory<Input::TouchDevice>("touch_from_button");
#ifdef HAVE_SDL2
sdl.reset();
@@ -77,6 +84,16 @@ struct InputSubsystem::Impl {
udpmotion.reset();
udptouch.reset();
Input::UnregisterFactory<Input::ButtonDevice>("mouse");
Input::UnregisterFactory<Input::AnalogDevice>("mouse");
Input::UnregisterFactory<Input::MotionDevice>("mouse");
Input::UnregisterFactory<Input::TouchDevice>("mouse");
mousebuttons.reset();
mouseanalog.reset();
mousemotion.reset();
mousetouch.reset();
}
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
@@ -140,7 +157,6 @@ struct InputSubsystem::Impl {
}
std::shared_ptr<Keyboard> keyboard;
std::shared_ptr<MotionEmu> motion_emu;
#ifdef HAVE_SDL2
std::unique_ptr<SDL::State> sdl;
#endif
@@ -149,8 +165,13 @@ struct InputSubsystem::Impl {
std::shared_ptr<GCVibrationFactory> gcvibration;
std::shared_ptr<UDPMotionFactory> udpmotion;
std::shared_ptr<UDPTouchFactory> udptouch;
std::shared_ptr<MouseButtonFactory> mousebuttons;
std::shared_ptr<MouseAnalogFactory> mouseanalog;
std::shared_ptr<MouseMotionFactory> mousemotion;
std::shared_ptr<MouseTouchFactory> mousetouch;
std::shared_ptr<CemuhookUDP::Client> udp;
std::shared_ptr<GCAdapter::Adapter> gcadapter;
std::shared_ptr<MouseInput::Mouse> mouse;
};
InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
@@ -173,12 +194,12 @@ const Keyboard* InputSubsystem::GetKeyboard() const {
return impl->keyboard.get();
}
MotionEmu* InputSubsystem::GetMotionEmu() {
return impl->motion_emu.get();
MouseInput::Mouse* InputSubsystem::GetMouse() {
return impl->mouse.get();
}
const MotionEmu* InputSubsystem::GetMotionEmu() const {
return impl->motion_emu.get();
const MouseInput::Mouse* InputSubsystem::GetMouse() const {
return impl->mouse.get();
}
std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
@@ -229,6 +250,38 @@ const UDPTouchFactory* InputSubsystem::GetUDPTouch() const {
return impl->udptouch.get();
}
MouseButtonFactory* InputSubsystem::GetMouseButtons() {
return impl->mousebuttons.get();
}
const MouseButtonFactory* InputSubsystem::GetMouseButtons() const {
return impl->mousebuttons.get();
}
MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() {
return impl->mouseanalog.get();
}
const MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() const {
return impl->mouseanalog.get();
}
MouseMotionFactory* InputSubsystem::GetMouseMotions() {
return impl->mousemotion.get();
}
const MouseMotionFactory* InputSubsystem::GetMouseMotions() const {
return impl->mousemotion.get();
}
MouseTouchFactory* InputSubsystem::GetMouseTouch() {
return impl->mousetouch.get();
}
const MouseTouchFactory* InputSubsystem::GetMouseTouch() const {
return impl->mousetouch.get();
}
void InputSubsystem::ReloadInputDevices() {
if (!impl->udp) {
return;
+36 -5
View File
@@ -25,6 +25,10 @@ namespace Settings::NativeMotion {
enum Values : int;
}
namespace MouseInput {
class Mouse;
}
namespace InputCommon {
namespace Polling {
@@ -56,8 +60,11 @@ class GCAnalogFactory;
class GCButtonFactory;
class UDPMotionFactory;
class UDPTouchFactory;
class MouseButtonFactory;
class MouseAnalogFactory;
class MouseMotionFactory;
class MouseTouchFactory;
class Keyboard;
class MotionEmu;
/**
* Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
@@ -90,11 +97,11 @@ public:
/// Retrieves the underlying keyboard device.
[[nodiscard]] const Keyboard* GetKeyboard() const;
/// Retrieves the underlying motion emulation factory.
[[nodiscard]] MotionEmu* GetMotionEmu();
/// Retrieves the underlying mouse device.
[[nodiscard]] MouseInput::Mouse* GetMouse();
/// Retrieves the underlying motion emulation factory.
[[nodiscard]] const MotionEmu* GetMotionEmu() const;
/// Retrieves the underlying mouse device.
[[nodiscard]] const MouseInput::Mouse* GetMouse() const;
/**
* Returns all available input devices that this Factory can create a new device with.
@@ -137,6 +144,30 @@ public:
/// Retrieves the underlying udp touch handler.
[[nodiscard]] const UDPTouchFactory* GetUDPTouch() const;
/// Retrieves the underlying GameCube button handler.
[[nodiscard]] MouseButtonFactory* GetMouseButtons();
/// Retrieves the underlying GameCube button handler.
[[nodiscard]] const MouseButtonFactory* GetMouseButtons() const;
/// Retrieves the underlying udp touch handler.
[[nodiscard]] MouseAnalogFactory* GetMouseAnalogs();
/// Retrieves the underlying udp touch handler.
[[nodiscard]] const MouseAnalogFactory* GetMouseAnalogs() const;
/// Retrieves the underlying udp motion handler.
[[nodiscard]] MouseMotionFactory* GetMouseMotions();
/// Retrieves the underlying udp motion handler.
[[nodiscard]] const MouseMotionFactory* GetMouseMotions() const;
/// Retrieves the underlying udp touch handler.
[[nodiscard]] MouseTouchFactory* GetMouseTouch();
/// Retrieves the underlying udp touch handler.
[[nodiscard]] const MouseTouchFactory* GetMouseTouch() const;
/// Reloads the input devices
void ReloadInputDevices();
-179
View File
@@ -1,179 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <chrono>
#include <mutex>
#include <thread>
#include <tuple>
#include "common/math_util.h"
#include "common/quaternion.h"
#include "common/thread.h"
#include "common/vector_math.h"
#include "input_common/motion_emu.h"
namespace InputCommon {
// Implementation class of the motion emulation device
class MotionEmuDevice {
public:
explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
: update_millisecond(update_millisecond_),
update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
std::chrono::milliseconds(update_millisecond))),
sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
~MotionEmuDevice() {
if (motion_emu_thread.joinable()) {
shutdown_event.Set();
motion_emu_thread.join();
}
}
void BeginTilt(int x, int y) {
mouse_origin = Common::MakeVec(x, y);
is_tilting = true;
}
void Tilt(int x, int y) {
if (!is_tilting) {
return;
}
std::lock_guard guard{tilt_mutex};
const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
if (mouse_move.x == 0 && mouse_move.y == 0) {
tilt_angle = 0;
} else {
tilt_direction = mouse_move.Cast<float>();
tilt_angle =
std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
}
}
void EndTilt() {
std::lock_guard guard{tilt_mutex};
tilt_angle = 0;
is_tilting = false;
}
Input::MotionStatus GetStatus() {
std::lock_guard guard{status_mutex};
return status;
}
private:
const int update_millisecond;
const std::chrono::steady_clock::duration update_duration;
const float sensitivity;
Common::Vec2<int> mouse_origin;
std::mutex tilt_mutex;
Common::Vec2<float> tilt_direction;
float tilt_angle = 0;
bool is_tilting = false;
Common::Event shutdown_event;
Input::MotionStatus status;
std::mutex status_mutex;
// Note: always keep the thread declaration at the end so that other objects are initialized
// before this!
std::thread motion_emu_thread;
void MotionEmuThread() {
auto update_time = std::chrono::steady_clock::now();
Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
while (!shutdown_event.WaitUntil(update_time)) {
update_time += update_duration;
const Common::Quaternion<float> old_q = q;
{
std::lock_guard guard{tilt_mutex};
// Find the quaternion describing current 3DS tilting
q = Common::MakeQuaternion(
Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
}
const auto inv_q = q.Inverse();
// Set the gravity vector in world space
auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
// Find the angular rate vector in world space
auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f;
// Transform the two vectors from world space to 3DS space
gravity = QuaternionRotate(inv_q, gravity);
angular_rate = QuaternionRotate(inv_q, angular_rate);
// TODO: Calculate the correct rotation vector and orientation matrix
const auto matrix4x4 = q.ToMatrix();
const auto rotation = Common::MakeVec(0.0f, 0.0f, 0.0f);
const std::array orientation{
Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10]),
};
// Update the sensor state
{
std::lock_guard guard{status_mutex};
status = std::make_tuple(gravity, angular_rate, rotation, orientation);
}
}
}
};
// Interface wrapper held by input receiver as a unique_ptr. It holds the implementation class as
// a shared_ptr, which is also observed by the factory class as a weak_ptr. In this way the factory
// can forward all the inputs to the implementation only when it is valid.
class MotionEmuDeviceWrapper : public Input::MotionDevice {
public:
explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
}
Input::MotionStatus GetStatus() const override {
return device->GetStatus();
}
std::shared_ptr<MotionEmuDevice> device;
};
std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) {
const int update_period = params.Get("update_period", 100);
const float sensitivity = params.Get("sensitivity", 0.01f);
auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
// Previously created device is disconnected here. Having two motion devices for 3DS is not
// expected.
current_device = device_wrapper->device;
return device_wrapper;
}
void MotionEmu::BeginTilt(int x, int y) {
if (auto ptr = current_device.lock()) {
ptr->BeginTilt(x, y);
}
}
void MotionEmu::Tilt(int x, int y) {
if (auto ptr = current_device.lock()) {
ptr->Tilt(x, y);
}
}
void MotionEmu::EndTilt() {
if (auto ptr = current_device.lock()) {
ptr->EndTilt();
}
}
} // namespace InputCommon
-46
View File
@@ -1,46 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/frontend/input.h"
namespace InputCommon {
class MotionEmuDevice;
class MotionEmu : public Input::Factory<Input::MotionDevice> {
public:
/**
* Creates a motion device emulated from mouse input
* @param params contains parameters for creating the device:
* - "update_period": update period in milliseconds
* - "sensitivity": the coefficient converting mouse movement to tilting angle
*/
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
/**
* Signals that a motion sensor tilt has begun.
* @param x the x-coordinate of the cursor
* @param y the y-coordinate of the cursor
*/
void BeginTilt(int x, int y);
/**
* Signals that a motion sensor tilt is occurring.
* @param x the x-coordinate of the cursor
* @param y the y-coordinate of the cursor
*/
void Tilt(int x, int y);
/**
* Signals that a motion sensor tilt has ended.
*/
void EndTilt();
private:
std::weak_ptr<MotionEmuDevice> current_device;
};
} // namespace InputCommon
+125
View File
@@ -0,0 +1,125 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "common/math_util.h"
#include "common/param_package.h"
#include "input_common/mouse/mouse_input.h"
namespace MouseInput {
Mouse::Mouse() {
update_thread = std::thread(&Mouse::UpdateThread, this);
}
Mouse::~Mouse() {
update_thread_running = false;
if (update_thread.joinable()) {
update_thread.join();
}
}
void Mouse::UpdateThread() {
constexpr int update_time = 10;
while (update_thread_running) {
for (MouseInfo& info : mouse_info) {
Common::Vec3f angular_direction = {-info.tilt_direction.y, 0.0f,
-info.tilt_direction.x};
info.motion.SetGyroscope(angular_direction * info.tilt_speed);
info.motion.UpdateRotation(update_time * 1000);
info.motion.UpdateOrientation(update_time * 1000);
info.tilt_speed = 0;
info.data.motion = info.motion.GetMotion();
}
if (configuring) {
UpdateYuzuSettings();
}
std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
}
}
void Mouse::UpdateYuzuSettings() {
MouseStatus pad_status{};
if (buttons != 0) {
pad_status.button = last_button;
mouse_queue.Push(pad_status);
}
}
void Mouse::PressButton(int x, int y, int button_) {
if (button_ >= static_cast<int>(mouse_info.size())) {
return;
}
int button = 1 << button_;
buttons |= static_cast<u16>(button);
last_button = static_cast<MouseButton>(button_);
mouse_info[button_].mouse_origin = Common::MakeVec(x, y);
mouse_info[button_].last_mouse_position = Common::MakeVec(x, y);
mouse_info[button_].data.pressed = true;
}
void Mouse::MouseMove(int x, int y) {
for (MouseInfo& info : mouse_info) {
if (info.data.pressed) {
auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin;
auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position;
info.last_mouse_position = Common::MakeVec(x, y);
info.data.axis = {mouse_move.x, -mouse_move.y};
if (mouse_change.x == 0 && mouse_change.y == 0) {
info.tilt_speed = 0;
} else {
info.tilt_direction = mouse_change.Cast<float>();
info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
}
}
}
}
void Mouse::ReleaseButton(int button_) {
if (button_ >= static_cast<int>(mouse_info.size())) {
return;
}
int button = 1 << button_;
buttons &= static_cast<u16>(0xFF - button);
mouse_info[button_].tilt_speed = 0;
mouse_info[button_].data.pressed = false;
mouse_info[button_].data.axis = {0, 0};
}
void Mouse::BeginConfiguration() {
buttons = 0;
last_button = MouseButton::Undefined;
mouse_queue.Clear();
configuring = true;
}
void Mouse::EndConfiguration() {
buttons = 0;
last_button = MouseButton::Undefined;
mouse_queue.Clear();
configuring = false;
}
Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
return mouse_queue;
}
const Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() const {
return mouse_queue;
}
MouseData& Mouse::GetMouseState(std::size_t button) {
return mouse_info[button].data;
}
const MouseData& Mouse::GetMouseState(std::size_t button) const {
return mouse_info[button].data;
}
} // namespace MouseInput
+99
View File
@@ -0,0 +1,99 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <algorithm>
#include <functional>
#include <mutex>
#include <thread>
#include <unordered_map>
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
#include "core/frontend/input.h"
#include "input_common/main.h"
#include "input_common/motion_input.h"
namespace MouseInput {
enum class MouseButton {
Left,
Wheel,
Right,
Foward,
Backward,
Undefined,
};
struct MouseStatus {
MouseButton button{MouseButton::Undefined};
};
struct MouseData {
bool pressed{};
std::array<int, 2> axis{};
Input::MotionStatus motion{};
Input::TouchStatus touch{};
};
class Mouse {
public:
Mouse();
~Mouse();
/// Used for polling
void BeginConfiguration();
void EndConfiguration();
/**
* Signals that a button is pressed.
* @param x the x-coordinate of the cursor
* @param y the y-coordinate of the cursor
* @param button the button pressed
*/
void PressButton(int x, int y, int button_);
/**
* Signals that mouse has moved.
* @param x the x-coordinate of the cursor
* @param y the y-coordinate of the cursor
*/
void MouseMove(int x, int y);
/**
* Signals that a motion sensor tilt has ended.
*/
void ReleaseButton(int button_);
[[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
[[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
[[nodiscard]] MouseData& GetMouseState(std::size_t button);
[[nodiscard]] const MouseData& GetMouseState(std::size_t button) const;
private:
void UpdateThread();
void UpdateYuzuSettings();
struct MouseInfo {
InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
Common::Vec2<int> mouse_origin;
Common::Vec2<int> last_mouse_position;
bool is_tilting = false;
float sensitivity{0.120f};
float tilt_speed = 0;
Common::Vec2<float> tilt_direction;
MouseData data;
};
u16 buttons{};
std::thread update_thread;
MouseButton last_button{MouseButton::Undefined};
std::array<MouseInfo, 5> mouse_info;
Common::SPSCQueue<MouseStatus> mouse_queue;
bool configuring{false};
bool update_thread_running{true};
};
} // namespace MouseInput
+261
View File
@@ -0,0 +1,261 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <atomic>
#include <list>
#include <mutex>
#include <utility>
#include "common/assert.h"
#include "common/threadsafe_queue.h"
#include "input_common/mouse/mouse_input.h"
#include "input_common/mouse/mouse_poller.h"
namespace InputCommon {
class MouseButton final : public Input::ButtonDevice {
public:
explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_)
: button(button_), mouse_input(mouse_input_) {}
bool GetStatus() const override {
return mouse_input->GetMouseState(button).pressed;
}
private:
const u32 button;
const MouseInput::Mouse* mouse_input;
};
MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
: mouse_input(std::move(mouse_input_)) {}
std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
const Common::ParamPackage& params) {
const auto button_id = params.Get("button", 0);
return std::make_unique<MouseButton>(button_id, mouse_input.get());
}
Common::ParamPackage MouseButtonFactory::GetNextInput() const {
MouseInput::MouseStatus pad;
Common::ParamPackage params;
auto& queue = mouse_input->GetMouseQueue();
while (queue.Pop(pad)) {
// This while loop will break on the earliest detected button
if (pad.button != MouseInput::MouseButton::Undefined) {
params.Set("engine", "mouse");
params.Set("button", static_cast<u16>(pad.button));
return params;
}
}
return params;
}
void MouseButtonFactory::BeginConfiguration() {
polling = true;
mouse_input->BeginConfiguration();
}
void MouseButtonFactory::EndConfiguration() {
polling = false;
mouse_input->EndConfiguration();
}
class MouseAnalog final : public Input::AnalogDevice {
public:
explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_, float range_,
const MouseInput::Mouse* mouse_input_)
: button(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), range(range_),
mouse_input(mouse_input_) {}
float GetAxis(u32 axis) const {
std::lock_guard lock{mutex};
const auto axis_value =
static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
return axis_value / (100.0f * range);
}
std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
float x = GetAxis(analog_axis_x);
float y = GetAxis(analog_axis_y);
// Make sure the coordinates are in the unit circle,
// otherwise normalize it.
float r = x * x + y * y;
if (r > 1.0f) {
r = std::sqrt(r);
x /= r;
y /= r;
}
return {x, y};
}
std::tuple<float, float> GetStatus() const override {
const auto [x, y] = GetAnalog(axis_x, axis_y);
const float r = std::sqrt((x * x) + (y * y));
if (r > deadzone) {
return {x / r * (r - deadzone) / (1 - deadzone),
y / r * (r - deadzone) / (1 - deadzone)};
}
return {0.0f, 0.0f};
}
private:
const u32 button;
const u32 axis_x;
const u32 axis_y;
const float deadzone;
const float range;
const MouseInput::Mouse* mouse_input;
mutable std::mutex mutex;
};
/// An analog device factory that creates analog devices from GC Adapter
MouseAnalogFactory::MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
: mouse_input(std::move(mouse_input_)) {}
/**
* Creates analog device from joystick axes
* @param params contains parameters for creating the device:
* - "port": the nth gcpad on the adapter
* - "axis_x": the index of the axis to be bind as x-axis
* - "axis_y": the index of the axis to be bind as y-axis
*/
std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create(
const Common::ParamPackage& params) {
const auto port = static_cast<u32>(params.Get("port", 0));
const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
return std::make_unique<MouseAnalog>(port, axis_x, axis_y, deadzone, range, mouse_input.get());
}
void MouseAnalogFactory::BeginConfiguration() {
polling = true;
mouse_input->BeginConfiguration();
}
void MouseAnalogFactory::EndConfiguration() {
polling = false;
mouse_input->EndConfiguration();
}
Common::ParamPackage MouseAnalogFactory::GetNextInput() const {
MouseInput::MouseStatus pad;
Common::ParamPackage params;
auto& queue = mouse_input->GetMouseQueue();
while (queue.Pop(pad)) {
// This while loop will break on the earliest detected button
if (pad.button != MouseInput::MouseButton::Undefined) {
params.Set("engine", "mouse");
params.Set("port", static_cast<u16>(pad.button));
params.Set("axis_x", 0);
params.Set("axis_y", 1);
return params;
}
}
return params;
}
class MouseMotion final : public Input::MotionDevice {
public:
explicit MouseMotion(u32 button_, const MouseInput::Mouse* mouse_input_)
: button(button_), mouse_input(mouse_input_) {}
Input::MotionStatus GetStatus() const override {
return mouse_input->GetMouseState(button).motion;
}
private:
const u32 button;
const MouseInput::Mouse* mouse_input;
};
MouseMotionFactory::MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
: mouse_input(std::move(mouse_input_)) {}
std::unique_ptr<Input::MotionDevice> MouseMotionFactory::Create(
const Common::ParamPackage& params) {
const auto button_id = params.Get("button", 0);
return std::make_unique<MouseMotion>(button_id, mouse_input.get());
}
Common::ParamPackage MouseMotionFactory::GetNextInput() const {
MouseInput::MouseStatus pad;
Common::ParamPackage params;
auto& queue = mouse_input->GetMouseQueue();
while (queue.Pop(pad)) {
// This while loop will break on the earliest detected button
if (pad.button != MouseInput::MouseButton::Undefined) {
params.Set("engine", "mouse");
params.Set("button", static_cast<u16>(pad.button));
return params;
}
}
return params;
}
void MouseMotionFactory::BeginConfiguration() {
polling = true;
mouse_input->BeginConfiguration();
}
void MouseMotionFactory::EndConfiguration() {
polling = false;
mouse_input->EndConfiguration();
}
class MouseTouch final : public Input::TouchDevice {
public:
explicit MouseTouch(u32 button_, const MouseInput::Mouse* mouse_input_)
: button(button_), mouse_input(mouse_input_) {}
Input::TouchStatus GetStatus() const override {
return mouse_input->GetMouseState(button).touch;
}
private:
const u32 button;
const MouseInput::Mouse* mouse_input;
};
MouseTouchFactory::MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
: mouse_input(std::move(mouse_input_)) {}
std::unique_ptr<Input::TouchDevice> MouseTouchFactory::Create(const Common::ParamPackage& params) {
const auto button_id = params.Get("button", 0);
return std::make_unique<MouseTouch>(button_id, mouse_input.get());
}
Common::ParamPackage MouseTouchFactory::GetNextInput() const {
MouseInput::MouseStatus pad;
Common::ParamPackage params;
auto& queue = mouse_input->GetMouseQueue();
while (queue.Pop(pad)) {
// This while loop will break on the earliest detected button
if (pad.button != MouseInput::MouseButton::Undefined) {
params.Set("engine", "mouse");
params.Set("button", static_cast<u16>(pad.button));
return params;
}
}
return params;
}
void MouseTouchFactory::BeginConfiguration() {
polling = true;
mouse_input->BeginConfiguration();
}
void MouseTouchFactory::EndConfiguration() {
polling = false;
mouse_input->EndConfiguration();
}
} // namespace InputCommon
+109
View File
@@ -0,0 +1,109 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/frontend/input.h"
#include "input_common/mouse/mouse_input.h"
namespace InputCommon {
/**
* A button device factory representing a mouse. It receives mouse events and forward them
* to all button devices it created.
*/
class MouseButtonFactory final : public Input::Factory<Input::ButtonDevice> {
public:
explicit MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
/**
* Creates a button device from a button press
* @param params contains parameters for creating the device:
* - "code": the code of the key to bind with the button
*/
std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput() const;
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
private:
std::shared_ptr<MouseInput::Mouse> mouse_input;
bool polling = false;
};
/// An analog device factory that creates analog devices from mouse
class MouseAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
public:
explicit MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput() const;
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
private:
std::shared_ptr<MouseInput::Mouse> mouse_input;
bool polling = false;
};
/// A motion device factory that creates motion devices from mouse
class MouseMotionFactory final : public Input::Factory<Input::MotionDevice> {
public:
explicit MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput() const;
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
private:
std::shared_ptr<MouseInput::Mouse> mouse_input;
bool polling = false;
};
/// An touch device factory that creates touch devices from mouse
class MouseTouchFactory final : public Input::Factory<Input::TouchDevice> {
public:
explicit MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput() const;
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
private:
std::shared_ptr<MouseInput::Mouse> mouse_input;
bool polling = false;
};
} // namespace InputCommon
+114 -151
View File
@@ -124,6 +124,112 @@ void Maxwell3D::InitializeRegisterDefaults() {
mme_inline[MAXWELL3D_REG_INDEX(index_array.count)] = true;
}
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
if (executing_macro == 0) {
// A macro call must begin by writing the macro method's register, not its argument.
ASSERT_MSG((method % 2) == 0,
"Can't start macro execution by writing to the ARGS register");
executing_macro = method;
}
macro_params.insert(macro_params.end(), base_start, base_start + amount);
// Call the macro when there are no more parameters in the command buffer
if (is_last_call) {
CallMacroMethod(executing_macro, macro_params);
macro_params.clear();
}
}
u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
// Keep track of the register value in shadow_state when requested.
const auto control = shadow_state.shadow_ram_control;
if (control == Regs::ShadowRamControl::Track ||
control == Regs::ShadowRamControl::TrackWithFilter) {
shadow_state.reg_array[method] = argument;
return argument;
}
if (control == Regs::ShadowRamControl::Replay) {
return shadow_state.reg_array[method];
}
return argument;
}
void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) {
if (regs.reg_array[method] == argument) {
return;
}
regs.reg_array[method] = argument;
for (const auto& table : dirty.tables) {
dirty.flags[table[method]] = true;
}
}
void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument,
bool is_last_call) {
switch (method) {
case MAXWELL3D_REG_INDEX(wait_for_idle):
return rasterizer->WaitForIdle();
case MAXWELL3D_REG_INDEX(shadow_ram_control):
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
return;
case MAXWELL3D_REG_INDEX(macros.data):
return macro_engine->AddCode(regs.macros.upload_address, argument);
case MAXWELL3D_REG_INDEX(macros.bind):
return ProcessMacroBind(argument);
case MAXWELL3D_REG_INDEX(firmware[4]):
return ProcessFirmwareCall4();
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]):
return StartCBData(method);
case MAXWELL3D_REG_INDEX(cb_bind[0]):
return ProcessCBBind(0);
case MAXWELL3D_REG_INDEX(cb_bind[1]):
return ProcessCBBind(1);
case MAXWELL3D_REG_INDEX(cb_bind[2]):
return ProcessCBBind(2);
case MAXWELL3D_REG_INDEX(cb_bind[3]):
return ProcessCBBind(3);
case MAXWELL3D_REG_INDEX(cb_bind[4]):
return ProcessCBBind(4);
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl):
return DrawArrays();
case MAXWELL3D_REG_INDEX(clear_buffers):
return ProcessClearBuffers();
case MAXWELL3D_REG_INDEX(query.query_get):
return ProcessQueryGet();
case MAXWELL3D_REG_INDEX(condition.mode):
return ProcessQueryCondition();
case MAXWELL3D_REG_INDEX(counter_reset):
return ProcessCounterReset();
case MAXWELL3D_REG_INDEX(sync_info):
return ProcessSyncPoint();
case MAXWELL3D_REG_INDEX(exec_upload):
return upload_state.ProcessExec(regs.exec_upload.linear != 0);
case MAXWELL3D_REG_INDEX(data_upload):
upload_state.ProcessData(argument, is_last_call);
if (is_last_call) {
OnMemoryWrite();
}
return;
}
}
void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) {
// Reset the current macro.
executing_macro = 0;
@@ -157,142 +263,16 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
// Methods after 0xE00 are special, they're actually triggers for some microcode that was
// uploaded to the GPU during initialization.
if (method >= MacroRegistersStart) {
// We're trying to execute a macro
if (executing_macro == 0) {
// A macro call must begin by writing the macro method's register, not its argument.
ASSERT_MSG((method % 2) == 0,
"Can't start macro execution by writing to the ARGS register");
executing_macro = method;
}
macro_params.push_back(method_argument);
// Call the macro when there are no more parameters in the command buffer
if (is_last_call) {
CallMacroMethod(executing_macro, macro_params);
macro_params.clear();
}
ProcessMacro(method, &method_argument, 1, is_last_call);
return;
}
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
u32 arg = method_argument;
// Keep track of the register value in shadow_state when requested.
if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track ||
shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) {
shadow_state.reg_array[method] = arg;
} else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) {
arg = shadow_state.reg_array[method];
}
if (regs.reg_array[method] != arg) {
regs.reg_array[method] = arg;
for (const auto& table : dirty.tables) {
dirty.flags[table[method]] = true;
}
}
switch (method) {
case MAXWELL3D_REG_INDEX(wait_for_idle): {
rasterizer->WaitForIdle();
break;
}
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_argument);
break;
}
case MAXWELL3D_REG_INDEX(macros.data): {
macro_engine->AddCode(regs.macros.upload_address, arg);
break;
}
case MAXWELL3D_REG_INDEX(macros.bind): {
ProcessMacroBind(arg);
break;
}
case MAXWELL3D_REG_INDEX(firmware[4]): {
ProcessFirmwareCall4();
break;
}
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): {
StartCBData(method);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[0]): {
ProcessCBBind(0);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[1]): {
ProcessCBBind(1);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[2]): {
ProcessCBBind(2);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[3]): {
ProcessCBBind(3);
break;
}
case MAXWELL3D_REG_INDEX(cb_bind[4]): {
ProcessCBBind(4);
break;
}
case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): {
DrawArrays();
break;
}
case MAXWELL3D_REG_INDEX(clear_buffers): {
ProcessClearBuffers();
break;
}
case MAXWELL3D_REG_INDEX(query.query_get): {
ProcessQueryGet();
break;
}
case MAXWELL3D_REG_INDEX(condition.mode): {
ProcessQueryCondition();
break;
}
case MAXWELL3D_REG_INDEX(counter_reset): {
ProcessCounterReset();
break;
}
case MAXWELL3D_REG_INDEX(sync_info): {
ProcessSyncPoint();
break;
}
case MAXWELL3D_REG_INDEX(exec_upload): {
upload_state.ProcessExec(regs.exec_upload.linear != 0);
break;
}
case MAXWELL3D_REG_INDEX(data_upload): {
upload_state.ProcessData(arg, is_last_call);
if (is_last_call) {
OnMemoryWrite();
}
break;
}
default:
break;
}
const u32 argument = ProcessShadowRam(method, method_argument);
ProcessDirtyRegisters(method, argument);
ProcessMethodCall(method, argument, method_argument, is_last_call);
}
void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
@@ -300,23 +280,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
// Methods after 0xE00 are special, they're actually triggers for some microcode that was
// uploaded to the GPU during initialization.
if (method >= MacroRegistersStart) {
// We're trying to execute a macro
if (executing_macro == 0) {
// A macro call must begin by writing the macro method's register, not its argument.
ASSERT_MSG((method % 2) == 0,
"Can't start macro execution by writing to the ARGS register");
executing_macro = method;
}
for (std::size_t i = 0; i < amount; i++) {
macro_params.push_back(base_start[i]);
}
// Call the macro when there are no more parameters in the command buffer
if (amount == methods_pending) {
CallMacroMethod(executing_macro, macro_params);
macro_params.clear();
}
ProcessMacro(method, base_start, amount, amount == methods_pending);
return;
}
switch (method) {
@@ -335,15 +299,14 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]):
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): {
case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]):
ProcessCBMultiData(method, base_start, amount);
break;
}
default: {
default:
for (std::size_t i = 0; i < amount; i++) {
CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1);
}
}
break;
}
}
+8
View File
@@ -1461,6 +1461,14 @@ public:
private:
void InitializeRegisterDefaults();
void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call);
u32 ProcessShadowRam(u32 method, u32 argument);
void ProcessDirtyRegisters(u32 method, u32 argument);
void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call);
Core::System& system;
MemoryManager& memory_manager;
+88 -96
View File
@@ -32,31 +32,31 @@ struct Register {
constexpr Register() = default;
constexpr Register(u64 value_) : value(value_) {}
constexpr Register(u64 value) : value(value) {}
[[nodiscard]] constexpr operator u64() const {
constexpr operator u64() const {
return value;
}
template <typename T>
[[nodiscard]] constexpr u64 operator-(const T& oth) const {
constexpr u64 operator-(const T& oth) const {
return value - oth;
}
template <typename T>
[[nodiscard]] constexpr u64 operator&(const T& oth) const {
constexpr u64 operator&(const T& oth) const {
return value & oth;
}
[[nodiscard]] constexpr u64 operator&(const Register& oth) const {
constexpr u64 operator&(const Register& oth) const {
return value & oth.value;
}
[[nodiscard]] constexpr u64 operator~() const {
constexpr u64 operator~() const {
return ~value;
}
[[nodiscard]] u64 GetSwizzledIndex(u64 elem) const {
u64 GetSwizzledIndex(u64 elem) const {
elem = (value + elem) & 3;
return (value & ~3) + elem;
}
@@ -75,7 +75,7 @@ enum class AttributeSize : u64 {
union Attribute {
Attribute() = default;
constexpr explicit Attribute(u64 value_) : value(value_) {}
constexpr explicit Attribute(u64 value) : value(value) {}
enum class Index : u64 {
LayerViewportPointSize = 6,
@@ -107,7 +107,7 @@ union Attribute {
BitField<31, 1, u64> patch;
BitField<47, 3, AttributeSize> size;
[[nodiscard]] bool IsPhysical() const {
bool IsPhysical() const {
return patch == 0 && element == 0 && static_cast<u64>(index.Value()) == 0;
}
} fmt20;
@@ -124,7 +124,7 @@ union Attribute {
union Sampler {
Sampler() = default;
constexpr explicit Sampler(u64 value_) : value(value_) {}
constexpr explicit Sampler(u64 value) : value(value) {}
enum class Index : u64 {
Sampler_0 = 8,
@@ -137,7 +137,7 @@ union Sampler {
union Image {
Image() = default;
constexpr explicit Image(u64 value_) : value{value_} {}
constexpr explicit Image(u64 value) : value{value} {}
BitField<36, 13, u64> index;
u64 value;
@@ -505,14 +505,14 @@ struct IpaMode {
IpaInterpMode interpolation_mode;
IpaSampleMode sampling_mode;
[[nodiscard]] bool operator==(const IpaMode& a) const {
bool operator==(const IpaMode& a) const {
return std::tie(interpolation_mode, sampling_mode) ==
std::tie(a.interpolation_mode, a.sampling_mode);
}
[[nodiscard]] bool operator!=(const IpaMode& a) const {
bool operator!=(const IpaMode& a) const {
return !operator==(a);
}
[[nodiscard]] bool operator<(const IpaMode& a) const {
bool operator<(const IpaMode& a) const {
return std::tie(interpolation_mode, sampling_mode) <
std::tie(a.interpolation_mode, a.sampling_mode);
}
@@ -658,10 +658,10 @@ union Instruction {
return *this;
}
constexpr Instruction(u64 value_) : value{value_} {}
constexpr Instruction(u64 value) : value{value} {}
constexpr Instruction(const Instruction& instr) : value(instr.value) {}
[[nodiscard]] constexpr bool Bit(u64 offset) const {
constexpr bool Bit(u64 offset) const {
return ((value >> offset) & 1) != 0;
}
@@ -746,34 +746,34 @@ union Instruction {
BitField<28, 8, u64> imm_lut28;
BitField<48, 8, u64> imm_lut48;
[[nodiscard]] u32 GetImmLut28() const {
u32 GetImmLut28() const {
return static_cast<u32>(imm_lut28);
}
[[nodiscard]] u32 GetImmLut48() const {
u32 GetImmLut48() const {
return static_cast<u32>(imm_lut48);
}
} lop3;
[[nodiscard]] u16 GetImm20_16() const {
u16 GetImm20_16() const {
return static_cast<u16>(imm20_16);
}
[[nodiscard]] u32 GetImm20_19() const {
u32 GetImm20_19() const {
u32 imm{static_cast<u32>(imm20_19)};
imm <<= 12;
imm |= negate_imm ? 0x80000000 : 0;
return imm;
}
[[nodiscard]] u32 GetImm20_32() const {
u32 GetImm20_32() const {
return static_cast<u32>(imm20_32);
}
[[nodiscard]] s32 GetSignedImm20_20() const {
const auto immediate = static_cast<u32>(imm20_19 | (negate_imm << 19));
s32 GetSignedImm20_20() const {
u32 immediate = static_cast<u32>(imm20_19 | (negate_imm << 19));
// Sign extend the 20-bit value.
const auto mask = 1U << (20 - 1);
u32 mask = 1U << (20 - 1);
return static_cast<s32>((immediate ^ mask) - mask);
}
} alu;
@@ -857,7 +857,7 @@ union Instruction {
BitField<56, 1, u64> second_negate;
BitField<30, 9, u64> second;
[[nodiscard]] u32 PackImmediates() const {
u32 PackImmediates() const {
// Immediates are half floats shifted.
constexpr u32 imm_shift = 6;
return static_cast<u32>((first << imm_shift) | (second << (16 + imm_shift)));
@@ -1033,7 +1033,7 @@ union Instruction {
BitField<28, 2, AtomicType> type;
BitField<30, 22, s64> offset;
[[nodiscard]] s32 GetImmediateOffset() const {
s32 GetImmediateOffset() const {
return static_cast<s32>(offset << 2);
}
} atoms;
@@ -1215,7 +1215,7 @@ union Instruction {
BitField<39, 4, u64> rounding;
// H0, H1 extract for F16 missing
BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value
[[nodiscard]] F2fRoundingOp GetRoundingMode() const {
F2fRoundingOp GetRoundingMode() const {
constexpr u64 rounding_mask = 0x0B;
return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask);
}
@@ -1239,15 +1239,15 @@ union Instruction {
BitField<54, 1, u64> aoffi_flag;
BitField<55, 3, TextureProcessMode> process_mode;
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
return ((1ULL << component) & component_mask) != 0;
bool IsComponentEnabled(std::size_t component) const {
return ((1ull << component) & component_mask) != 0;
}
[[nodiscard]] TextureProcessMode GetTextureProcessMode() const {
TextureProcessMode GetTextureProcessMode() const {
return process_mode;
}
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return dc_flag != 0;
@@ -1271,15 +1271,15 @@ union Instruction {
BitField<36, 1, u64> aoffi_flag;
BitField<37, 3, TextureProcessMode> process_mode;
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
bool IsComponentEnabled(std::size_t component) const {
return ((1ULL << component) & component_mask) != 0;
}
[[nodiscard]] TextureProcessMode GetTextureProcessMode() const {
TextureProcessMode GetTextureProcessMode() const {
return process_mode;
}
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return dc_flag != 0;
@@ -1299,7 +1299,7 @@ union Instruction {
BitField<31, 4, u64> component_mask;
BitField<49, 1, u64> nodep_flag;
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NODEP:
return nodep_flag != 0;
@@ -1309,7 +1309,7 @@ union Instruction {
return false;
}
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
bool IsComponentEnabled(std::size_t component) const {
return ((1ULL << component) & component_mask) != 0;
}
} txq;
@@ -1321,11 +1321,11 @@ union Instruction {
BitField<35, 1, u64> ndv_flag;
BitField<49, 1, u64> nodep_flag;
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
return ((1ULL << component) & component_mask) != 0;
bool IsComponentEnabled(std::size_t component) const {
return ((1ull << component) & component_mask) != 0;
}
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return (ndv_flag != 0);
@@ -1347,7 +1347,7 @@ union Instruction {
BitField<54, 2, u64> offset_mode;
BitField<56, 2, u64> component;
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return ndv_flag != 0;
@@ -1373,7 +1373,7 @@ union Instruction {
BitField<33, 2, u64> offset_mode;
BitField<37, 2, u64> component;
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::NDV:
return ndv_flag != 0;
@@ -1399,7 +1399,7 @@ union Instruction {
BitField<52, 2, u64> component;
BitField<55, 1, u64> fp16_flag;
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return dc_flag != 0;
@@ -1422,20 +1422,16 @@ union Instruction {
BitField<53, 4, u64> texture_info;
BitField<59, 1, u64> fp32_flag;
[[nodiscard]] TextureType GetTextureType() const {
TextureType GetTextureType() const {
// The TEXS instruction has a weird encoding for the texture type.
if (texture_info == 0) {
if (texture_info == 0)
return TextureType::Texture1D;
}
if (texture_info >= 1 && texture_info <= 9) {
if (texture_info >= 1 && texture_info <= 9)
return TextureType::Texture2D;
}
if (texture_info >= 10 && texture_info <= 11) {
if (texture_info >= 10 && texture_info <= 11)
return TextureType::Texture3D;
}
if (texture_info >= 12 && texture_info <= 13) {
if (texture_info >= 12 && texture_info <= 13)
return TextureType::TextureCube;
}
LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}",
static_cast<u32>(texture_info.Value()));
@@ -1443,7 +1439,7 @@ union Instruction {
return TextureType::Texture1D;
}
[[nodiscard]] TextureProcessMode GetTextureProcessMode() const {
TextureProcessMode GetTextureProcessMode() const {
switch (texture_info) {
case 0:
case 2:
@@ -1462,7 +1458,7 @@ union Instruction {
return TextureProcessMode::None;
}
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::DC:
return (texture_info >= 4 && texture_info <= 6) || texture_info == 9;
@@ -1474,16 +1470,16 @@ union Instruction {
return false;
}
[[nodiscard]] bool IsArrayTexture() const {
bool IsArrayTexture() const {
// TEXS only supports Texture2D arrays.
return texture_info >= 7 && texture_info <= 9;
}
[[nodiscard]] bool HasTwoDestinations() const {
bool HasTwoDestinations() const {
return gpr28.Value() != Register::ZeroIndex;
}
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
bool IsComponentEnabled(std::size_t component) const {
static constexpr std::array<std::array<u32, 8>, 4> mask_lut{{
{},
{0x1, 0x2, 0x4, 0x8, 0x3, 0x9, 0xa, 0xc},
@@ -1510,7 +1506,7 @@ union Instruction {
BitField<54, 1, u64> cl;
BitField<55, 1, u64> process_mode;
[[nodiscard]] TextureProcessMode GetTextureProcessMode() const {
TextureProcessMode GetTextureProcessMode() const {
return process_mode == 0 ? TextureProcessMode::LZ : TextureProcessMode::LL;
}
} tld;
@@ -1520,7 +1516,7 @@ union Instruction {
BitField<53, 4, u64> texture_info;
BitField<59, 1, u64> fp32_flag;
[[nodiscard]] TextureType GetTextureType() const {
TextureType GetTextureType() const {
// The TLDS instruction has a weird encoding for the texture type.
if (texture_info <= 1) {
return TextureType::Texture1D;
@@ -1539,14 +1535,13 @@ union Instruction {
return TextureType::Texture1D;
}
[[nodiscard]] TextureProcessMode GetTextureProcessMode() const {
if (texture_info == 1 || texture_info == 5 || texture_info == 12) {
TextureProcessMode GetTextureProcessMode() const {
if (texture_info == 1 || texture_info == 5 || texture_info == 12)
return TextureProcessMode::LL;
}
return TextureProcessMode::LZ;
}
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::AOFFI:
return texture_info == 12 || texture_info == 4;
@@ -1560,7 +1555,7 @@ union Instruction {
return false;
}
[[nodiscard]] bool IsArrayTexture() const {
bool IsArrayTexture() const {
// TEXS only supports Texture2D arrays.
return texture_info == 8;
}
@@ -1572,7 +1567,7 @@ union Instruction {
BitField<35, 1, u64> aoffi_flag;
BitField<49, 1, u64> nodep_flag;
[[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const {
bool UsesMiscMode(TextureMiscMode mode) const {
switch (mode) {
case TextureMiscMode::AOFFI:
return aoffi_flag != 0;
@@ -1596,7 +1591,7 @@ union Instruction {
BitField<20, 3, StoreType> store_data_layout;
BitField<20, 4, u64> component_mask_selector;
[[nodiscard]] bool IsComponentEnabled(std::size_t component) const {
bool IsComponentEnabled(std::size_t component) const {
ASSERT(mode == SurfaceDataMode::P);
constexpr u8 R = 0b0001;
constexpr u8 G = 0b0010;
@@ -1609,7 +1604,7 @@ union Instruction {
return std::bitset<4>{mask.at(component_mask_selector)}.test(component);
}
[[nodiscard]] StoreType GetStoreDataLayout() const {
StoreType GetStoreDataLayout() const {
ASSERT(mode == SurfaceDataMode::D_BA);
return store_data_layout;
}
@@ -1627,15 +1622,14 @@ union Instruction {
BitField<20, 24, u64> target;
BitField<5, 1, u64> constant_buffer;
[[nodiscard]] s32 GetBranchTarget() const {
s32 GetBranchTarget() const {
// Sign extend the branch target offset
const auto mask = 1U << (24 - 1);
const auto target_value = static_cast<u32>(target);
constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction));
u32 mask = 1U << (24 - 1);
u32 value = static_cast<u32>(target);
// The branch offset is relative to the next instruction and is stored in bytes, so
// divide it by the size of an instruction and add 1 to it.
return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1;
return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) +
1;
}
} bra;
@@ -1643,15 +1637,14 @@ union Instruction {
BitField<20, 24, u64> target;
BitField<5, 1, u64> constant_buffer;
[[nodiscard]] s32 GetBranchExtend() const {
s32 GetBranchExtend() const {
// Sign extend the branch target offset
const auto mask = 1U << (24 - 1);
const auto target_value = static_cast<u32>(target);
constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction));
u32 mask = 1U << (24 - 1);
u32 value = static_cast<u32>(target);
// The branch offset is relative to the next instruction and is stored in bytes, so
// divide it by the size of an instruction and add 1 to it.
return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1;
return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) +
1;
}
} brx;
@@ -1704,7 +1697,7 @@ union Instruction {
BitField<50, 1, u64> is_op_b_register;
BitField<51, 3, VmnmxOperation> operation;
[[nodiscard]] VmnmxType SourceFormatA() const {
VmnmxType SourceFormatA() const {
switch (src_format_a) {
case 0b11:
return VmnmxType::Bits32;
@@ -1715,7 +1708,7 @@ union Instruction {
}
}
[[nodiscard]] VmnmxType SourceFormatB() const {
VmnmxType SourceFormatB() const {
switch (src_format_b) {
case 0b11:
return VmnmxType::Bits32;
@@ -1746,7 +1739,7 @@ union Instruction {
BitField<20, 14, u64> shifted_offset;
BitField<34, 5, u64> index;
[[nodiscard]] u64 GetOffset() const {
u64 GetOffset() const {
return shifted_offset * 4;
}
} cbuf34;
@@ -1755,7 +1748,7 @@ union Instruction {
BitField<20, 16, s64> offset;
BitField<36, 5, u64> index;
[[nodiscard]] s64 GetOffset() const {
s64 GetOffset() const {
return offset;
}
} cbuf36;
@@ -2004,29 +1997,29 @@ public:
/// Returns whether an opcode has an execution predicate field or not (ie, whether it can be
/// conditionally executed).
[[nodiscard]] static bool IsPredicatedInstruction(Id opcode) {
static bool IsPredicatedInstruction(Id opcode) {
// TODO(Subv): Add the rest of unpredicated instructions.
return opcode != Id::SSY && opcode != Id::PBK;
}
class Matcher {
public:
constexpr Matcher(const char* const name_, u16 mask_, u16 expected_, Id id_, Type type_)
: name{name_}, mask{mask_}, expected{expected_}, id{id_}, type{type_} {}
constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type)
: name{name}, mask{mask}, expected{expected}, id{id}, type{type} {}
[[nodiscard]] constexpr const char* GetName() const {
constexpr const char* GetName() const {
return name;
}
[[nodiscard]] constexpr u16 GetMask() const {
constexpr u16 GetMask() const {
return mask;
}
[[nodiscard]] constexpr Id GetId() const {
constexpr Id GetId() const {
return id;
}
[[nodiscard]] constexpr Type GetType() const {
constexpr Type GetType() const {
return type;
}
@@ -2035,7 +2028,7 @@ public:
* @param instruction The instruction to test
* @returns true if the given instruction matches.
*/
[[nodiscard]] constexpr bool Matches(u16 instruction) const {
constexpr bool Matches(u16 instruction) const {
return (instruction & mask) == expected;
}
@@ -2047,8 +2040,7 @@ public:
Type type;
};
using DecodeResult = std::optional<std::reference_wrapper<const Matcher>>;
[[nodiscard]] static DecodeResult Decode(Instruction instr) {
static std::optional<std::reference_wrapper<const Matcher>> Decode(Instruction instr) {
static const auto table{GetDecodeTable()};
const auto matches_instruction = [instr](const auto& matcher) {
@@ -2070,7 +2062,7 @@ private:
* A '0' in a bitstring indicates that a zero must be present at that bit position.
* A '1' in a bitstring indicates that a one must be present at that bit position.
*/
[[nodiscard]] static constexpr auto GetMaskAndExpect(const char* const bitstring) {
static constexpr auto GetMaskAndExpect(const char* const bitstring) {
u16 mask = 0, expect = 0;
for (std::size_t i = 0; i < opcode_bitsize; i++) {
const std::size_t bit_position = opcode_bitsize - i - 1;
@@ -2092,14 +2084,14 @@ private:
public:
/// Creates a matcher that can match and parse instructions based on bitstring.
[[nodiscard]] static constexpr auto GetMatcher(const char* const bitstring, Id op,
Type type, const char* const name) {
static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type,
const char* const name) {
const auto [mask, expected] = GetMaskAndExpect(bitstring);
return Matcher(name, mask, expected, op, type);
}
};
[[nodiscard]] static std::vector<Matcher> GetDecodeTable() {
static std::vector<Matcher> GetDecodeTable() {
std::vector<Matcher> table = {
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
+9 -17
View File
@@ -35,7 +35,7 @@
#include "core/settings.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "input_common/mouse/mouse_input.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
#include "yuzu/bootmanager.h"
@@ -382,23 +382,19 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
}
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
if (!Settings::values.touchscreen.enabled) {
input_subsystem->GetKeyboard()->PressKey(event->button());
return;
}
// Touch input is handled in TouchBeginEvent
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
return;
}
auto pos = event->pos();
const auto [x, y] = ScaleTouch(pos);
input_subsystem->GetMouse()->PressButton(x, y, event->button());
if (event->button() == Qt::LeftButton) {
const auto [x, y] = ScaleTouch(pos);
this->TouchPressed(x, y);
} else if (event->button() == Qt::RightButton) {
input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y());
}
QWidget::mousePressEvent(event);
}
@@ -410,26 +406,22 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
auto pos = event->pos();
const auto [x, y] = ScaleTouch(pos);
input_subsystem->GetMouse()->MouseMove(x, y);
this->TouchMoved(x, y);
input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y());
QWidget::mouseMoveEvent(event);
}
void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
if (!Settings::values.touchscreen.enabled) {
input_subsystem->GetKeyboard()->ReleaseKey(event->button());
return;
}
// Touch input is handled in TouchEndEvent
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
return;
}
input_subsystem->GetMouse()->ReleaseButton(event->button());
if (event->button() == Qt::LeftButton) {
this->TouchReleased();
} else if (event->button() == Qt::RightButton) {
input_subsystem->GetMotionEmu()->EndTilt();
}
}
@@ -19,6 +19,7 @@
#include "core/hle/service/sm/sm.h"
#include "input_common/gcadapter/gc_poller.h"
#include "input_common/main.h"
#include "input_common/mouse/mouse_poller.h"
#include "input_common/udp/udp.h"
#include "ui_configure_input_player.h"
#include "yuzu/configuration/config.h"
@@ -186,6 +187,14 @@ QString ButtonToText(const Common::ParamPackage& param) {
return {};
}
if (param.Get("engine", "") == "mouse") {
if (param.Has("button")) {
const QString button_str = QString::number(int(param.Get("button", 0)));
return QObject::tr("Click %1").arg(button_str);
}
return GetKeyName(param.Get("code", 0));
}
return QObject::tr("[unknown]");
}
@@ -237,6 +246,26 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
return {};
}
if (param.Get("engine", "") == "mouse") {
if (dir == "modifier") {
return QObject::tr("[unused]");
}
if (dir == "left" || dir == "right") {
const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
return QObject::tr("Mouse %1").arg(axis_x_str);
}
if (dir == "up" || dir == "down") {
const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
return QObject::tr("Mouse %1").arg(axis_y_str);
}
return {};
}
return QObject::tr("[unknown]");
}
} // namespace
@@ -532,6 +561,34 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
return;
}
}
if (input_subsystem->GetMouseButtons()->IsPolling()) {
params = input_subsystem->GetMouseButtons()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
SetPollingResult(params, false);
return;
}
}
if (input_subsystem->GetMouseAnalogs()->IsPolling()) {
params = input_subsystem->GetMouseAnalogs()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
SetPollingResult(params, false);
return;
}
}
if (input_subsystem->GetMouseMotions()->IsPolling()) {
params = input_subsystem->GetMouseMotions()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
SetPollingResult(params, false);
return;
}
}
if (input_subsystem->GetMouseTouch()->IsPolling()) {
params = input_subsystem->GetMouseTouch()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
SetPollingResult(params, false);
return;
}
}
for (auto& poller : device_pollers) {
params = poller->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
@@ -809,8 +866,9 @@ void ConfigureInputPlayer::UpdateUI() {
int slider_value;
auto& param = analogs_param[analog_id];
const bool is_controller =
param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad";
const bool is_controller = param.Get("engine", "") == "sdl" ||
param.Get("engine", "") == "gcpad" ||
param.Get("engine", "") == "mouse";
if (is_controller) {
if (!param.Has("deadzone")) {
@@ -1050,6 +1108,16 @@ void ConfigureInputPlayer::HandleClick(
input_subsystem->GetUDPMotions()->BeginConfiguration();
}
if (type == InputCommon::Polling::DeviceType::Button) {
input_subsystem->GetMouseButtons()->BeginConfiguration();
} else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
input_subsystem->GetMouseAnalogs()->BeginConfiguration();
} else if (type == InputCommon::Polling::DeviceType::Motion) {
input_subsystem->GetMouseMotions()->BeginConfiguration();
} else {
input_subsystem->GetMouseTouch()->BeginConfiguration();
}
timeout_timer->start(2500); // Cancel after 2.5 seconds
poll_timer->start(50); // Check for new inputs every 50ms
}
@@ -1069,6 +1137,11 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
input_subsystem->GetUDPMotions()->EndConfiguration();
input_subsystem->GetMouseButtons()->EndConfiguration();
input_subsystem->GetMouseAnalogs()->EndConfiguration();
input_subsystem->GetMouseMotions()->EndConfiguration();
input_subsystem->GetMouseTouch()->EndConfiguration();
if (!abort) {
(*input_setter)(params);
}
@@ -1100,15 +1173,7 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
return;
}
if (want_keyboard_mouse) {
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
false);
} else {
// We don't want any mouse buttons, so don't stop polling
return;
}
SetPollingResult({}, true);
input_subsystem->GetMouse()->PressButton(0, 0, event->button());
}
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
+4 -4
View File
@@ -9,7 +9,7 @@
#include "core/perf_stats.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "input_common/mouse/mouse_input.h"
#include "input_common/sdl/sdl.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
@@ -30,7 +30,7 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
input_subsystem->GetMotionEmu()->Tilt(x, y);
input_subsystem->GetMouse()->MouseMove(x, y);
}
void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
@@ -42,9 +42,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
}
} else if (button == SDL_BUTTON_RIGHT) {
if (state == SDL_PRESSED) {
input_subsystem->GetMotionEmu()->BeginTilt(x, y);
input_subsystem->GetMouse()->PressButton(x, y, button);
} else {
input_subsystem->GetMotionEmu()->EndTilt();
input_subsystem->GetMouse()->ReleaseButton(button);
}
}
}
@@ -17,7 +17,6 @@
#include "core/settings.h"
#include "input_common/keyboard.h"
#include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "video_core/renderer_base.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h"