Compare commits

..

3 Commits

Author SHA1 Message Date
bunnei
e05bfd2f54 core: hle: service: buffer_queue: Improve management of KEvent. 2021-09-04 22:25:46 -07:00
bunnei
d9ce179ec2 Merge pull request #6968 from bunnei/nvflinger-event
core: hle: service: nvflinger/vi: Improve management of KEvent.
2021-09-04 22:25:20 -07:00
bunnei
fb3e9314b9 core: hle: service: nvflinger/vi: Improve management of KEvent. 2021-09-03 21:53:00 -07:00
11 changed files with 85 additions and 63 deletions

View File

@@ -9,17 +9,20 @@
#include "core/core.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service::NVFlinger {
BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_)
: id(id_), layer_id(layer_id_), buffer_wait_event{kernel} {
Kernel::KAutoObject::Create(std::addressof(buffer_wait_event));
buffer_wait_event.Initialize("BufferQueue:WaitEvent");
BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
KernelHelpers::ServiceContext& service_context_)
: id(id_), layer_id(layer_id_), service_context{service_context_} {
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
}
BufferQueue::~BufferQueue() = default;
BufferQueue::~BufferQueue() {
service_context.CloseEvent(buffer_wait_event);
}
void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
ASSERT(slot < buffer_slots);
@@ -41,7 +44,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
.multi_fence = {},
};
buffer_wait_event.GetWritableEvent().Signal();
buffer_wait_event->GetWritableEvent().Signal();
}
std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +122,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
}
free_buffers_condition.notify_one();
buffer_wait_event.GetWritableEvent().Signal();
buffer_wait_event->GetWritableEvent().Signal();
}
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +157,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
}
free_buffers_condition.notify_one();
buffer_wait_event.GetWritableEvent().Signal();
buffer_wait_event->GetWritableEvent().Signal();
}
void BufferQueue::Connect() {
@@ -169,7 +172,7 @@ void BufferQueue::Disconnect() {
std::unique_lock lock{queue_sequence_mutex};
queue_sequence.clear();
}
buffer_wait_event.GetWritableEvent().Signal();
buffer_wait_event->GetWritableEvent().Signal();
is_connect = false;
free_buffers_condition.notify_one();
}
@@ -189,11 +192,11 @@ u32 BufferQueue::Query(QueryType type) {
}
Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() {
return buffer_wait_event.GetWritableEvent();
return buffer_wait_event->GetWritableEvent();
}
Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() {
return buffer_wait_event.GetReadableEvent();
return buffer_wait_event->GetReadableEvent();
}
} // namespace Service::NVFlinger

View File

@@ -24,6 +24,10 @@ class KReadableEvent;
class KWritableEvent;
} // namespace Kernel
namespace Service::KernelHelpers {
class ServiceContext;
} // namespace Service::KernelHelpers
namespace Service::NVFlinger {
constexpr u32 buffer_slots = 0x40;
@@ -54,7 +58,8 @@ public:
NativeWindowFormat = 2,
};
explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_);
explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
KernelHelpers::ServiceContext& service_context_);
~BufferQueue();
enum class BufferTransformFlags : u32 {
@@ -130,12 +135,14 @@ private:
std::list<u32> free_buffers;
std::array<Buffer, buffer_slots> buffers;
std::list<u32> queue_sequence;
Kernel::KEvent buffer_wait_event;
Kernel::KEvent* buffer_wait_event{};
std::mutex free_buffers_mutex;
std::condition_variable free_buffers_condition;
std::mutex queue_sequence_mutex;
KernelHelpers::ServiceContext& service_context;
};
} // namespace Service::NVFlinger

View File

