Merge pull request #8992 from Morph1984/vi-vsync-event

service: vi: Retrieve vsync event once per display
This commit is contained in:
bunnei 2022-10-02 03:02:59 -07:00 committed by GitHub
commit 80a3a73123
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 29 deletions

View file

@ -22,6 +22,7 @@
#include "core/hle/service/nvflinger/ui/graphic_buffer.h" #include "core/hle/service/nvflinger/ui/graphic_buffer.h"
#include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h" #include "core/hle/service/vi/layer/vi_layer.h"
#include "core/hle/service/vi/vi_results.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
namespace Service::NVFlinger { namespace Service::NVFlinger {
@ -163,15 +164,15 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
return layer->GetBinderId(); return layer->GetBinderId();
} }
Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) { ResultVal<Kernel::KReadableEvent*> NVFlinger::FindVsyncEvent(u64 display_id) {
const auto lock_guard = Lock(); const auto lock_guard = Lock();
auto* const display = FindDisplay(display_id); auto* const display = FindDisplay(display_id);
if (display == nullptr) { if (display == nullptr) {
return nullptr; return VI::ResultNotFound;
} }
return &display->GetVSyncEvent(); return display->GetVSyncEvent();
} }
VI::Display* NVFlinger::FindDisplay(u64 display_id) { VI::Display* NVFlinger::FindDisplay(u64 display_id) {

View file

@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/result.h"
#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/kernel_helpers.h"
namespace Common { namespace Common {
@ -71,8 +72,9 @@ public:
/// Gets the vsync event for the specified display. /// Gets the vsync event for the specified display.
/// ///
/// If an invalid display ID is provided, then nullptr is returned. /// If an invalid display ID is provided, then VI::ResultNotFound is returned.
[[nodiscard]] Kernel::KReadableEvent* FindVsyncEvent(u64 display_id); /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
[[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id);
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
/// finished. /// finished.

View file

@ -19,6 +19,7 @@
#include "core/hle/service/nvflinger/hos_binder_driver_server.h" #include "core/hle/service/nvflinger/hos_binder_driver_server.h"
#include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h" #include "core/hle/service/vi/layer/vi_layer.h"
#include "core/hle/service/vi/vi_results.h"
namespace Service::VI { namespace Service::VI {
@ -55,8 +56,18 @@ const Layer& Display::GetLayer(std::size_t index) const {
return *layers.at(index); return *layers.at(index);
} }
Kernel::KReadableEvent& Display::GetVSyncEvent() { ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() {
return vsync_event->GetReadableEvent(); if (got_vsync_event) {
return ResultPermissionDenied;
}
got_vsync_event = true;
return GetVSyncEventUnchecked();
}
Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
return &vsync_event->GetReadableEvent();
} }
void Display::SignalVSyncEvent() { void Display::SignalVSyncEvent() {

View file

@ -9,6 +9,7 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/result.h"
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
@ -73,8 +74,16 @@ public:
return layers.size(); return layers.size();
} }
/// Gets the readable vsync event. /**
Kernel::KReadableEvent& GetVSyncEvent(); * Gets the internal vsync event.
*
* @returns The internal Vsync event if it has not yet been retrieved,
* VI::ResultPermissionDenied otherwise.
*/
[[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent();
/// Gets the internal vsync event.
Kernel::KReadableEvent* GetVSyncEventUnchecked();
/// Signals the internal vsync event. /// Signals the internal vsync event.
void SignalVSyncEvent(); void SignalVSyncEvent();
@ -118,6 +127,7 @@ private:
std::vector<std::unique_ptr<Layer>> layers; std::vector<std::unique_ptr<Layer>> layers;
Kernel::KEvent* vsync_event{}; Kernel::KEvent* vsync_event{};
bool got_vsync_event{false};
}; };
} // namespace Service::VI } // namespace Service::VI

View file

@ -29,16 +29,12 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi.h"
#include "core/hle/service/vi/vi_m.h" #include "core/hle/service/vi/vi_m.h"
#include "core/hle/service/vi/vi_results.h"
#include "core/hle/service/vi/vi_s.h" #include "core/hle/service/vi/vi_s.h"
#include "core/hle/service/vi/vi_u.h" #include "core/hle/service/vi/vi_u.h"
namespace Service::VI { namespace Service::VI {
constexpr Result ERR_OPERATION_FAILED{ErrorModule::VI, 1};
constexpr Result ERR_PERMISSION_DENIED{ErrorModule::VI, 5};
constexpr Result ERR_UNSUPPORTED{ErrorModule::VI, 6};
constexpr Result ERR_NOT_FOUND{ErrorModule::VI, 7};
struct DisplayInfo { struct DisplayInfo {
/// The name of this particular display. /// The name of this particular display.
char display_name[0x40]{"Default"}; char display_name[0x40]{"Default"};
@ -348,7 +344,7 @@ private:
if (!layer_id) { if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -498,7 +494,7 @@ private:
if (!display_id) { if (!display_id) {
LOG_ERROR(Service_VI, "Display not found! display_name={}", name); LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -554,14 +550,14 @@ private:
if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
LOG_ERROR(Service_VI, "Invalid scaling mode provided."); LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
rb.Push(ERR_OPERATION_FAILED); rb.Push(ResultOperationFailed);
return; return;
} }
if (scaling_mode != NintendoScaleMode::ScaleToWindow && if (scaling_mode != NintendoScaleMode::ScaleToWindow &&
scaling_mode != NintendoScaleMode::PreserveAspectRatio) { scaling_mode != NintendoScaleMode::PreserveAspectRatio) {
LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
rb.Push(ERR_UNSUPPORTED); rb.Push(ResultNotSupported);
return; return;
} }
@ -594,7 +590,7 @@ private:
if (!display_id) { if (!display_id) {
LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -602,7 +598,7 @@ private:
if (!buffer_queue_id) { if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -640,7 +636,7 @@ private:
if (!layer_id) { if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -648,7 +644,7 @@ private:
if (!buffer_queue_id) { if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(ResultNotFound);
return; return;
} }
@ -675,19 +671,23 @@ private:
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u64 display_id = rp.Pop<u64>(); const u64 display_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
if (!vsync_event) { if (vsync_event.Failed()) {
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); const auto result = vsync_event.Code();
if (result == ResultNotFound) {
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
}
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_FOUND); rb.Push(result);
return; return;
} }
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushCopyObjects(vsync_event); rb.PushCopyObjects(*vsync_event);
} }
void ConvertScalingMode(Kernel::HLERequestContext& ctx) { void ConvertScalingMode(Kernel::HLERequestContext& ctx) {
@ -764,7 +764,7 @@ private:
return ConvertedScaleMode::PreserveAspectRatio; return ConvertedScaleMode::PreserveAspectRatio;
default: default:
LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
return ERR_OPERATION_FAILED; return ResultOperationFailed;
} }
} }
@ -794,7 +794,7 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System&
if (!IsValidServiceAccess(permission, policy)) { if (!IsValidServiceAccess(permission, policy)) {
LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_PERMISSION_DENIED); rb.Push(ResultPermissionDenied);
return; return;
} }

View file

@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/result.h"
namespace Service::VI {
constexpr Result ResultOperationFailed{ErrorModule::VI, 1};
constexpr Result ResultPermissionDenied{ErrorModule::VI, 5};
constexpr Result ResultNotSupported{ErrorModule::VI, 6};
constexpr Result ResultNotFound{ErrorModule::VI, 7};
} // namespace Service::VI