summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/vi
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp34
-rw-r--r--src/core/hle/service/vi/display/vi_display.h21
-rw-r--r--src/core/hle/service/vi/vi.cpp41
-rw-r--r--src/core/hle/service/vi/vi_results.h15
4 files changed, 78 insertions, 33 deletions
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index b34febb50..8ef74f1f0 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -10,8 +10,8 @@
#include "core/core.h"
#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/nvdrv/core/container.h"
#include "core/hle/service/nvflinger/buffer_item_consumer.h"
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvflinger/buffer_queue_core.h"
@@ -19,6 +19,7 @@
#include "core/hle/service/nvflinger/hos_binder_driver_server.h"
#include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h"
+#include "core/hle/service/vi/vi_results.h"
namespace Service::VI {
@@ -28,11 +29,13 @@ struct BufferQueue {
std::unique_ptr<android::BufferQueueConsumer> consumer;
};
-static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context) {
+static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
+ Service::Nvidia::NvCore::NvMap& nvmap) {
auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
- return {buffer_queue_core,
- std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core),
- std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
+ return {
+ buffer_queue_core,
+ std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
+ std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)};
}
Display::Display(u64 id, std::string name_,
@@ -55,18 +58,29 @@ const Layer& Display::GetLayer(std::size_t index) const {
return *layers.at(index);
}
-Kernel::KReadableEvent& Display::GetVSyncEvent() {
- return vsync_event->GetReadableEvent();
+ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() {
+ if (got_vsync_event) {
+ return ResultPermissionDenied;
+ }
+
+ got_vsync_event = true;
+
+ return GetVSyncEventUnchecked();
+}
+
+Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
+ return &vsync_event->GetReadableEvent();
}
void Display::SignalVSyncEvent() {
- vsync_event->GetWritableEvent().Signal();
+ vsync_event->Signal();
}
-void Display::CreateLayer(u64 layer_id, u32 binder_id) {
+void Display::CreateLayer(u64 layer_id, u32 binder_id,
+ Service::Nvidia::NvCore::Container& nv_core) {
ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
- auto [core, producer, consumer] = CreateBufferQueue(service_context);
+ auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
buffer_item_consumer->Connect(false);
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 3838bb599..33d5f398c 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -9,6 +9,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "core/hle/result.h"
namespace Kernel {
class KEvent;
@@ -26,6 +27,11 @@ namespace Service::NVFlinger {
class HosBinderDriverServer;
}
+namespace Service::Nvidia::NvCore {
+class Container;
+class NvMap;
+} // namespace Service::Nvidia::NvCore
+
namespace Service::VI {
class Layer;
@@ -73,8 +79,16 @@ public:
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.
void SignalVSyncEvent();
@@ -84,7 +98,7 @@ public:
/// @param layer_id The ID to assign to the created layer.
/// @param binder_id The ID assigned to the buffer queue.
///
- void CreateLayer(u64 layer_id, u32 binder_id);
+ void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
/// Closes and removes a layer from this display with the given ID.
///
@@ -118,6 +132,7 @@ private:
std::vector<std::unique_ptr<Layer>> layers;
Kernel::KEvent* vsync_event{};
+ bool got_vsync_event{false};
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 546879648..9c917cacf 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -29,16 +29,12 @@
#include "core/hle/service/service.h"
#include "core/hle/service/vi/vi.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_u.h"
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 {
/// The name of this particular display.
char display_name[0x40]{"Default"};
@@ -62,6 +58,7 @@ static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
class NativeWindow final {
public:
constexpr explicit NativeWindow(u32 id_) : id{id_} {}
+ constexpr explicit NativeWindow(const NativeWindow& other) = default;
private:
const u32 magic = 2;
@@ -348,7 +345,7 @@ private:
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -498,7 +495,7 @@ private:
if (!display_id) {
LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -554,14 +551,14 @@ private:
if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
- rb.Push(ERR_OPERATION_FAILED);
+ rb.Push(ResultOperationFailed);
return;
}
if (scaling_mode != NintendoScaleMode::ScaleToWindow &&
scaling_mode != NintendoScaleMode::PreserveAspectRatio) {
LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
- rb.Push(ERR_UNSUPPORTED);
+ rb.Push(ResultNotSupported);
return;
}
@@ -594,7 +591,7 @@ private:
if (!display_id) {
LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -602,7 +599,7 @@ private:
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -640,7 +637,7 @@ private:
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -648,7 +645,7 @@ private:
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(ResultNotFound);
return;
}
@@ -675,19 +672,23 @@ private:
IPC::RequestParser rp{ctx};
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);
- if (!vsync_event) {
- LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
+ if (vsync_event.Failed()) {
+ 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};
- rb.Push(ERR_NOT_FOUND);
+ rb.Push(result);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
- rb.PushCopyObjects(vsync_event);
+ rb.PushCopyObjects(*vsync_event);
}
void ConvertScalingMode(Kernel::HLERequestContext& ctx) {
@@ -764,7 +765,7 @@ private:
return ConvertedScaleMode::PreserveAspectRatio;
default:
LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
- return ERR_OPERATION_FAILED;
+ return ResultOperationFailed;
}
}
@@ -794,7 +795,7 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System&
if (!IsValidServiceAccess(permission, policy)) {
LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ERR_PERMISSION_DENIED);
+ rb.Push(ResultPermissionDenied);
return;
}
diff --git a/src/core/hle/service/vi/vi_results.h b/src/core/hle/service/vi/vi_results.h
new file mode 100644
index 000000000..22bac799f
--- /dev/null
+++ b/src/core/hle/service/vi/vi_results.h
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#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