@@ -61,12 +61,13 @@ void NVFlinger::SplitVSync() {
}
}
NVFlinger::NVFlinger(Core::System& system_) : system(system_) {
displays.emplace_back(0, "Default", system);
displays.emplace_back(1, "External", system);
displays.emplace_back(2, "Edid", system);
displays.emplace_back(3, "Internal", system);
displays.emplace_back(4, "Null", system);
NVFlinger::NVFlinger(Core::System& system_)
: system(system_), service_context(system_, "nvflinger") {
displays.emplace_back(0, "Default", service_context, system);
displays.emplace_back(1, "External", service_context, system);
displays.emplace_back(2, "Edid", service_context, system);
displays.emplace_back(3, "Internal", service_context, system);
displays.emplace_back(4, "Null", service_context, system);
guard = std::make_shared<std::mutex>();
// Schedule the screen composition events
@@ -146,7 +147,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
const u32 buffer_queue_id = next_buffer_queue_id++;
buffer_queues.emplace_back(
std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id));
std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id, service_context));
display.CreateLayer(layer_id, *buffer_queues.back());
}

View File

@@ -15,6 +15,7 @@
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/kernel_helpers.h"
namespace Common {
class Event;
@@ -135,6 +136,8 @@ private:
std::unique_ptr<std::thread> vsync_thread;
std::unique_ptr<Common::Event> wait_event;
std::atomic<bool> is_running{};
KernelHelpers::ServiceContext service_context;
};
} // namespace Service::NVFlinger

View File

@@ -12,18 +12,21 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h"
namespace Service::VI {
Display::Display(u64 id, std::string name_, Core::System& system)
: display_id{id}, name{std::move(name_)}, vsync_event{system.Kernel()} {
Kernel::KAutoObject::Create(std::addressof(vsync_event));
vsync_event.Initialize(fmt::format("Display VSync Event {}", id));
Display::Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_,
Core::System& system_)
: display_id{id}, name{std::move(name_)}, service_context{service_context_} {
vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id));
}
Display::~Display() = default;
Display::~Display() {
service_context.CloseEvent(vsync_event);
}
Layer& Display::GetLayer(std::size_t index) {
return *layers.at(index);
@@ -34,11 +37,11 @@ const Layer& Display::GetLayer(std::size_t index) const {
}
Kernel::KReadableEvent& Display::GetVSyncEvent() {
return vsync_event.GetReadableEvent();
return vsync_event->GetReadableEvent();
}
void Display::SignalVSyncEvent() {
vsync_event.GetWritableEvent().Signal();
vsync_event->GetWritableEvent().Signal();
}
void Display::CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue) {

View File

@@ -18,6 +18,9 @@ class KEvent;
namespace Service::NVFlinger {
class BufferQueue;
}
namespace Service::KernelHelpers {
class ServiceContext;
} // namespace Service::KernelHelpers
namespace Service::VI {
@@ -31,10 +34,13 @@ class Display {
public:
/// Constructs a display with a given unique ID and name.
///
/// @param id The unique ID for this display.
/// @param id The unique ID for this display.
/// @param service_context_ The ServiceContext for the owning service.
/// @param name_ The name for this display.
/// @param system_ The global system instance.
///
Display(u64 id, std::string name_, Core::System& system);
Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_,
Core::System& system_);
~Display();
/// Gets the unique ID assigned to this display.
@@ -98,9 +104,10 @@ public:
private:
u64 display_id;
std::string name;
KernelHelpers::ServiceContext& service_context;
std::vector<std::shared_ptr<Layer>> layers;
Kernel::KEvent vsync_event;
Kernel::KEvent* vsync_event{};
};
} // namespace Service::VI

View File

@@ -165,7 +165,7 @@ public:
}
std::tuple<float, float> GetStatus() const override {
if (Settings::values.emulate_analog_keyboard.GetValue()) {
if (Settings::values.emulate_analog_keyboard) {
const auto now = std::chrono::steady_clock::now();
float angle_ = GetAngle(now);
return std::make_tuple(std::cos(angle_) * amplitude, std::sin(angle_) * amplitude);

View File

@@ -31,7 +31,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
info.motion.UpdateOrientation(update_time * 1000);
info.tilt_speed = 0;
info.data.motion = info.motion.GetMotion();
if (Settings::values.mouse_panning.GetValue()) {
if (Settings::values.mouse_panning) {
info.last_mouse_change *= 0.96f;
info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x),
static_cast<int>(16 * -info.last_mouse_change.y)};
@@ -74,7 +74,7 @@ void Mouse::PressButton(int x, int y, MouseButton button_) {
void Mouse::StopPanning() {
for (MouseInfo& info : mouse_info) {
if (Settings::values.mouse_panning.GetValue()) {
if (Settings::values.mouse_panning) {
info.data.axis = {};
info.tilt_speed = 0;
info.last_mouse_change = {};
@@ -84,7 +84,7 @@ void Mouse::StopPanning() {
void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
for (MouseInfo& info : mouse_info) {
if (Settings::values.mouse_panning.GetValue()) {
if (Settings::values.mouse_panning) {
auto mouse_change =
(Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
mouse_panning_timout = 0;

View File

@@ -201,7 +201,7 @@ bool Client::DeviceConnected(std::size_t pad) const {
void Client::ReloadSockets() {
Reset();
std::stringstream servers_ss(Settings::values.udp_input_servers.GetValue());
std::stringstream servers_ss(static_cast<std::string>(Settings::values.udp_input_servers));
std::string server_token;
std::size_t client = 0;
while (std::getline(servers_ss, server_token, ',')) {

View File

@@ -130,7 +130,7 @@ public:
format.setVersion(4, 6);
format.setProfile(QSurfaceFormat::CompatibilityProfile);
format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
if (Settings::values.renderer_debug.GetValue()) {
if (Settings::values.renderer_debug) {
format.setOption(QSurfaceFormat::FormatOption::DebugContext);
}
// TODO: expose a setting for buffer value (ie default/single/double/triple)
@@ -440,7 +440,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y);
this->TouchMoved(x, y, 0);
if (Settings::values.mouse_panning.GetValue()) {
if (Settings::values.mouse_panning) {
QCursor::setPos(mapToGlobal({center_x, center_y}));
}
@@ -756,7 +756,7 @@ void GRenderWindow::showEvent(QShowEvent* event) {
bool GRenderWindow::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::HoverMove) {
if (Settings::values.mouse_panning.GetValue()) {
if (Settings::values.mouse_panning) {
auto* hover_event = static_cast<QMouseEvent*>(event);
mouseMoveEvent(hover_event);
return false;

View File

@@ -161,14 +161,14 @@ void GMainWindow::ShowTelemetryCallout() {
return;
}
UISettings::values.callout_flags.SetValue(UISettings::values.callout_flags.GetValue() |
static_cast<uint32_t>(CalloutFlag::Telemetry));
UISettings::values.callout_flags =
UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry);
const QString telemetry_message =
tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous "
"data is collected</a> to help improve yuzu. "
"<br/><br/>Would you like to share your usage data with us?");
if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) {
Settings::values.enable_telemetry.SetValue(false);
Settings::values.enable_telemetry = false;
Core::System::GetInstance().ApplySettings();
}
}
@@ -328,7 +328,7 @@ GMainWindow::GMainWindow()
continue;
}
Settings::values.current_user.SetValue(static_cast<s32>(selected_user));
Settings::values.current_user = static_cast<s32>(selected_user);
continue;
}
@@ -998,9 +998,8 @@ void GMainWindow::InitializeHotkeys() {
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
});
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
&QShortcut::activated, this, [] {
Settings::values.audio_muted.SetValue(!Settings::values.audio_muted.GetValue());
});
&QShortcut::activated, this,
[] { Settings::values.audio_muted = !Settings::values.audio_muted; });
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Framerate Limit"), this),
&QShortcut::activated, this, [] {
Settings::values.disable_fps_limit.SetValue(
@@ -1008,8 +1007,8 @@ void GMainWindow::InitializeHotkeys() {
});
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this),
&QShortcut::activated, this, [&] {
Settings::values.mouse_panning.SetValue(!Settings::values.mouse_panning.GetValue());
if (Settings::values.mouse_panning.GetValue()) {
Settings::values.mouse_panning = !Settings::values.mouse_panning;
if (Settings::values.mouse_panning) {
render_window->installEventFilter(render_window);
render_window->setAttribute(Qt::WA_Hover, true);
}
@@ -1057,7 +1056,7 @@ void GMainWindow::RestoreUIState() {
}
void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
if (!UISettings::values.pause_when_in_background.GetValue()) {
if (!UISettings::values.pause_when_in_background) {
return;
}
if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive &&
@@ -1224,8 +1223,8 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
if (result == Core::System::ResultStatus::Success &&
system.GetAppLoader().GetFileType() == Loader::FileType::DeconstructedRomDirectory &&
drd_callout) {
UISettings::values.callout_flags.SetValue(UISettings::values.callout_flags.GetValue() |
static_cast<u32>(CalloutFlag::DRDDeprecation));
UISettings::values.callout_flags = UISettings::values.callout_flags.GetValue() |
static_cast<u32>(CalloutFlag::DRDDeprecation);
QMessageBox::warning(
this, tr("Warning Outdated Game Format"),
tr("You are using the deconstructed ROM directory format for this game, which is an "
@@ -1300,7 +1299,7 @@ void GMainWindow::SelectAndSetCurrentUser() {
return;
}
Settings::values.current_user.SetValue(dialog.GetIndex());
Settings::values.current_user = dialog.GetIndex();
}
void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
@@ -1338,7 +1337,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
Settings::LogSettings();
if (UISettings::values.select_user_on_boot.GetValue()) {
if (UISettings::values.select_user_on_boot) {
SelectAndSetCurrentUser();
}
@@ -1375,12 +1374,12 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
status_bar_update_timer.start(500);
renderer_status_button->setDisabled(true);
if (UISettings::values.hide_mouse.GetValue() || Settings::values.mouse_panning.GetValue()) {
if (UISettings::values.hide_mouse || Settings::values.mouse_panning) {
render_window->installEventFilter(render_window);
render_window->setAttribute(Qt::WA_Hover, true);
}
if (UISettings::values.hide_mouse.GetValue()) {
if (UISettings::values.hide_mouse) {
mouse_hide_timer.start();
}
@@ -2683,8 +2682,7 @@ void GMainWindow::OnConfigure() {
config->Save();
if ((UISettings::values.hide_mouse.GetValue() || Settings::values.mouse_panning.GetValue()) &&
emulation_running) {
if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) {
render_window->installEventFilter(render_window);
render_window->setAttribute(Qt::WA_Hover, true);
} else {
@@ -2692,7 +2690,7 @@ void GMainWindow::OnConfigure() {
render_window->setAttribute(Qt::WA_Hover, false);
}
if (UISettings::values.hide_mouse.GetValue()) {
if (UISettings::values.hide_mouse) {
mouse_hide_timer.start();
}
@@ -2815,7 +2813,7 @@ void GMainWindow::OnCaptureScreenshot() {
}
#ifdef _WIN32
if (UISettings::values.enable_screenshot_save_as.GetValue()) {
if (UISettings::values.enable_screenshot_save_as) {
OnPauseGame();
filename = QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), filename,
tr("PNG Image (*.png)"));
@@ -2900,7 +2898,7 @@ void GMainWindow::UpdateStatusBar() {
} else {
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
}
if (Settings::values.disable_fps_limit.GetValue()) {
if (Settings::values.disable_fps_limit) {
game_fps_label->setText(
tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
} else {
@@ -2963,7 +2961,7 @@ void GMainWindow::UpdateUISettings() {
}
void GMainWindow::HideMouseCursor() {
if (emu_thread == nullptr && UISettings::values.hide_mouse.GetValue()) {
if (emu_thread == nullptr && UISettings::values.hide_mouse) {
mouse_hide_timer.stop();
ShowMouseCursor();
return;
@@ -2973,13 +2971,13 @@ void GMainWindow::HideMouseCursor() {
void GMainWindow::ShowMouseCursor() {
render_window->unsetCursor();
if (emu_thread != nullptr && UISettings::values.hide_mouse.GetValue()) {
if (emu_thread != nullptr && UISettings::values.hide_mouse) {
mouse_hide_timer.start();
}
}
void GMainWindow::OnMouseActivity() {
if (!Settings::values.mouse_panning.GetValue()) {
if (!Settings::values.mouse_panning) {
ShowMouseCursor();
}
}
@@ -3176,7 +3174,7 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
}
bool GMainWindow::ConfirmClose() {
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing.GetValue())
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
return true;
QMessageBox::StandardButton answer =