Compare commits

..

26 Commits

Author SHA1 Message Date
Liam
23f30d1b65 renderer_opengl: isolate core presentation code 2024-01-14 22:19:46 -05:00
Liam
cc86efff36 video_core: simplify accelerated surface fetch and crop handling between APIs 2024-01-11 23:05:00 -05:00
Charles Lombardo
a4d90a9a64 Merge pull request #12653 from liamwhite/once-more
ci: fix file mode check in format script
2024-01-11 19:58:41 -05:00
Liam
84787a2ada ci: fix file mode check in format script 2024-01-11 18:57:07 -05:00
Charles Lombardo
6533dfd7ce Merge pull request #12639 from liamwhite/format-oops
ci: fix format task
2024-01-10 12:44:07 -05:00
Liam
e11a3414ae ci: fix format task 2024-01-10 11:52:58 -05:00
liamwhite
4fdc900581 Merge pull request #12634 from lat9nq/apple-intl-2
externals: Update txdb_to_nx
2024-01-09 18:42:57 -05:00
lat9nq
d99830b59c externals: Update txdb_to_nx
Includes a fix lat9nq/tzdb_to_nx@1e82342 that fixes a build issue on Mac OS.
2024-01-09 17:29:38 -05:00
Narr the Reg
23c11e50f9 Merge pull request #12609 from liamwhite/wrong-name-again
vi: minor cleanups
2024-01-09 11:15:56 -06:00
liamwhite
5fde5e62a8 Merge pull request #12622 from liamwhite/format
ci: make verify format workflow output more helpful
2024-01-09 07:31:34 -05:00
Viktor Szépe
f124461674 Fix typos in src/core (#12625)
* Fix typos in src/core

* Fix typo correction

* Fix indentation of MemoryStateNames

* Fix indent
2024-01-08 13:31:48 -06:00
Liam
30743eff56 ci: make verify format workflow output more helpful 2024-01-08 09:52:25 -05:00
Liam
4f83b00f6f general: fix trailing whitespace 2024-01-08 09:34:32 -05:00
Liam
ea710e6523 vi: connect vsync event handle lifetime to application display service interface 2024-01-07 21:47:41 -05:00
Liam
ae88ea79b2 vi: fix name of nvnflinger 2024-01-07 21:31:03 -05:00
liamwhite
82b58668ed Merge pull request #12608 from szepeviktor/typos
Fix typos in video_core
2024-01-07 20:42:54 -05:00
liamwhite
bd80929ac1 Merge pull request #12606 from german77/npad_close
service: hid: Delete shared memory handle when unused
2024-01-07 20:41:11 -05:00
liamwhite
2a4ac7cfac Merge pull request #12600 from german77/npad-impl
service: hid: Hook interface implementations
2024-01-07 20:41:06 -05:00
liamwhite
ab513c378a Merge pull request #12599 from german77/settings
service: set: Use official names
2024-01-07 20:40:56 -05:00
german77
bc2d1262d7 service: hid: Delete shared memory handle when unused 2024-01-07 12:55:24 -06:00
german77
5105b90017 service: hid: Implement GetLastActiveNpad 2024-01-06 23:30:43 -06:00
german77
3516a2d0bf service: hid: Implement AssigningSingleOnSlSrPress 2024-01-06 23:30:42 -06:00
german77
f224ef6185 service: hid: Implement SetNpadSystemExtStateEnabled 2024-01-06 23:30:41 -06:00
german77
8e27a485d8 service: set: Rename files 2024-01-06 23:16:03 -06:00
german77
a36f4d0a9f service: hid: Implement CaptureButtonAssignment 2024-01-06 21:18:44 -06:00
german77
37b0870ee3 service: set: Use official names 2024-01-06 17:37:36 -06:00
79 changed files with 1494 additions and 1392 deletions

View File

@@ -3,38 +3,32 @@
# SPDX-FileCopyrightText: 2019 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop \
dist/*.svg dist/*.xml; then
shopt -s nullglob globstar
if git grep -nrI '\s$' src **/*.yml **/*.txt **/*.md Doxyfile .gitignore .gitmodules .ci* dist/*.desktop dist/*.svg dist/*.xml; then
echo Trailing whitespace found, aborting
exit 1
fi
# Default clang-format points to default 3.5 version one
CLANG_FORMAT=${CLANG_FORMAT:-clang-format-15}
$CLANG_FORMAT --version
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
# Get list of every file modified in this pull request
files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' || true)"
else
# Check everything for branch pushes
files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')"
fi
CLANG_FORMAT="${CLANG_FORMAT:-clang-format-15}"
"$CLANG_FORMAT" --version
# Turn off tracing for this because it's too verbose
set +x
for f in $files_to_lint; do
d=$(diff -u "$f" <($CLANG_FORMAT "$f") || true)
if ! [ -z "$d" ]; then
echo "!!! $f not compliant to coding style, here is the fix:"
echo "$d"
fail=1
fi
# Check everything for branch pushes
FILES_TO_LINT="$(find src/ -name '*.cpp' -or -name '*.h')"
for f in $FILES_TO_LINT; do
echo "$f"
"$CLANG_FORMAT" -i "$f"
done
set -x
DIFF=$(git -c core.fileMode=false diff)
if [ "$fail" = 1 ]; then
if [ ! -z "$DIFF" ]; then
echo "!!! Not compliant to coding style, here is the fix:"
echo "$DIFF"
exit 1
fi

View File

@@ -9,7 +9,7 @@ chmod a+x ./.ci/scripts/linux/docker.sh
sudo chown -R 1027 ./
# The environment variables listed below:
# AZURECIREPO TITLEBARFORMATIDLE TITLEBARFORMATRUNNING DISPLAYVERSION
# AZURECIREPO TITLEBARFORMATIDLE TITLEBARFORMATRUNNING DISPLAYVERSION
# are requested in src/common/CMakeLists.txt and appear to be provided somewhere in Azure DevOps
docker run -e AZURECIREPO -e TITLEBARFORMATIDLE -e TITLEBARFORMATRUNNING -e DISPLAYVERSION -e ENABLE_COMPATIBILITY_REPORTING -e CCACHE_DIR=/yuzu/ccache -v "$(pwd):/yuzu" -w /yuzu yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.ci/scripts/linux/docker.sh "$1"

View File

@@ -1,4 +1,4 @@
Copyright (c) <year> <owner>
Copyright (c) <year> <owner>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

View File

@@ -1,4 +1,4 @@
Copyright (c) <year> <owner>.
Copyright (c) <year> <owner>.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

View File

@@ -35,7 +35,7 @@ Mozilla Public License Version 2.0
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"

View File

@@ -138,7 +138,7 @@ if (NOT WIN32 AND NOT ANDROID)
--cross-prefix=${TOOLCHAIN}/bin/aarch64-linux-android-
--sysroot=${SYSROOT}
--target-os=android
--extra-ldflags="--ld-path=${TOOLCHAIN}/bin/ld.lld"
--extra-ldflags="--ld-path=${TOOLCHAIN}/bin/ld.lld"
--extra-ldflags="-nostdlib"
)
endif()

View File

@@ -708,24 +708,24 @@ add_library(core STATIC
hle/service/server_manager.h
hle/service/service.cpp
hle/service/service.h
hle/service/set/set.cpp
hle/service/set/set.h
hle/service/set/appln_settings.cpp
hle/service/set/appln_settings.h
hle/service/set/device_settings.cpp
hle/service/set/device_settings.h
hle/service/set/factory_settings_server.cpp
hle/service/set/factory_settings_server.h
hle/service/set/firmware_debug_settings_server.cpp
hle/service/set/firmware_debug_settings_server.h
hle/service/set/private_settings.cpp
hle/service/set/private_settings.h
hle/service/set/set_cal.cpp
hle/service/set/set_cal.h
hle/service/set/set_fd.cpp
hle/service/set/set_fd.h
hle/service/set/set_sys.cpp
hle/service/set/set_sys.h
hle/service/set/settings.cpp
hle/service/set/settings.h
hle/service/set/settings_server.cpp
hle/service/set/settings_server.h
hle/service/set/system_settings.cpp
hle/service/set/system_settings.h
hle/service/set/system_settings_server.cpp
hle/service/set/system_settings_server.h
hle/service/sm/sm.cpp
hle/service/sm/sm.h
hle/service/sm/sm_controller.cpp

View File

@@ -64,7 +64,7 @@ public:
return [this] { ShutdownThreadFunction(); };
}
void PreemptSingleCore(bool from_running_enviroment = true);
void PreemptSingleCore(bool from_running_environment = true);
std::size_t CurrentCore() const {
return current_core.load();

View File

@@ -559,28 +559,28 @@ void GDBStub::HandleVCont(std::string_view command, std::vector<DebuggerAction>&
}
constexpr std::array<std::pair<const char*, Kernel::Svc::MemoryState>, 22> MemoryStateNames{{
{"----- Free -----", Kernel::Svc::MemoryState::Free},
{"Io ", Kernel::Svc::MemoryState::Io},
{"Static ", Kernel::Svc::MemoryState::Static},
{"Code ", Kernel::Svc::MemoryState::Code},
{"CodeData ", Kernel::Svc::MemoryState::CodeData},
{"Normal ", Kernel::Svc::MemoryState::Normal},
{"Shared ", Kernel::Svc::MemoryState::Shared},
{"AliasCode ", Kernel::Svc::MemoryState::AliasCode},
{"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData},
{"Ipc ", Kernel::Svc::MemoryState::Ipc},
{"Stack ", Kernel::Svc::MemoryState::Stack},
{"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal},
{"Transfered ", Kernel::Svc::MemoryState::Transfered},
{"SharedTransfered", Kernel::Svc::MemoryState::SharedTransfered},
{"SharedCode ", Kernel::Svc::MemoryState::SharedCode},
{"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible},
{"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc},
{"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc},
{"Kernel ", Kernel::Svc::MemoryState::Kernel},
{"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode},
{"CodeOut ", Kernel::Svc::MemoryState::CodeOut},
{"Coverage ", Kernel::Svc::MemoryState::Coverage},
{"----- Free ------", Kernel::Svc::MemoryState::Free},
{"Io ", Kernel::Svc::MemoryState::Io},
{"Static ", Kernel::Svc::MemoryState::Static},
{"Code ", Kernel::Svc::MemoryState::Code},
{"CodeData ", Kernel::Svc::MemoryState::CodeData},
{"Normal ", Kernel::Svc::MemoryState::Normal},
{"Shared ", Kernel::Svc::MemoryState::Shared},
{"AliasCode ", Kernel::Svc::MemoryState::AliasCode},
{"AliasCodeData ", Kernel::Svc::MemoryState::AliasCodeData},
{"Ipc ", Kernel::Svc::MemoryState::Ipc},
{"Stack ", Kernel::Svc::MemoryState::Stack},
{"ThreadLocal ", Kernel::Svc::MemoryState::ThreadLocal},
{"Transferred ", Kernel::Svc::MemoryState::Transferred},
{"SharedTransferred", Kernel::Svc::MemoryState::SharedTransferred},
{"SharedCode ", Kernel::Svc::MemoryState::SharedCode},
{"Inaccessible ", Kernel::Svc::MemoryState::Inaccessible},
{"NonSecureIpc ", Kernel::Svc::MemoryState::NonSecureIpc},
{"NonDeviceIpc ", Kernel::Svc::MemoryState::NonDeviceIpc},
{"Kernel ", Kernel::Svc::MemoryState::Kernel},
{"GeneratedCode ", Kernel::Svc::MemoryState::GeneratedCode},
{"CodeOut ", Kernel::Svc::MemoryState::CodeOut},
{"Coverage ", Kernel::Svc::MemoryState::Coverage},
}};
static constexpr const char* GetMemoryStateName(Kernel::Svc::MemoryState state) {

View File

@@ -26,7 +26,7 @@
#include "core/file_sys/vfs_vector.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ns/language.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/settings_server.h"
#include "core/loader/loader.h"
#include "core/loader/nso.h"
#include "core/memory/cheat_engine.h"

View File

@@ -81,12 +81,12 @@ enum class KMemoryState : u32 {
ThreadLocal = static_cast<u32>(Svc::MemoryState::ThreadLocal) | FlagLinearMapped,
Transfered = static_cast<u32>(Svc::MemoryState::Transfered) | FlagsMisc |
FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc |
FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
Transferred = static_cast<u32>(Svc::MemoryState::Transferred) | FlagsMisc |
FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc |
FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
SharedTransfered = static_cast<u32>(Svc::MemoryState::SharedTransfered) | FlagsMisc |
FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
SharedTransferred = static_cast<u32>(Svc::MemoryState::SharedTransferred) | FlagsMisc |
FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
SharedCode = static_cast<u32>(Svc::MemoryState::SharedCode) | FlagMapped |
FlagReferenceCounted | FlagLinearMapped | FlagCanUseNonSecureIpc |
@@ -130,8 +130,8 @@ static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x0FFFBD09);
static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x045C3C0A);
static_assert(static_cast<u32>(KMemoryState::Stack) == 0x045C3C0B);
static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0400000C);
static_assert(static_cast<u32>(KMemoryState::Transfered) == 0x055C3C0D);
static_assert(static_cast<u32>(KMemoryState::SharedTransfered) == 0x045C380E);
static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x055C3C0D);
static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x045C380E);
static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0440380F);
static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010);
static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x045C3811);

View File

@@ -486,8 +486,8 @@ KProcessAddress KPageTableBase::GetRegionAddress(Svc::MemoryState state) const {
case Svc::MemoryState::Shared:
case Svc::MemoryState::AliasCode:
case Svc::MemoryState::AliasCodeData:
case Svc::MemoryState::Transfered:
case Svc::MemoryState::SharedTransfered:
case Svc::MemoryState::Transferred:
case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:
@@ -522,8 +522,8 @@ size_t KPageTableBase::GetRegionSize(Svc::MemoryState state) const {
case Svc::MemoryState::Shared:
case Svc::MemoryState::AliasCode:
case Svc::MemoryState::AliasCodeData:
case Svc::MemoryState::Transfered:
case Svc::MemoryState::SharedTransfered:
case Svc::MemoryState::Transferred:
case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:
@@ -564,8 +564,8 @@ bool KPageTableBase::CanContain(KProcessAddress addr, size_t size, Svc::MemorySt
case Svc::MemoryState::AliasCodeData:
case Svc::MemoryState::Stack:
case Svc::MemoryState::ThreadLocal:
case Svc::MemoryState::Transfered:
case Svc::MemoryState::SharedTransfered:
case Svc::MemoryState::Transferred:
case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:

View File

@@ -76,8 +76,8 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer
// Map the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
? KMemoryState::Transfered
: KMemoryState::SharedTransfered;
? KMemoryState::Transferred
: KMemoryState::SharedTransferred;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
address, *m_page_group, state, KMemoryPermission::UserReadWrite));
@@ -96,8 +96,8 @@ Result KTransferMemory::Unmap(KProcessAddress address, size_t size) {
// Unmap the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
? KMemoryState::Transfered
: KMemoryState::SharedTransfered;
? KMemoryState::Transferred
: KMemoryState::SharedTransferred;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state));
// Mark ourselves as unmapped.

View File

@@ -90,7 +90,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
.CanContain(address, size, KMemoryState::Transfered),
.CanContain(address, size, KMemoryState::Transferred),
ResultInvalidMemoryRegion);
// Map the transfer memory.
@@ -117,7 +117,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
.CanContain(address, size, KMemoryState::Transfered),
.CanContain(address, size, KMemoryState::Transferred),
ResultInvalidMemoryRegion);
// Unmap the transfer memory.

View File

@@ -27,8 +27,8 @@ enum class MemoryState : u32 {
Ipc = 0x0A,
Stack = 0x0B,
ThreadLocal = 0x0C,
Transfered = 0x0D,
SharedTransfered = 0x0E,
Transferred = 0x0D,
SharedTransferred = 0x0E,
SharedCode = 0x0F,
Inaccessible = 0x10,
NonSecureIpc = 0x11,

View File

@@ -76,7 +76,7 @@ struct UiSettingsDisplayOptions {
bool is_system_or_launcher;
bool is_registration_permitted;
bool show_skip_button;
bool aditional_select;
bool additional_select;
bool show_user_selector;
bool is_unqualified_user_selectable;
};

View File

@@ -85,7 +85,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu
}
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time,
ContentType content_type, s64 start_posix_time,
s64 end_posix_time, u64 aruid) const {
if (!is_mounted) {
return ResultIsNotMounted;
@@ -94,7 +94,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou
std::vector<ApplicationAlbumEntry> album_entries;
const auto start_date = ConvertToAlbumDateTime(start_posix_time);
const auto end_date = ConvertToAlbumDateTime(end_posix_time);
const auto result = GetAlbumFileList(album_entries, contex_type, start_date, end_date, aruid);
const auto result = GetAlbumFileList(album_entries, content_type, start_date, end_date, aruid);
if (result.IsError()) {
return result;
@@ -113,14 +113,14 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou
}
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date,
ContentType content_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid) const {
if (!is_mounted) {
return ResultIsNotMounted;
}
for (auto& [file_id, path] : album_files) {
if (file_id.type != contex_type) {
if (file_id.type != content_type) {
continue;
}
if (file_id.date > start_date) {
@@ -139,7 +139,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_en
.hash{},
.datetime = file_id.date,
.storage = file_id.storage,
.content = contex_type,
.content = content_type,
.unknown = 1,
};
out_entries.push_back(entry);

View File

@@ -45,10 +45,10 @@ public:
Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
u8 flags) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time, s64 end_posix_time,
ContentType content_type, s64 start_posix_time, s64 end_posix_time,
u64 aruid) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date,
ContentType content_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid) const;
Result GetAutoSavingStorage(bool& out_is_autosaving) const;
Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output,

View File

@@ -12,7 +12,7 @@ constexpr Result ResultUnknown5(ErrorModule::Capture, 5);
constexpr Result ResultUnknown6(ErrorModule::Capture, 6);
constexpr Result ResultUnknown7(ErrorModule::Capture, 7);
constexpr Result ResultOutOfRange(ErrorModule::Capture, 8);
constexpr Result ResulInvalidTimestamp(ErrorModule::Capture, 12);
constexpr Result ResultInvalidTimestamp(ErrorModule::Capture, 12);
constexpr Result ResultInvalidStorage(ErrorModule::Capture, 13);
constexpr Result ResultInvalidFileContents(ErrorModule::Capture, 14);
constexpr Result ResultIsNotMounted(ErrorModule::Capture, 21);

View File

@@ -131,7 +131,7 @@ private:
u8 is_favorite;
u8 same_app;
u8 same_app_played;
u8 arbitary_app_played;
u8 arbitrary_app_played;
u64 group_id;
};
static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size");

View File

@@ -18,23 +18,23 @@ namespace Service::HID {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
std::shared_ptr<ResourceManager> resouce_manager = std::make_shared<ResourceManager>(system);
std::shared_ptr<ResourceManager> resource_manager = std::make_shared<ResourceManager>(system);
std::shared_ptr<HidFirmwareSettings> firmware_settings =
std::make_shared<HidFirmwareSettings>();
// TODO: Remove this hack until this service is emulated properly.
const auto process_list = system.Kernel().GetProcessList();
if (!process_list.empty()) {
resouce_manager->Initialize();
resouce_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
resource_manager->Initialize();
resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
}
server_manager->RegisterNamedService(
"hid", std::make_shared<IHidServer>(system, resouce_manager, firmware_settings));
"hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));
server_manager->RegisterNamedService(
"hid:dbg", std::make_shared<IHidDebugServer>(system, resouce_manager));
"hid:dbg", std::make_shared<IHidDebugServer>(system, resource_manager));
server_manager->RegisterNamedService(
"hid:sys", std::make_shared<IHidSystemServer>(system, resouce_manager));
"hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager));
server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));

View File

@@ -1444,8 +1444,8 @@ void IHidServer::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING(Service_HID, "(STUBBED) called, use_center_clamp={}, applet_resource_user_id={}",
parameters.use_center_clamp, parameters.applet_resource_user_id);
LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}",
parameters.use_center_clamp, parameters.applet_resource_user_id);
GetResourceManager()->GetNpad()->SetNpadAnalogStickUseCenterClamp(
parameters.applet_resource_user_id, parameters.use_center_clamp);
@@ -1466,23 +1466,27 @@ void IHidServer::SetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING(Service_HID,
"(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
LOG_INFO(Service_HID, "called, npad_styleset={}, applet_resource_user_id={}, button={}",
parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
const auto result = GetResourceManager()->GetNpad()->SetNpadCaptureButtonAssignment(
parameters.applet_resource_user_id, parameters.npad_styleset, parameters.button);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
applet_resource_user_id);
LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
const auto result =
GetResourceManager()->GetNpad()->ClearNpadCaptureButtonAssignment(applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {

View File

@@ -46,7 +46,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
{311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
{312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
{313, nullptr, "GetNpadCaptureButtonAssignment"},
{313, &IHidSystemServer::GetNpadCaptureButtonAssignment, "GetNpadCaptureButtonAssignment"},
{314, nullptr, "GetAppletFooterUiType"},
{315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
{316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
@@ -54,8 +54,8 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
{318, &IHidSystemServer::HasBattery, "HasBattery"},
{319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
{321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
{322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
{323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
{322, &IHidSystemServer::SetNpadSystemExtStateEnabled, "SetNpadSystemExtStateEnabled"},
{323, nullptr, "GetLastActiveUniquePad"},
{324, nullptr, "GetUniquePadButtonSet"},
{325, nullptr, "GetUniquePadColor"},
{326, nullptr, "GetUniquePadAppletDetailedUiType"},
@@ -251,25 +251,38 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
}
void IHidSystemServer::EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
GetResourceManager()->GetNpad()->AssigningSingleOnSlSrPress(applet_resource_user_id, true);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
GetResourceManager()->GetNpad()->AssigningSingleOnSlSrPress(applet_resource_user_id, false);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "(STUBBED) called"); // Spams a lot when controller applet is running
Core::HID::NpadIdType npad_id{};
const Result result = GetResourceManager()->GetNpad()->GetLastActiveNpad(npad_id);
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0); // Dont forget to fix this
rb.Push(result);
rb.PushEnum(npad_id);
}
void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) {
@@ -331,6 +344,27 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) {
rb.Push(result);
}
void IHidSystemServer::GetNpadCaptureButtonAssignment(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
const auto capture_button_list_size{ctx.GetWriteBufferNumElements<Core::HID::NpadButton>()};
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
std::vector<Core::HID::NpadButton> capture_button_list(capture_button_list_size);
const auto& npad = GetResourceManager()->GetNpad();
const u64 list_size =
npad->GetNpadCaptureButtonAssignment(capture_button_list, applet_resource_user_id);
if (list_size != 0) {
ctx.WriteBuffer(capture_button_list);
}
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(list_size);
}
void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
@@ -423,13 +457,25 @@ void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) {
rb.Push(static_cast<u32>(unique_pads.size()));
}
void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) {
void IHidSystemServer::SetNpadSystemExtStateEnabled(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
bool is_enabled;
INSERT_PADDING_BYTES_NOINIT(7);
u64 applet_resource_user_id;
};
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
LOG_WARNING(Service_HID, "(STUBBED) called");
const auto parameters{rp.PopRaw<Parameters>()};
LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
parameters.is_enabled, parameters.applet_resource_user_id);
const auto result = GetResourceManager()->GetNpad()->SetNpadSystemExtStateEnabled(
parameters.applet_resource_user_id, parameters.is_enabled);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void IHidSystemServer::RegisterAppletResourceUserId(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};

View File

@@ -31,13 +31,14 @@ private:
void GetNpadFullKeyGripColor(HLERequestContext& ctx);
void GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx);
void SetSupportedNpadStyleSetAll(HLERequestContext& ctx);
void GetNpadCaptureButtonAssignment(HLERequestContext& ctx);
void GetAppletDetailedUiType(HLERequestContext& ctx);
void GetNpadInterfaceType(HLERequestContext& ctx);
void GetNpadLeftRightInterfaceType(HLERequestContext& ctx);
void HasBattery(HLERequestContext& ctx);
void HasLeftRightBattery(HLERequestContext& ctx);
void GetUniquePadsFromNpad(HLERequestContext& ctx);
void GetIrSensorState(HLERequestContext& ctx);
void SetNpadSystemExtStateEnabled(HLERequestContext& ctx);
void RegisterAppletResourceUserId(HLERequestContext& ctx);
void UnregisterAppletResourceUserId(HLERequestContext& ctx);
void EnableAppletToGetInput(HLERequestContext& ctx);

View File

@@ -67,7 +67,7 @@ HidBus::~HidBus() {
void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
if (is_hidbus_enabled) {
for (std::size_t i = 0; i < devices.size(); ++i) {
if (!devices[i].is_device_initializated) {
if (!devices[i].is_device_initialized) {
continue;
}
auto& device = devices[i].device;
@@ -213,7 +213,7 @@ void HidBus::Initialize(HLERequestContext& ctx) {
if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) {
MakeDevice<RingController>(bus_handle_);
devices[device_index.value()].is_device_initializated = true;
devices[device_index.value()].is_device_initialized = true;
devices[device_index.value()].device->ActivateDevice();
cur_entry.is_in_focus = true;
cur_entry.is_connected = true;
@@ -222,7 +222,7 @@ void HidBus::Initialize(HLERequestContext& ctx) {
cur_entry.is_polling_mode = false;
} else {
MakeDevice<HidbusStubbed>(bus_handle_);
devices[device_index.value()].is_device_initializated = true;
devices[device_index.value()].is_device_initialized = true;
cur_entry.is_in_focus = true;
cur_entry.is_connected = false;
cur_entry.is_connected_result = ResultSuccess;
@@ -261,7 +261,7 @@ void HidBus::Finalize(HLERequestContext& ctx) {
const auto entry_index = devices[device_index.value()].handle.internal_index;
auto& cur_entry = hidbus_status.entries[entry_index];
auto& device = devices[device_index.value()].device;
devices[device_index.value()].is_device_initializated = false;
devices[device_index.value()].is_device_initialized = false;
device->DeactivateDevice();
cur_entry.is_in_focus = true;

View File

@@ -89,7 +89,7 @@ private:
static_assert(sizeof(HidbusStatusManager) <= 0x1000, "HidbusStatusManager is an invalid size");
struct HidbusDevice {
bool is_device_initializated{};
bool is_device_initialized{};
BusHandle handle{};
std::unique_ptr<HidbusBase> device{nullptr};
};

View File

@@ -181,22 +181,22 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
}
}
buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors);
buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors);
buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors);
buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors);
buffer_x_descriptors.reserve(command_header->num_buf_x_descriptors);
buffer_a_descriptors.reserve(command_header->num_buf_a_descriptors);
buffer_b_descriptors.reserve(command_header->num_buf_b_descriptors);
buffer_w_descriptors.reserve(command_header->num_buf_w_descriptors);
for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) {
buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>());
buffer_x_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>());
}
for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) {
buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
buffer_a_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
}
for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) {
buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
buffer_b_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
}
for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) {
buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
buffer_w_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
}
const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size;
@@ -246,7 +246,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) {
if (command_header->buf_c_descriptor_flags ==
IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) {
buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
buffer_c_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
} else {
u32 num_buf_c_descriptors =
static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2;
@@ -256,7 +256,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
ASSERT(num_buf_c_descriptors < 14);
for (u32 i = 0; i < num_buf_c_descriptors; ++i) {
buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
buffer_c_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>());
}
}
}

View File

@@ -232,19 +232,19 @@ public:
}
[[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const {
return buffer_x_desciptors;
return buffer_x_descriptors;
}
[[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const {
return buffer_a_desciptors;
return buffer_a_descriptors;
}
[[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const {
return buffer_b_desciptors;
return buffer_b_descriptors;
}
[[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const {
return buffer_c_desciptors;
return buffer_c_descriptors;
}
[[nodiscard]] const IPC::DomainMessageHeader& GetDomainMessageHeader() const {
@@ -406,11 +406,11 @@ private:
std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header;
std::optional<IPC::DataPayloadHeader> data_payload_header;
std::optional<IPC::DomainMessageHeader> domain_message_header;
std::vector<IPC::BufferDescriptorX> buffer_x_desciptors;
std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors;
std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors;
std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors;
std::vector<IPC::BufferDescriptorC> buffer_c_desciptors;
std::vector<IPC::BufferDescriptorX> buffer_x_descriptors;
std::vector<IPC::BufferDescriptorABW> buffer_a_descriptors;
std::vector<IPC::BufferDescriptorABW> buffer_b_descriptors;
std::vector<IPC::BufferDescriptorABW> buffer_w_descriptors;
std::vector<IPC::BufferDescriptorC> buffer_c_descriptors;
u32_le command{};
u64 pid{};

View File

@@ -19,7 +19,7 @@ namespace Service::NFP::AmiiboCrypto {
bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
const auto& amiibo_data = ntag_file.user_memory;
LOG_DEBUG(Service_NFP, "uuid_lock=0x{0:x}", ntag_file.static_lock);
LOG_DEBUG(Service_NFP, "compability_container=0x{0:x}", ntag_file.compability_container);
LOG_DEBUG(Service_NFP, "compatibility_container=0x{0:x}", ntag_file.compatibility_container);
LOG_DEBUG(Service_NFP, "write_count={}", static_cast<u16>(amiibo_data.write_counter));
LOG_DEBUG(Service_NFP, "character_id=0x{0:x}", amiibo_data.model_info.character_id);
@@ -49,7 +49,7 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
if (ntag_file.static_lock != 0xE00F) {
return false;
}
if (ntag_file.compability_container != 0xEEFF10F1U) {
if (ntag_file.compatibility_container != 0xEEFF10F1U) {
return false;
}
if (amiibo_data.model_info.tag_type != NFC::PackedTagType::Type2) {
@@ -78,7 +78,7 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2;
encoded_data.internal_number = nfc_data.internal_number;
encoded_data.static_lock = nfc_data.static_lock;
encoded_data.compability_container = nfc_data.compability_container;
encoded_data.compatibility_container = nfc_data.compatibility_container;
encoded_data.hmac_data = nfc_data.user_memory.hmac_data;
encoded_data.constant_value = nfc_data.user_memory.constant_value;
encoded_data.write_counter = nfc_data.user_memory.write_counter;
@@ -112,7 +112,7 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2;
nfc_data.internal_number = encoded_data.internal_number;
nfc_data.static_lock = encoded_data.static_lock;
nfc_data.compability_container = encoded_data.compability_container;
nfc_data.compatibility_container = encoded_data.compatibility_container;
nfc_data.user_memory.hmac_data = encoded_data.hmac_data;
nfc_data.user_memory.constant_value = encoded_data.constant_value;
nfc_data.user_memory.write_counter = encoded_data.write_counter;
@@ -257,7 +257,7 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou
out_data.uid_crc_check2 = in_data.uid_crc_check2;
out_data.internal_number = in_data.internal_number;
out_data.static_lock = in_data.static_lock;
out_data.compability_container = in_data.compability_container;
out_data.compatibility_container = in_data.compatibility_container;
out_data.constant_value = in_data.constant_value;
out_data.write_counter = in_data.write_counter;

View File

@@ -75,7 +75,7 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
return;
}
if (!is_initalized) {
if (!is_initialized) {
return;
}
@@ -207,7 +207,7 @@ void NfcDevice::Initialize() {
return;
}
is_initalized = npad_device->AddNfcHandle();
is_initialized = npad_device->AddNfcHandle();
}
void NfcDevice::Finalize() {
@@ -226,7 +226,7 @@ void NfcDevice::Finalize() {
}
device_state = DeviceState::Unavailable;
is_initalized = false;
is_initialized = false;
}
Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {

View File

@@ -126,7 +126,7 @@ private:
Kernel::KEvent* deactivate_event = nullptr;
Kernel::KEvent* availability_change_event = nullptr;
bool is_initalized{};
bool is_initialized{};
NfcProtocol allowed_protocols{};
DeviceState device_state{DeviceState::Unavailable};

View File

@@ -243,12 +243,12 @@ static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid si
struct NTAG215File {
u8 uid_crc_check2;
u8 internal_number;
u16 static_lock; // Set defined pages as read only
u32 compability_container; // Defines available memory
HashData hmac_data; // Hash
u8 constant_value; // Must be A5
u16_be write_counter; // Number of times the amiibo has been written?
u8 amiibo_version; // Amiibo file version
u16 static_lock; // Set defined pages as read only
u32 compatibility_container; // Defines available memory
HashData hmac_data; // Hash
u8 constant_value; // Must be A5
u16_be write_counter; // Number of times the amiibo has been written?
u8 amiibo_version; // Amiibo file version
AmiiboSettings settings;
Service::Mii::Ver3StoreData owner_mii; // Mii data
u64_be application_id; // Game id
@@ -278,7 +278,7 @@ struct EncryptedNTAG215File {
u8 uuid_crc_check2;
u8 internal_number;
u16 static_lock; // Set defined pages as read only
u32 compability_container; // Defines available memory
u32 compatibility_container; // Defines available memory
EncryptedAmiiboFile user_memory; // Writable data
u32 dynamic_lock; // Dynamic lock
u32 CFG0; // Defines memory protected by password

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ns/language.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/settings_server.h"
namespace Service::NS {

View File

@@ -16,7 +16,7 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pdm_qry.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/settings_server.h"
namespace Service::NS {

View File

@@ -90,7 +90,7 @@ private:
u64_le align;
};
};
static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size");
static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitializeEx is incorrect size");
struct IoctlFreeSpace {
u64_le offset{};

View File

@@ -15,7 +15,7 @@ namespace Service::Nvidia::Devices {
nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_)
: nvdevice{system_}, events_interface{events_interface_} {
error_notifier_event = events_interface.CreateEvent("CtrlGpuErrorNotifier");
unknown_event = events_interface.CreateEvent("CtrlGpuUknownEvent");
unknown_event = events_interface.CreateEvent("CtrlGpuUnknownEvent");
}
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() {
events_interface.FreeEvent(error_notifier_event);

View File

@@ -51,7 +51,7 @@ enum class NvResult : u32 {
DispNoDisplaysAttached = 0x20003,
DispModeNotSupported = 0x20004,
DispNotFound = 0x20005,
DispAttachDissallowed = 0x20006,
DispAttachDisallowed = 0x20006,
DispTypeNotSupported = 0x20007,
DispAuthenticationFailed = 0x20008,
DispNotAttached = 0x20009,

View File

@@ -223,7 +223,8 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
return VI::ResultNotFound;
}
return display->GetVSyncEvent(out_vsync_event);
*out_vsync_event = display->GetVSyncEvent();
return ResultSuccess;
}
VI::Display* Nvnflinger::FindDisplay(u64 display_id) {

View File

@@ -54,8 +54,8 @@ public:
class IClkrstSession final : public ServiceFramework<IClkrstSession> {
public:
explicit IClkrstSession(Core::System& system_, DeviceCode deivce_code_)
: ServiceFramework{system_, "IClkrstSession"}, deivce_code(deivce_code_) {
explicit IClkrstSession(Core::System& system_, DeviceCode device_code_)
: ServiceFramework{system_, "IClkrstSession"}, device_code(device_code_) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "SetClockEnabled"},
@@ -93,7 +93,7 @@ private:
rb.Push<u32>(clock_rate);
}
DeviceCode deivce_code;
DeviceCode device_code;
u32 clock_rate{};
};
@@ -118,9 +118,9 @@ private:
void OpenSession(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto device_code = static_cast<DeviceCode>(rp.Pop<u32>());
const auto unkonwn_input = rp.Pop<u32>();
const auto unknown_input = rp.Pop<u32>();
LOG_DEBUG(Service_PCV, "called, device_code={}, input={}", device_code, unkonwn_input);
LOG_DEBUG(Service_PCV, "called, device_code={}, input={}", device_code, unknown_input);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);

View File

@@ -1,11 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/set/set_cal.h"
#include "core/hle/service/set/factory_settings_server.h"
namespace Service::Set {
SET_CAL::SET_CAL(Core::System& system_) : ServiceFramework{system_, "set:cal"} {
IFactorySettingsServer::IFactorySettingsServer(Core::System& system_)
: ServiceFramework{system_, "set:cal"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetBluetoothBdAddress"},
@@ -57,6 +58,6 @@ SET_CAL::SET_CAL(Core::System& system_) : ServiceFramework{system_, "set:cal"} {
RegisterHandlers(functions);
}
SET_CAL::~SET_CAL() = default;
IFactorySettingsServer::~IFactorySettingsServer() = default;
} // namespace Service::Set

View File

@@ -11,10 +11,10 @@ class System;
namespace Service::Set {
class SET_FD final : public ServiceFramework<SET_FD> {
class IFactorySettingsServer final : public ServiceFramework<IFactorySettingsServer> {
public:
explicit SET_FD(Core::System& system_);
~SET_FD() override;
explicit IFactorySettingsServer(Core::System& system_);
~IFactorySettingsServer() override;
};
} // namespace Service::Set

View File

@@ -1,11 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/set/set_fd.h"
#include "core/hle/service/set/firmware_debug_settings_server.h"
namespace Service::Set {
SET_FD::SET_FD(Core::System& system_) : ServiceFramework{system_, "set:fd"} {
IFirmwareDebugSettingsServer::IFirmwareDebugSettingsServer(Core::System& system_)
: ServiceFramework{system_, "set:fd"} {
// clang-format off
static const FunctionInfo functions[] = {
{2, nullptr, "SetSettingsItemValue"},
@@ -23,6 +24,6 @@ SET_FD::SET_FD(Core::System& system_) : ServiceFramework{system_, "set:fd"} {
RegisterHandlers(functions);
}
SET_FD::~SET_FD() = default;
IFirmwareDebugSettingsServer::~IFirmwareDebugSettingsServer() = default;
} // namespace Service::Set

View File

@@ -11,10 +11,10 @@ class System;
namespace Service::Set {
class SET_CAL final : public ServiceFramework<SET_CAL> {
class IFirmwareDebugSettingsServer final : public ServiceFramework<IFirmwareDebugSettingsServer> {
public:
explicit SET_CAL(Core::System& system_);
~SET_CAL() override;
explicit IFirmwareDebugSettingsServer(Core::System& system_);
~IFirmwareDebugSettingsServer() override;
};
} // namespace Service::Set

View File

@@ -2,21 +2,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/server_manager.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/set_cal.h"
#include "core/hle/service/set/set_fd.h"
#include "core/hle/service/set/set_sys.h"
#include "core/hle/service/set/factory_settings_server.h"
#include "core/hle/service/set/firmware_debug_settings_server.h"
#include "core/hle/service/set/settings.h"
#include "core/hle/service/set/settings_server.h"
#include "core/hle/service/set/system_settings_server.h"
namespace Service::Set {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("set", std::make_shared<SET>(system));
server_manager->RegisterNamedService("set:cal", std::make_shared<SET_CAL>(system));
server_manager->RegisterNamedService("set:fd", std::make_shared<SET_FD>(system));
server_manager->RegisterNamedService("set:sys", std::make_shared<SET_SYS>(system));
server_manager->RegisterNamedService("set", std::make_shared<ISettingsServer>(system));
server_manager->RegisterNamedService("set:cal",
std::make_shared<IFactorySettingsServer>(system));
server_manager->RegisterNamedService("set:fd",
std::make_shared<IFirmwareDebugSettingsServer>(system));
server_manager->RegisterNamedService("set:sys",
std::make_shared<ISystemSettingsServer>(system));
ServerManager::RunServer(std::move(server_manager));
}

View File

@@ -7,7 +7,7 @@
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/set.h"
#include "core/hle/service/set/settings_server.h"
namespace Service::Set {
namespace {
@@ -58,13 +58,36 @@ LanguageCode GetLanguageCodeFromIndex(std::size_t index) {
return available_language_codes.at(index);
}
void SET::GetAvailableLanguageCodes(HLERequestContext& ctx) {
ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{system_, "set"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ISettingsServer::GetLanguageCode, "GetLanguageCode"},
{1, &ISettingsServer::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, &ISettingsServer::MakeLanguageCode, "MakeLanguageCode"},
{3, &ISettingsServer::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
{4, &ISettingsServer::GetRegionCode, "GetRegionCode"},
{5, &ISettingsServer::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
{6, &ISettingsServer::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
{7, &ISettingsServer::GetKeyCodeMap, "GetKeyCodeMap"},
{8, &ISettingsServer::GetQuestFlag, "GetQuestFlag"},
{9, &ISettingsServer::GetKeyCodeMap2, "GetKeyCodeMap2"},
{10, nullptr, "GetFirmwareVersionForDebug"},
{11, &ISettingsServer::GetDeviceNickName, "GetDeviceNickName"},
};
// clang-format on
RegisterHandlers(functions);
}
ISettingsServer::~ISettingsServer() = default;
void ISettingsServer::GetAvailableLanguageCodes(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
GetAvailableLanguageCodesImpl(ctx, PRE_4_0_0_MAX_ENTRIES);
}
void SET::MakeLanguageCode(HLERequestContext& ctx) {
void ISettingsServer::MakeLanguageCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index = rp.Pop<u32>();
@@ -80,25 +103,25 @@ void SET::MakeLanguageCode(HLERequestContext& ctx) {
rb.PushEnum(available_language_codes[index]);
}
void SET::GetAvailableLanguageCodes2(HLERequestContext& ctx) {
void ISettingsServer::GetAvailableLanguageCodes2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
GetAvailableLanguageCodesImpl(ctx, POST_4_0_0_MAX_ENTRIES);
}
void SET::GetAvailableLanguageCodeCount(HLERequestContext& ctx) {
void ISettingsServer::GetAvailableLanguageCodeCount(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
PushResponseLanguageCode(ctx, PRE_4_0_0_MAX_ENTRIES);
}
void SET::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) {
void ISettingsServer::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
PushResponseLanguageCode(ctx, POST_4_0_0_MAX_ENTRIES);
}
void SET::GetQuestFlag(HLERequestContext& ctx) {
void ISettingsServer::GetQuestFlag(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
@@ -106,7 +129,7 @@ void SET::GetQuestFlag(HLERequestContext& ctx) {
rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue()));
}
void SET::GetLanguageCode(HLERequestContext& ctx) {
void ISettingsServer::GetLanguageCode(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue());
IPC::ResponseBuilder rb{ctx, 4};
@@ -115,7 +138,7 @@ void SET::GetLanguageCode(HLERequestContext& ctx) {
available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]);
}
void SET::GetRegionCode(HLERequestContext& ctx) {
void ISettingsServer::GetRegionCode(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
@@ -123,44 +146,21 @@ void SET::GetRegionCode(HLERequestContext& ctx) {
rb.Push(static_cast<u32>(Settings::values.region_index.GetValue()));
}
void SET::GetKeyCodeMap(HLERequestContext& ctx) {
void ISettingsServer::GetKeyCodeMap(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
GetKeyCodeMapImpl(ctx);
}
void SET::GetKeyCodeMap2(HLERequestContext& ctx) {
void ISettingsServer::GetKeyCodeMap2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "Called {}", ctx.Description());
GetKeyCodeMapImpl(ctx);
}
void SET::GetDeviceNickName(HLERequestContext& ctx) {
void ISettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
ctx.WriteBuffer(Settings::values.device_name.GetValue());
}
SET::SET(Core::System& system_) : ServiceFramework{system_, "set"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &SET::GetLanguageCode, "GetLanguageCode"},
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, &SET::MakeLanguageCode, "MakeLanguageCode"},
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
{4, &SET::GetRegionCode, "GetRegionCode"},
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
{7, &SET::GetKeyCodeMap, "GetKeyCodeMap"},
{8, &SET::GetQuestFlag, "GetQuestFlag"},
{9, &SET::GetKeyCodeMap2, "GetKeyCodeMap2"},
{10, nullptr, "GetFirmwareVersionForDebug"},
{11, &SET::GetDeviceNickName, "GetDeviceNickName"},
};
// clang-format on
RegisterHandlers(functions);
}
SET::~SET() = default;
} // namespace Service::Set

View File

@@ -73,10 +73,10 @@ static constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> languag
LanguageCode GetLanguageCodeFromIndex(std::size_t idx);
class SET final : public ServiceFramework<SET> {
class ISettingsServer final : public ServiceFramework<ISettingsServer> {
public:
explicit SET(Core::System& system_);
~SET() override;
explicit ISettingsServer(Core::System& system_);
~ISettingsServer() override;
private:
void GetLanguageCode(HLERequestContext& ctx);

View File

@@ -28,7 +28,7 @@ SystemSettings DefaultSystemSettings() {
.cmu_mode = CmuMode::None,
.tv_underscan = {},
.tv_gama = 1.0f,
.constrast_ratio = 0.5f,
.contrast_ratio = 0.5f,
};
settings.initial_launch_settings_packed = {

View File

@@ -208,7 +208,7 @@ struct TvSettings {
CmuMode cmu_mode;
u32 tv_underscan;
f32 tv_gama;
f32 constrast_ratio;
f32 contrast_ratio;
};
static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size");
@@ -341,7 +341,7 @@ struct SystemSettings {
std::array<u8, 0x3C> reserved_09934;
// nn::settings::system::ErrorReportSharePermission
ErrorReportSharePermission error_report_share_permssion;
ErrorReportSharePermission error_report_share_permission;
std::array<u8, 0x3C> reserved_09974;

View File

@@ -47,10 +47,10 @@ static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is
Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
GetFirmwareVersionType type);
class SET_SYS final : public ServiceFramework<SET_SYS> {
class ISystemSettingsServer final : public ServiceFramework<ISystemSettingsServer> {
public:
explicit SET_SYS(Core::System& system_);
~SET_SYS() override;
explicit ISystemSettingsServer(Core::System& system_);
~ISystemSettingsServer() override;
Result GetSettingsItemValue(std::vector<u8>& out_value, const std::string& category,
const std::string& name);

View File

@@ -71,18 +71,7 @@ size_t Display::GetNumLayers() const {
return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); });
}
Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) {
if (got_vsync_event) {
return ResultPermissionDenied;
}
got_vsync_event = true;
*out_vsync_event = GetVSyncEventUnchecked();
return ResultSuccess;
}
Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
Kernel::KReadableEvent* Display::GetVSyncEvent() {
return &vsync_event->GetReadableEvent();
}

View File

@@ -74,16 +74,8 @@ public:
std::size_t GetNumLayers() const;
/**
* Gets the internal vsync event.
*
* @returns The internal Vsync event if it has not yet been retrieved,
* VI::ResultPermissionDenied otherwise.
*/
[[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event);
/// Gets the internal vsync event.
Kernel::KReadableEvent* GetVSyncEventUnchecked();
Kernel::KReadableEvent* GetVSyncEvent();
/// Signals the internal vsync event.
void SignalVSyncEvent();
@@ -104,7 +96,6 @@ public:
/// Resets the display for a new connection.
void Reset() {
layers.clear();
got_vsync_event = false;
}
/// Attempts to find a layer with the given ID.
@@ -133,7 +124,6 @@ private:
std::vector<std::unique_ptr<Layer>> layers;
Kernel::KEvent* vsync_event{};
bool got_vsync_event{false};
};
} // namespace Service::VI

View File

@@ -343,8 +343,8 @@ private:
class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
public:
explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_)
: ServiceFramework{system_, "IManagerDisplayService"}, nv_flinger{nv_flinger_} {
explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
: ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} {
// clang-format off
static const FunctionInfo functions[] = {
{200, nullptr, "AllocateProcessHeapBlock"},
@@ -440,7 +440,7 @@ private:
IPC::RequestParser rp{ctx};
const u64 display = rp.Pop<u64>();
const Result rc = nv_flinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(rc);
@@ -457,7 +457,7 @@ private:
"(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
unknown, display, aruid);
const auto layer_id = nv_flinger.CreateLayer(display);
const auto layer_id = nvnflinger.CreateLayer(display);
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
IPC::ResponseBuilder rb{ctx, 2};
@@ -494,14 +494,14 @@ private:
rb.Push(ResultSuccess);
}
Nvnflinger::Nvnflinger& nv_flinger;
Nvnflinger::Nvnflinger& nvnflinger;
};
class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
public:
IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_,
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
: ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_},
: ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_},
hos_binder_driver_server{hos_binder_driver_server_} {
static const FunctionInfo functions[] = {
@@ -564,7 +564,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger);
rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger);
}
void GetManagerDisplayService(HLERequestContext& ctx) {
@@ -572,7 +572,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IManagerDisplayService>(system, nv_flinger);
rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger);
}
void GetIndirectDisplayTransactionService(HLERequestContext& ctx) {
@@ -607,7 +607,7 @@ private:
ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
const auto display_id = nv_flinger.OpenDisplay(name);
const auto display_id = nvnflinger.OpenDisplay(name);
if (!display_id) {
LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
IPC::ResponseBuilder rb{ctx, 2};
@@ -624,7 +624,7 @@ private:
IPC::RequestParser rp{ctx};
const u64 display_id = rp.Pop<u64>();
const Result rc = nv_flinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(rc);
@@ -703,7 +703,7 @@ private:
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
const auto display_id = nv_flinger.OpenDisplay(display_name);
const auto display_id = nvnflinger.OpenDisplay(display_name);
if (!display_id) {
LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -711,7 +711,7 @@ private:
return;
}
const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id);
const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id);
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -719,7 +719,7 @@ private:
return;
}
nv_flinger.OpenLayer(layer_id);
nvnflinger.OpenLayer(layer_id);
android::OutputParcel parcel;
parcel.WriteInterface(NativeWindow{*buffer_queue_id});
@@ -737,7 +737,7 @@ private:
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
nv_flinger.CloseLayer(layer_id);
nvnflinger.CloseLayer(layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -753,7 +753,7 @@ private:
// TODO(Subv): What's the difference between a Stray and a Managed layer?
const auto layer_id = nv_flinger.CreateLayer(display_id);
const auto layer_id = nvnflinger.CreateLayer(display_id);
if (!layer_id) {
LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -761,7 +761,7 @@ private:
return;
}
const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id);
const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
if (!buffer_queue_id) {
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
@@ -785,7 +785,7 @@ private:
const u64 layer_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
nv_flinger.DestroyLayer(layer_id);
nvnflinger.DestroyLayer(layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -798,7 +798,7 @@ private:
LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
Kernel::KReadableEvent* vsync_event{};
const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id);
const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id);
if (result != ResultSuccess) {
if (result == ResultNotFound) {
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
@@ -808,6 +808,12 @@ private:
rb.Push(result);
return;
}
if (vsync_event_fetched) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(VI::ResultPermissionDenied);
return;
}
vsync_event_fetched = true;
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
@@ -899,8 +905,9 @@ private:
}
}
Nvnflinger::Nvnflinger& nv_flinger;
Nvnflinger::Nvnflinger& nvnflinger;
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
bool vsync_event_fetched{false};
};
static bool IsValidServiceAccess(Permission permission, Policy policy) {
@@ -916,7 +923,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
}
void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
Nvnflinger::Nvnflinger& nv_flinger,
Nvnflinger::Nvnflinger& nvnflinger,
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
Permission permission) {
IPC::RequestParser rp{ctx};
@@ -931,19 +938,19 @@ void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server);
rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server);
}
void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger,
void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService(
"vi:m", std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server));
"vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server));
server_manager->RegisterNamedService(
"vi:s", std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server));
"vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server));
server_manager->RegisterNamedService(
"vi:u", std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server));
"vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server));
ServerManager::RunServer(std::move(server_manager));
}

View File

@@ -48,7 +48,7 @@ void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
Permission permission);
} // namespace detail
void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nv_flinger,
void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
} // namespace Service::VI

View File

@@ -130,6 +130,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) {
if (aruid_data.flag.is_assigned) {
aruid_data.shared_memory_format = nullptr;
aruid_data.flag.is_assigned.Assign(false);
shared_memory_holder[index].Finalize();
}
}

View File

@@ -1344,4 +1344,49 @@ AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id
};
}
Result NPad::SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set,
Core::HID::NpadButton button_assignment) {
std::scoped_lock lock{mutex};
return npad_resource.SetNpadCaptureButtonAssignment(aruid, npad_style_set, button_assignment);
}
Result NPad::ClearNpadCaptureButtonAssignment(u64 aruid) {
std::scoped_lock lock{mutex};
return npad_resource.ClearNpadCaptureButtonAssignment(aruid);
}
std::size_t NPad::GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list,
u64 aruid) const {
std::scoped_lock lock{mutex};
return npad_resource.GetNpadCaptureButtonAssignment(out_list, aruid);
}
Result NPad::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) {
std::scoped_lock lock{mutex};
const auto result = npad_resource.SetNpadSystemExtStateEnabled(aruid, is_enabled);
if (result.IsSuccess()) {
std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex};
// TODO: abstracted_pad->EnableAppletToGetInput(aruid);
}
return result;
}
Result NPad::AssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) {
std::scoped_lock lock{mutex};
bool is_currently_enabled{};
Result result = npad_resource.IsAssigningSingleOnSlSrPressEnabled(is_currently_enabled, aruid);
if (result.IsSuccess() && is_enabled != is_currently_enabled) {
result = npad_resource.SetAssigningSingleOnSlSrPress(aruid, is_enabled);
}
return result;
}
Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const {
std::scoped_lock lock{mutex};
out_npad_id = hid_core.GetLastActiveController();
return ResultSuccess;
}
} // namespace Service::HID

View File

@@ -149,6 +149,18 @@ public:
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set,
Core::HID::NpadButton button_assignment);
Result ClearNpadCaptureButtonAssignment(u64 aruid);
std::size_t GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list,
u64 aruid) const;
Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled);
Result AssigningSingleOnSlSrPress(u64 aruid, bool is_enabled);
Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const;
private:
struct VibrationData {
bool device_mounted{};

View File

@@ -55,6 +55,7 @@ add_library(video_core STATIC
engines/maxwell_dma.h
engines/puller.cpp
engines/puller.h
framebuffer_config.cpp
framebuffer_config.h
fsr.cpp
fsr.h
@@ -116,6 +117,8 @@ add_library(video_core STATIC
renderer_null/renderer_null.h
renderer_opengl/blit_image.cpp
renderer_opengl/blit_image.h
renderer_opengl/gl_blit_screen.cpp
renderer_opengl/gl_blit_screen.h
renderer_opengl/gl_buffer_cache_base.cpp
renderer_opengl/gl_buffer_cache.cpp
renderer_opengl/gl_buffer_cache.h

View File

@@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "video_core/framebuffer_config.h"
namespace Tegra {
Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
u32 texture_height) {
f32 left, top, right, bottom;
if (!framebuffer.crop_rect.IsEmpty()) {
// If crop rectangle is not empty, apply properties from rectangle.
left = static_cast<f32>(framebuffer.crop_rect.left);
top = static_cast<f32>(framebuffer.crop_rect.top);
right = static_cast<f32>(framebuffer.crop_rect.right);
bottom = static_cast<f32>(framebuffer.crop_rect.bottom);
} else {
// Otherwise, fall back to framebuffer dimensions.
left = 0;
top = 0;
right = static_cast<f32>(framebuffer.width);
bottom = static_cast<f32>(framebuffer.height);
}
// Apply transformation flags.
auto framebuffer_transform_flags = framebuffer.transform_flags;
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
// Switch left and right.
std::swap(left, right);
}
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
// Switch top and bottom.
std::swap(top, bottom);
}
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
if (True(framebuffer_transform_flags)) {
UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
static_cast<u32>(framebuffer_transform_flags));
}
// Normalize coordinate space.
left /= static_cast<f32>(texture_width);
top /= static_cast<f32>(texture_height);
right /= static_cast<f32>(texture_width);
bottom /= static_cast<f32>(texture_height);
return Common::Rectangle<f32>(left, top, right, bottom);
}
} // namespace Tegra

View File

@@ -24,4 +24,7 @@ struct FramebufferConfig {
Common::Rectangle<int> crop_rect;
};
Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
u32 texture_height);
} // namespace Tegra

View File

@@ -155,12 +155,6 @@ public:
virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<const u8> memory) = 0;
/// Attempt to use a faster method to display the framebuffer to screen
[[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
return false;
}
/// Increase/decrease the number of object in pages touching the specified region
virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {}

View File

@@ -94,10 +94,6 @@ bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surfac
}
void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<const u8> memory) {}
bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
return true;
}
void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) {}
void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {

View File

@@ -78,8 +78,6 @@ public:
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<const u8> memory) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) override;
void InitializeChannel(Tegra::Control::ChannelState& channel) override;

View File

@@ -0,0 +1,517 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "video_core/framebuffer_config.h"
#include "video_core/host_shaders/ffx_a_h.h"
#include "video_core/host_shaders/ffx_fsr1_h.h"
#include "video_core/host_shaders/full_screen_triangle_vert.h"
#include "video_core/host_shaders/fxaa_frag.h"
#include "video_core/host_shaders/fxaa_vert.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h"
#include "video_core/host_shaders/opengl_present_frag.h"
#include "video_core/host_shaders/opengl_present_scaleforce_frag.h"
#include "video_core/host_shaders/opengl_present_vert.h"
#include "video_core/host_shaders/opengl_smaa_glsl.h"
#include "video_core/host_shaders/present_bicubic_frag.h"
#include "video_core/host_shaders/present_gaussian_frag.h"
#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h"
#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h"
#include "video_core/host_shaders/smaa_edge_detection_frag.h"
#include "video_core/host_shaders/smaa_edge_detection_vert.h"
#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h"
#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h"
#include "video_core/renderer_opengl/gl_blit_screen.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_state_tracker.h"
#include "video_core/smaa_area_tex.h"
#include "video_core/smaa_search_tex.h"
#include "video_core/textures/decoders.h"
namespace OpenGL {
namespace {
constexpr GLint PositionLocation = 0;
constexpr GLint TexCoordLocation = 1;
constexpr GLint ModelViewMatrixLocation = 0;
struct ScreenRectVertex {
constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v)
: position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {}
std::array<GLfloat, 2> position;
std::array<GLfloat, 2> tex_coord;
};
/**
* Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
* corner and (width, height) on the lower-bottom.
*
* The projection part of the matrix is trivial, hence these operations are represented
* by a 3x2 matrix.
*/
std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
// clang-format off
matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
// Last matrix row is implicitly assumed to be [0, 0, 1].
// clang-format on
return matrix;
}
} // namespace
BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_,
StateTracker& state_tracker_, ProgramManager& program_manager_,
Device& device_)
: rasterizer(rasterizer_), cpu_memory(cpu_memory_), state_tracker(state_tracker_),
program_manager(program_manager_), device(device_) {
// Create shader programs
fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER);
fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER);
const auto replace_include = [](std::string& shader_source, std::string_view include_name,
std::string_view include_content) {
const std::string include_string = fmt::format("#include \"{}\"", include_name);
const std::size_t pos = shader_source.find(include_string);
ASSERT(pos != std::string::npos);
shader_source.replace(pos, include_string.size(), include_content);
};
const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) {
std::string shader_source{specialized_source};
replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL);
return CreateProgram(shader_source, stage);
};
smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER);
smaa_edge_detection_frag =
SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER);
smaa_blending_weight_calculation_vert =
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER);
smaa_blending_weight_calculation_frag =
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER);
smaa_neighborhood_blending_vert =
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER);
smaa_neighborhood_blending_frag =
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER);
present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
present_gaussian_fragment =
CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER);
present_scaleforce_fragment =
CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
GL_FRAGMENT_SHADER);
std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG};
replace_include(fsr_source, "ffx_a.h", HostShaders::FFX_A_H);
replace_include(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H);
std::string fsr_easu_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG};
std::string fsr_rcas_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG};
replace_include(fsr_easu_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
replace_include(fsr_rcas_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
fsr = std::make_unique<FSR>(HostShaders::FULL_SCREEN_TRIANGLE_VERT, fsr_easu_frag_source,
fsr_rcas_frag_source);
// Generate presentation sampler
present_sampler.Create();
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
present_sampler_nn.Create();
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Generate VBO handle for drawing
vertex_buffer.Create();
// Attach vertex data to VAO
glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
// Allocate textures for the screen
framebuffer_texture.resource.Create(GL_TEXTURE_2D);
const GLuint texture = framebuffer_texture.resource.handle;
glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
// Clear screen to black
const u8 framebuffer_data[4] = {0, 0, 0, 0};
glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE,
framebuffer_data);
aa_framebuffer.Create();
smaa_area_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT);
glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG,
GL_UNSIGNED_BYTE, areaTexBytes);
smaa_search_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT);
glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED,
GL_UNSIGNED_BYTE, searchTexBytes);
// Enable unified vertex attributes and query vertex buffer address when the driver supports it
if (device.HasVertexBufferUnifiedMemory()) {
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
&vertex_buffer_address);
}
}
FramebufferTextureInfo BlitScreen::PrepareRenderTarget(
const Tegra::FramebufferConfig& framebuffer) {
// If framebuffer is provided, reload it from memory to a texture
if (framebuffer_texture.width != static_cast<GLsizei>(framebuffer.width) ||
framebuffer_texture.height != static_cast<GLsizei>(framebuffer.height) ||
framebuffer_texture.pixel_format != framebuffer.pixel_format ||
gl_framebuffer_data.empty()) {
// Reallocate texture if the framebuffer size has changed.
// This is expected to not happen very often and hence should not be a
// performance problem.
ConfigureFramebufferTexture(framebuffer);
}
// Load the framebuffer from memory if needed
return LoadFBToScreenInfo(framebuffer);
}
FramebufferTextureInfo BlitScreen::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) {
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
const auto accelerated_info =
rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
if (accelerated_info) {
return *accelerated_info;
}
// Reset the screen info's display texture to its own permanent texture
FramebufferTextureInfo info{};
info.display_texture = framebuffer_texture.resource.handle;
info.width = framebuffer.width;
info.height = framebuffer.height;
// TODO(Rodrigo): Read this from HLE
constexpr u32 block_height_log2 = 4;
const auto pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
const u64 size_in_bytes{Tegra::Texture::CalculateSize(
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
const u8* const host_ptr{cpu_memory.GetPointer(framebuffer_addr)};
const std::span<const u8> input_data(host_ptr, size_in_bytes);
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
framebuffer.width, framebuffer.height, 1, block_height_log2,
0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
// Update existing texture
// TODO: Test what happens on hardware when you change the framebuffer dimensions so that
// they differ from the LCD resolution.
// TODO: Applications could theoretically crash yuzu here by specifying too large
// framebuffer sizes. We should make sure that this cannot happen.
glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width,
framebuffer.height, framebuffer_texture.gl_format,
framebuffer_texture.gl_type, gl_framebuffer_data.data());
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
return info;
}
void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) {
framebuffer_texture.width = framebuffer.width;
framebuffer_texture.height = framebuffer.height;
framebuffer_texture.pixel_format = framebuffer.pixel_format;
const auto pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height *
bytes_per_pixel);
GLint internal_format;
switch (framebuffer.pixel_format) {
case Service::android::PixelFormat::Rgba8888:
internal_format = GL_RGBA8;
framebuffer_texture.gl_format = GL_RGBA;
framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case Service::android::PixelFormat::Rgb565:
internal_format = GL_RGB565;
framebuffer_texture.gl_format = GL_RGB;
framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
break;
default:
internal_format = GL_RGBA8;
framebuffer_texture.gl_format = GL_RGBA;
framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
// UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
// static_cast<u32>(framebuffer.pixel_format));
break;
}
framebuffer_texture.resource.Release();
framebuffer_texture.resource.Create(GL_TEXTURE_2D);
glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format,
framebuffer_texture.width, framebuffer_texture.height);
aa_texture.Release();
aa_texture.Create(GL_TEXTURE_2D);
glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
smaa_edges_tex.Release();
smaa_edges_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
smaa_blend_tex.Release();
smaa_blend_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
}
void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout& layout) {
FramebufferTextureInfo info = PrepareRenderTarget(framebuffer);
const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
// TODO: Signal state tracker about these changes
state_tracker.NotifyScreenDrawVertexArray();
state_tracker.NotifyPolygonModes();
state_tracker.NotifyViewport0();
state_tracker.NotifyScissor0();
state_tracker.NotifyColorMask(0);
state_tracker.NotifyBlend0();
state_tracker.NotifyFramebuffer();
state_tracker.NotifyFrontFace();
state_tracker.NotifyCullTest();
state_tracker.NotifyDepthTest();
state_tracker.NotifyStencilTest();
state_tracker.NotifyPolygonOffset();
state_tracker.NotifyRasterizeEnable();
state_tracker.NotifyFramebufferSRGB();
state_tracker.NotifyLogicOp();
state_tracker.NotifyClipControl();
state_tracker.NotifyAlphaTest();
state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
glEnable(GL_CULL_FACE);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_RASTERIZER_DISCARD);
glDisable(GL_ALPHA_TEST);
glDisablei(GL_BLEND, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthRangeIndexed(0, 0.0, 0.0);
glBindTextureUnit(0, info.display_texture);
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing);
anti_aliasing = Settings::AntiAliasing::None;
Settings::values.anti_aliasing.SetValue(anti_aliasing);
}
if (anti_aliasing != Settings::AntiAliasing::None) {
glEnablei(GL_SCISSOR_TEST, 0);
auto viewport_width = Settings::values.resolution_info.ScaleUp(framebuffer.width);
auto viewport_height = Settings::values.resolution_info.ScaleUp(framebuffer.height);
glScissorIndexed(0, 0, 0, viewport_width, viewport_height);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
static_cast<GLfloat>(viewport_height));
glBindSampler(0, present_sampler.handle);
GLint old_read_fb;
GLint old_draw_fb;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
switch (anti_aliasing) {
case Settings::AntiAliasing::Fxaa: {
program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} break;
case Settings::AntiAliasing::Smaa: {
glClearColor(0, 0, 0, 0);
glFrontFace(GL_CCW);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
glBindSampler(1, present_sampler.handle);
glBindSampler(2, present_sampler.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
smaa_edges_tex.handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle,
smaa_edge_detection_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindTextureUnit(0, smaa_edges_tex.handle);
glBindTextureUnit(1, smaa_area_tex.handle);
glBindTextureUnit(2, smaa_search_tex.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
smaa_blend_tex.handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle,
smaa_blending_weight_calculation_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindTextureUnit(0, info.display_texture);
glBindTextureUnit(1, smaa_blend_tex.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
aa_texture.handle, 0);
program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle,
smaa_neighborhood_blending_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glFrontFace(GL_CW);
} break;
default:
UNREACHABLE();
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
glBindTextureUnit(0, aa_texture.handle);
}
glDisablei(GL_SCISSOR_TEST, 0);
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
if (!fsr->AreBuffersInitialized()) {
fsr->InitBuffers();
}
const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width);
const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height);
glBindSampler(0, present_sampler.handle);
fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop);
} else {
if (fsr->AreBuffersInitialized()) {
fsr->ReleaseBuffers();
}
}
const std::array ortho_matrix =
MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
const auto fragment_handle = [this]() {
switch (Settings::values.scaling_filter.GetValue()) {
case Settings::ScalingFilter::NearestNeighbor:
case Settings::ScalingFilter::Bilinear:
return present_bilinear_fragment.handle;
case Settings::ScalingFilter::Bicubic:
return present_bicubic_fragment.handle;
case Settings::ScalingFilter::Gaussian:
return present_gaussian_fragment.handle;
case Settings::ScalingFilter::ScaleForce:
return present_scaleforce_fragment.handle;
case Settings::ScalingFilter::Fsr:
return fsr->GetPresentFragmentProgram().handle;
default:
return present_bilinear_fragment.handle;
}
}();
program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
ortho_matrix.data());
f32 left, top, right, bottom;
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
// FSR has already applied the crop, so we just want to render the image
// it has produced.
left = 0;
top = 0;
right = 1;
bottom = 1;
} else {
// Apply the precomputed crop.
left = crop.left;
top = crop.top;
right = crop.right;
bottom = crop.bottom;
}
// Map the coordinates to the screen.
const auto& screen = layout.screen;
const auto x = screen.left;
const auto y = screen.top;
const auto w = screen.GetWidth();
const auto h = screen.GetHeight();
const std::array vertices = {
ScreenRectVertex(x, y, left, top),
ScreenRectVertex(x + w, y, right, top),
ScreenRectVertex(x, y + h, left, bottom),
ScreenRectVertex(x + w, y + h, right, bottom),
};
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
glDisable(GL_FRAMEBUFFER_SRGB);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
static_cast<GLfloat>(layout.height));
glEnableVertexAttribArray(PositionLocation);
glEnableVertexAttribArray(TexCoordLocation);
glVertexAttribDivisor(PositionLocation, 0);
glVertexAttribDivisor(TexCoordLocation, 0);
glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
offsetof(ScreenRectVertex, position));
glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
offsetof(ScreenRectVertex, tex_coord));
glVertexAttribBinding(PositionLocation, 0);
glVertexAttribBinding(TexCoordLocation, 0);
if (device.HasVertexBufferUnifiedMemory()) {
glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
sizeof(vertices));
} else {
glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
}
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
glBindSampler(0, present_sampler.handle);
} else {
glBindSampler(0, present_sampler_nn.handle);
}
// Update background color before drawing
glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
Settings::values.bg_green.GetValue() / 255.0f,
Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// TODO
// program_manager.RestoreGuestPipeline();
}
} // namespace OpenGL

View File

@@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <vector>
#include "core/hle/service/nvnflinger/pixel_format.h"
#include "video_core/renderer_opengl/gl_fsr.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
namespace Core::Memory {
class Memory;
}
namespace Layout {
struct FramebufferLayout;
}
namespace Tegra {
struct FramebufferConfig;
}
namespace OpenGL {
class Device;
class RasterizerOpenGL;
class StateTracker;
/// Structure used for storing information about the textures for the Switch screen
struct TextureInfo {
OGLTexture resource;
GLsizei width;
GLsizei height;
GLenum gl_format;
GLenum gl_type;
Service::android::PixelFormat pixel_format;
};
/// Structure used for storing information about the display target for the Switch screen
struct FramebufferTextureInfo {
GLuint display_texture{};
u32 width;
u32 height;
};
class BlitScreen {
public:
explicit BlitScreen(RasterizerOpenGL& rasterizer, Core::Memory::Memory& cpu_memory,
StateTracker& state_tracker, ProgramManager& program_manager,
Device& device);
void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer);
/// Draws the emulated screens to the emulator window.
void DrawScreen(const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout& layout);
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
/// Loads framebuffer from emulated memory into the active OpenGL texture.
FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer);
private:
RasterizerOpenGL& rasterizer;
Core::Memory::Memory& cpu_memory;
StateTracker& state_tracker;
ProgramManager& program_manager;
Device& device;
OGLSampler present_sampler;
OGLSampler present_sampler_nn;
OGLBuffer vertex_buffer;
OGLProgram fxaa_vertex;
OGLProgram fxaa_fragment;
OGLProgram present_vertex;
OGLProgram present_bilinear_fragment;
OGLProgram present_bicubic_fragment;
OGLProgram present_gaussian_fragment;
OGLProgram present_scaleforce_fragment;
/// Display information for Switch screen
TextureInfo framebuffer_texture;
OGLTexture aa_texture;
OGLFramebuffer aa_framebuffer;
OGLProgram smaa_edge_detection_vert;
OGLProgram smaa_blending_weight_calculation_vert;
OGLProgram smaa_neighborhood_blending_vert;
OGLProgram smaa_edge_detection_frag;
OGLProgram smaa_blending_weight_calculation_frag;
OGLProgram smaa_neighborhood_blending_frag;
OGLTexture smaa_area_tex;
OGLTexture smaa_search_tex;
OGLTexture smaa_edges_tex;
OGLTexture smaa_blend_tex;
std::unique_ptr<FSR> fsr;
/// OpenGL framebuffer data
std::vector<u8> gl_framebuffer_data;
// GPU address of the vertex buffer
GLuint64EXT vertex_buffer_address = 0;
};
} // namespace OpenGL

View File

@@ -25,7 +25,7 @@ FSR::~FSR() = default;
void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
u32 input_image_width, u32 input_image_height,
const Common::Rectangle<int>& crop_rect) {
const Common::Rectangle<f32>& crop_rect) {
const auto output_image_width = screen.GetWidth();
const auto output_image_height = screen.GetHeight();
@@ -57,14 +57,19 @@ void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& sc
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width),
static_cast<GLfloat>(output_image_height));
FsrConstants constants;
FsrEasuConOffset(
constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12,
const f32 input_width = static_cast<f32>(input_image_width);
const f32 input_height = static_cast<f32>(input_image_height);
const f32 output_width = static_cast<f32>(screen.GetWidth());
const f32 output_height = static_cast<f32>(screen.GetHeight());
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
const f32 viewport_x = crop_rect.left * input_width;
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height;
const f32 viewport_y = crop_rect.top * input_height;
static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()),
static_cast<f32>(input_image_width), static_cast<f32>(input_image_height),
static_cast<f32>(output_image_width), static_cast<f32>(output_image_height),
static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top));
FsrConstants constants;
FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8,
constants.data() + 12, viewport_width, viewport_height, input_width,
input_height, output_width, output_height, viewport_x, viewport_y);
glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants));

View File

@@ -22,7 +22,7 @@ public:
void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
u32 input_image_width, u32 input_image_height,
const Common::Rectangle<int>& crop_rect);
const Common::Rectangle<f32>& crop_rect);
void InitBuffers();

View File

@@ -71,9 +71,8 @@ std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Core::Memory::Memory& cpu_memory_, const Device& device_,
ScreenInfo& screen_info_, ProgramManager& program_manager_,
StateTracker& state_tracker_)
: RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_), screen_info(screen_info_),
ProgramManager& program_manager_, StateTracker& state_tracker_)
: RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_),
program_manager(program_manager_), state_tracker(state_tracker_),
texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
texture_cache(texture_cache_runtime, *this),
@@ -738,10 +737,10 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
query_cache.InvalidateRegion(*cpu_addr, copy_size);
}
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
std::optional<FramebufferTextureInfo> RasterizerOpenGL::AccelerateDisplay(
const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, u32 pixel_stride) {
if (framebuffer_addr == 0) {
return false;
return {};
}
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
@@ -749,16 +748,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
ImageView* const image_view{
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
if (!image_view) {
return false;
return {};
}
// Verify that the cached surface is the same size and format as the requested framebuffer
// ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
// ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
screen_info.texture.width = image_view->size.width;
screen_info.texture.height = image_view->size.height;
screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
return true;
FramebufferTextureInfo info{};
info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
info.width = image_view->size.width;
info.height = image_view->size.height;
return info;
}
void RasterizerOpenGL::SyncState() {

View File

@@ -17,6 +17,7 @@
#include "video_core/rasterizer_accelerated.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/blit_image.h"
#include "video_core/renderer_opengl/gl_blit_screen.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_device.h"
#include "video_core/renderer_opengl/gl_fence_manager.h"
@@ -38,7 +39,7 @@ class MemoryManager;
namespace OpenGL {
struct ScreenInfo;
struct FramebufferTextureInfo;
struct ShaderEntries;
struct BindlessSSBO {
@@ -77,8 +78,7 @@ class RasterizerOpenGL : public VideoCore::RasterizerAccelerated,
public:
explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Core::Memory::Memory& cpu_memory_, const Device& device_,
ScreenInfo& screen_info_, ProgramManager& program_manager_,
StateTracker& state_tracker_);
ProgramManager& program_manager_, StateTracker& state_tracker_);
~RasterizerOpenGL() override;
void Draw(bool is_indexed, u32 instance_count) override;
@@ -123,8 +123,6 @@ public:
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<const u8> memory) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -145,6 +143,10 @@ public:
return true;
}
std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr,
u32 pixel_stride);
private:
static constexpr size_t MAX_TEXTURES = 192;
static constexpr size_t MAX_IMAGES = 48;
@@ -237,7 +239,6 @@ private:
Tegra::GPU& gpu;
const Device& device;
ScreenInfo& screen_info;
ProgramManager& program_manager;
StateTracker& state_tracker;

View File

@@ -17,68 +17,16 @@
#include "core/frontend/emu_window.h"
#include "core/memory.h"
#include "core/telemetry_session.h"
#include "video_core/host_shaders/ffx_a_h.h"
#include "video_core/host_shaders/ffx_fsr1_h.h"
#include "video_core/host_shaders/full_screen_triangle_vert.h"
#include "video_core/host_shaders/fxaa_frag.h"
#include "video_core/host_shaders/fxaa_vert.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h"
#include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h"
#include "video_core/host_shaders/opengl_present_frag.h"
#include "video_core/host_shaders/opengl_present_scaleforce_frag.h"
#include "video_core/host_shaders/opengl_present_vert.h"
#include "video_core/host_shaders/opengl_smaa_glsl.h"
#include "video_core/host_shaders/present_bicubic_frag.h"
#include "video_core/host_shaders/present_gaussian_frag.h"
#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h"
#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h"
#include "video_core/host_shaders/smaa_edge_detection_frag.h"
#include "video_core/host_shaders/smaa_edge_detection_vert.h"
#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h"
#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h"
#include "video_core/renderer_opengl/gl_blit_screen.h"
#include "video_core/renderer_opengl/gl_fsr.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/smaa_area_tex.h"
#include "video_core/smaa_search_tex.h"
#include "video_core/textures/decoders.h"
namespace OpenGL {
namespace {
constexpr GLint PositionLocation = 0;
constexpr GLint TexCoordLocation = 1;
constexpr GLint ModelViewMatrixLocation = 0;
struct ScreenRectVertex {
constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v)
: position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {}
std::array<GLfloat, 2> position;
std::array<GLfloat, 2> tex_coord;
};
/**
* Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
* corner and (width, height) on the lower-bottom.
*
* The projection part of the matrix is trivial, hence these operations are represented
* by a 3x2 matrix.
*/
std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
// clang-format off
matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
// Last matrix row is implicitly assumed to be [0, 0, 1].
// clang-format on
return matrix;
}
const char* GetSource(GLenum source) {
switch (source) {
case GL_DEBUG_SOURCE_API:
@@ -149,14 +97,13 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, device{emu_window_},
state_tracker{}, program_manager{device},
rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) {
rasterizer(emu_window, gpu, cpu_memory, device, program_manager, state_tracker) {
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(DebugHandler, nullptr);
}
AddTelemetryFields();
InitOpenGLObjects();
// Initialize default attributes to match hardware's disabled attributes
GLint max_attribs{};
@@ -168,14 +115,8 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
// Enable unified vertex attributes and query vertex buffer address when the driver supports it
if (device.HasVertexBufferUnifiedMemory()) {
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
&vertex_buffer_address);
}
blit_screen = std::make_unique<BlitScreen>(rasterizer, cpu_memory, state_tracker,
program_manager, device);
}
RendererOpenGL::~RendererOpenGL() = default;
@@ -184,11 +125,11 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (!framebuffer) {
return;
}
PrepareRendertarget(framebuffer);
RenderScreenshot();
RenderScreenshot(*framebuffer);
state_tracker.BindFramebuffer(0);
DrawScreen(emu_window.GetFramebufferLayout());
blit_screen->DrawScreen(*framebuffer, emu_window.GetFramebufferLayout());
++m_current_frame;
@@ -199,172 +140,6 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
render_window.OnFrameDisplayed();
}
void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {
if (!framebuffer) {
return;
}
// If framebuffer is provided, reload it from memory to a texture
if (screen_info.texture.width != static_cast<GLsizei>(framebuffer->width) ||
screen_info.texture.height != static_cast<GLsizei>(framebuffer->height) ||
screen_info.texture.pixel_format != framebuffer->pixel_format ||
gl_framebuffer_data.empty()) {
// Reallocate texture if the framebuffer size has changed.
// This is expected to not happen very often and hence should not be a
// performance problem.
ConfigureFramebufferTexture(screen_info.texture, *framebuffer);
}
// Load the framebuffer from memory, draw it to the screen, and swap buffers
LoadFBToScreenInfo(*framebuffer);
}
void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) {
// Framebuffer orientation handling
framebuffer_transform_flags = framebuffer.transform_flags;
framebuffer_crop_rect = framebuffer.crop_rect;
framebuffer_width = framebuffer.width;
framebuffer_height = framebuffer.height;
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
screen_info.was_accelerated =
rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
if (screen_info.was_accelerated) {
return;
}
// Reset the screen info's display texture to its own permanent texture
screen_info.display_texture = screen_info.texture.resource.handle;
// TODO(Rodrigo): Read this from HLE
constexpr u32 block_height_log2 = 4;
const auto pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
const u64 size_in_bytes{Tegra::Texture::CalculateSize(
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
const u8* const host_ptr{cpu_memory.GetPointer(framebuffer_addr)};
const std::span<const u8> input_data(host_ptr, size_in_bytes);
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
framebuffer.width, framebuffer.height, 1, block_height_log2,
0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
// Update existing texture
// TODO: Test what happens on hardware when you change the framebuffer dimensions so that
// they differ from the LCD resolution.
// TODO: Applications could theoretically crash yuzu here by specifying too large
// framebuffer sizes. We should make sure that this cannot happen.
glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width,
framebuffer.height, screen_info.texture.gl_format,
screen_info.texture.gl_type, gl_framebuffer_data.data());
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture) {
const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
}
void RendererOpenGL::InitOpenGLObjects() {
// Create shader programs
fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER);
fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER);
const auto replace_include = [](std::string& shader_source, std::string_view include_name,
std::string_view include_content) {
const std::string include_string = fmt::format("#include \"{}\"", include_name);
const std::size_t pos = shader_source.find(include_string);
ASSERT(pos != std::string::npos);
shader_source.replace(pos, include_string.size(), include_content);
};
const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) {
std::string shader_source{specialized_source};
replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL);
return CreateProgram(shader_source, stage);
};
smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER);
smaa_edge_detection_frag =
SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER);
smaa_blending_weight_calculation_vert =
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER);
smaa_blending_weight_calculation_frag =
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER);
smaa_neighborhood_blending_vert =
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER);
smaa_neighborhood_blending_frag =
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER);
present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
present_gaussian_fragment =
CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER);
present_scaleforce_fragment =
CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
GL_FRAGMENT_SHADER);
std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG};
replace_include(fsr_source, "ffx_a.h", HostShaders::FFX_A_H);
replace_include(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H);
std::string fsr_easu_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG};
std::string fsr_rcas_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG};
replace_include(fsr_easu_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
replace_include(fsr_rcas_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source);
fsr = std::make_unique<FSR>(HostShaders::FULL_SCREEN_TRIANGLE_VERT, fsr_easu_frag_source,
fsr_rcas_frag_source);
// Generate presentation sampler
present_sampler.Create();
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
present_sampler_nn.Create();
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Generate VBO handle for drawing
vertex_buffer.Create();
// Attach vertex data to VAO
glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
// Allocate textures for the screen
screen_info.texture.resource.Create(GL_TEXTURE_2D);
const GLuint texture = screen_info.texture.resource.handle;
glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
screen_info.display_texture = screen_info.texture.resource.handle;
// Clear screen to black
LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
aa_framebuffer.Create();
smaa_area_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT);
glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG,
GL_UNSIGNED_BYTE, areaTexBytes);
smaa_search_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT);
glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED,
GL_UNSIGNED_BYTE, searchTexBytes);
}
void RendererOpenGL::AddTelemetryFields() {
const char* const gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
const char* const gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
@@ -380,328 +155,7 @@ void RendererOpenGL::AddTelemetryFields() {
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
}
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer) {
texture.width = framebuffer.width;
texture.height = framebuffer.height;
texture.pixel_format = framebuffer.pixel_format;
const auto pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
gl_framebuffer_data.resize(texture.width * texture.height * bytes_per_pixel);
GLint internal_format;
switch (framebuffer.pixel_format) {
case Service::android::PixelFormat::Rgba8888:
internal_format = GL_RGBA8;
texture.gl_format = GL_RGBA;
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case Service::android::PixelFormat::Rgb565:
internal_format = GL_RGB565;
texture.gl_format = GL_RGB;
texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
break;
default:
internal_format = GL_RGBA8;
texture.gl_format = GL_RGBA;
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
// UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
// static_cast<u32>(framebuffer.pixel_format));
break;
}
texture.resource.Release();
texture.resource.Create(GL_TEXTURE_2D);
glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
aa_texture.Release();
aa_texture.Create(GL_TEXTURE_2D);
glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
smaa_edges_tex.Release();
smaa_edges_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
smaa_blend_tex.Release();
smaa_blend_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
}
void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
// TODO: Signal state tracker about these changes
state_tracker.NotifyScreenDrawVertexArray();
state_tracker.NotifyPolygonModes();
state_tracker.NotifyViewport0();
state_tracker.NotifyScissor0();
state_tracker.NotifyColorMask(0);
state_tracker.NotifyBlend0();
state_tracker.NotifyFramebuffer();
state_tracker.NotifyFrontFace();
state_tracker.NotifyCullTest();
state_tracker.NotifyDepthTest();
state_tracker.NotifyStencilTest();
state_tracker.NotifyPolygonOffset();
state_tracker.NotifyRasterizeEnable();
state_tracker.NotifyFramebufferSRGB();
state_tracker.NotifyLogicOp();
state_tracker.NotifyClipControl();
state_tracker.NotifyAlphaTest();
state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
glEnable(GL_CULL_FACE);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_RASTERIZER_DISCARD);
glDisable(GL_ALPHA_TEST);
glDisablei(GL_BLEND, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthRangeIndexed(0, 0.0, 0.0);
glBindTextureUnit(0, screen_info.display_texture);
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing);
anti_aliasing = Settings::AntiAliasing::None;
Settings::values.anti_aliasing.SetValue(anti_aliasing);
}
if (anti_aliasing != Settings::AntiAliasing::None) {
glEnablei(GL_SCISSOR_TEST, 0);
auto viewport_width = screen_info.texture.width;
auto scissor_width = framebuffer_crop_rect.GetWidth();
if (scissor_width <= 0) {
scissor_width = viewport_width;
}
auto viewport_height = screen_info.texture.height;
auto scissor_height = framebuffer_crop_rect.GetHeight();
if (scissor_height <= 0) {
scissor_height = viewport_height;
}
if (screen_info.was_accelerated) {
viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height);
scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height);
}
glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
static_cast<GLfloat>(viewport_height));
glBindSampler(0, present_sampler.handle);
GLint old_read_fb;
GLint old_draw_fb;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
switch (anti_aliasing) {
case Settings::AntiAliasing::Fxaa: {
program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} break;
case Settings::AntiAliasing::Smaa: {
glClearColor(0, 0, 0, 0);
glFrontFace(GL_CCW);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle);
glBindSampler(1, present_sampler.handle);
glBindSampler(2, present_sampler.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
smaa_edges_tex.handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle,
smaa_edge_detection_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindTextureUnit(0, smaa_edges_tex.handle);
glBindTextureUnit(1, smaa_area_tex.handle);
glBindTextureUnit(2, smaa_search_tex.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
smaa_blend_tex.handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle,
smaa_blending_weight_calculation_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindTextureUnit(0, screen_info.display_texture);
glBindTextureUnit(1, smaa_blend_tex.handle);
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
aa_texture.handle, 0);
program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle,
smaa_neighborhood_blending_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glFrontFace(GL_CW);
} break;
default:
UNREACHABLE();
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
glBindTextureUnit(0, aa_texture.handle);
}
glDisablei(GL_SCISSOR_TEST, 0);
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
if (!fsr->AreBuffersInitialized()) {
fsr->InitBuffers();
}
auto crop_rect = framebuffer_crop_rect;
if (crop_rect.GetWidth() == 0) {
crop_rect.right = framebuffer_width;
}
if (crop_rect.GetHeight() == 0) {
crop_rect.bottom = framebuffer_height;
}
crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width);
const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height);
glBindSampler(0, present_sampler.handle);
fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect);
} else {
if (fsr->AreBuffersInitialized()) {
fsr->ReleaseBuffers();
}
}
const std::array ortho_matrix =
MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
const auto fragment_handle = [this]() {
switch (Settings::values.scaling_filter.GetValue()) {
case Settings::ScalingFilter::NearestNeighbor:
case Settings::ScalingFilter::Bilinear:
return present_bilinear_fragment.handle;
case Settings::ScalingFilter::Bicubic:
return present_bicubic_fragment.handle;
case Settings::ScalingFilter::Gaussian:
return present_gaussian_fragment.handle;
case Settings::ScalingFilter::ScaleForce:
return present_scaleforce_fragment.handle;
case Settings::ScalingFilter::Fsr:
return fsr->GetPresentFragmentProgram().handle;
default:
return present_bilinear_fragment.handle;
}
}();
program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
ortho_matrix.data());
const auto& texcoords = screen_info.display_texcoords;
auto left = texcoords.left;
auto right = texcoords.right;
if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) {
if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) {
// Flip the framebuffer vertically
left = texcoords.right;
right = texcoords.left;
} else {
// Other transformations are unsupported
LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}",
framebuffer_transform_flags);
UNIMPLEMENTED();
}
}
ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented");
f32 left_start{};
if (framebuffer_crop_rect.Top() > 0) {
left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
static_cast<f32>(framebuffer_crop_rect.Bottom());
}
f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width);
f32 scale_v =
static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height);
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) {
// Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
// (e.g. handheld mode) on a 1920x1080 framebuffer.
if (framebuffer_crop_rect.GetWidth() > 0) {
scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
static_cast<f32>(screen_info.texture.width);
}
if (framebuffer_crop_rect.GetHeight() > 0) {
scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
static_cast<f32>(screen_info.texture.height);
}
}
if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa &&
!screen_info.was_accelerated) {
scale_u /= Settings::values.resolution_info.up_factor;
scale_v /= Settings::values.resolution_info.up_factor;
}
const auto& screen = layout.screen;
const std::array vertices = {
ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u,
left_start + left * scale_v),
ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u,
left_start + left * scale_v),
ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u,
left_start + right * scale_v),
ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u,
left_start + right * scale_v),
};
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
glDisable(GL_FRAMEBUFFER_SRGB);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
static_cast<GLfloat>(layout.height));
glEnableVertexAttribArray(PositionLocation);
glEnableVertexAttribArray(TexCoordLocation);
glVertexAttribDivisor(PositionLocation, 0);
glVertexAttribDivisor(TexCoordLocation, 0);
glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
offsetof(ScreenRectVertex, position));
glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
offsetof(ScreenRectVertex, tex_coord));
glVertexAttribBinding(PositionLocation, 0);
glVertexAttribBinding(TexCoordLocation, 0);
if (device.HasVertexBufferUnifiedMemory()) {
glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
sizeof(vertices));
} else {
glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
}
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
glBindSampler(0, present_sampler.handle);
} else {
glBindSampler(0, present_sampler_nn.handle);
}
// Update background color before drawing
glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
Settings::values.bg_green.GetValue() / 255.0f,
Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// TODO
// program_manager.RestoreGuestPipeline();
}
void RendererOpenGL::RenderScreenshot() {
void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
if (!renderer_settings.screenshot_requested) {
return;
}
@@ -723,7 +177,7 @@ void RendererOpenGL::RenderScreenshot() {
glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
DrawScreen(layout);
blit_screen->DrawScreen(framebuffer, layout);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);

View File

@@ -25,37 +25,13 @@ namespace Core::Frontend {
class EmuWindow;
}
namespace Core::Memory {
class Memory;
}
namespace Layout {
struct FramebufferLayout;
}
namespace Tegra {
class GPU;
}
namespace OpenGL {
/// Structure used for storing information about the textures for the Switch screen
struct TextureInfo {
OGLTexture resource;
GLsizei width;
GLsizei height;
GLenum gl_format;
GLenum gl_type;
Service::android::PixelFormat pixel_format;
};
/// Structure used for storing information about the display target for the Switch screen
struct ScreenInfo {
GLuint display_texture{};
bool was_accelerated = false;
const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
TextureInfo texture;
};
class BlitScreen;
class RendererOpenGL final : public VideoCore::RendererBase {
public:
@@ -76,28 +52,8 @@ public:
}
private:
/// Initializes the OpenGL state and creates persistent objects.
void InitOpenGLObjects();
void AddTelemetryFields();
void ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer);
/// Draws the emulated screens to the emulator window.
void DrawScreen(const Layout::FramebufferLayout& layout);
void RenderScreenshot();
/// Loads framebuffer from emulated memory into the active OpenGL texture.
void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
/// Fills active OpenGL texture with the given RGB color.Since the color is solid, the texture
/// can be 1x1 but will stretch across whatever it's rendered on.
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture);
void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer);
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
Core::TelemetrySession& telemetry_session;
Core::Frontend::EmuWindow& emu_window;
@@ -108,49 +64,9 @@ private:
StateTracker state_tracker;
ProgramManager program_manager;
RasterizerOpenGL rasterizer;
// OpenGL object IDs
OGLSampler present_sampler;
OGLSampler present_sampler_nn;
OGLBuffer vertex_buffer;
OGLProgram fxaa_vertex;
OGLProgram fxaa_fragment;
OGLProgram present_vertex;
OGLProgram present_bilinear_fragment;
OGLProgram present_bicubic_fragment;
OGLProgram present_gaussian_fragment;
OGLProgram present_scaleforce_fragment;
OGLFramebuffer screenshot_framebuffer;
// GPU address of the vertex buffer
GLuint64EXT vertex_buffer_address = 0;
/// Display information for Switch screen
ScreenInfo screen_info;
OGLTexture aa_texture;
OGLFramebuffer aa_framebuffer;
OGLProgram smaa_edge_detection_vert;
OGLProgram smaa_blending_weight_calculation_vert;
OGLProgram smaa_neighborhood_blending_vert;
OGLProgram smaa_edge_detection_frag;
OGLProgram smaa_blending_weight_calculation_frag;
OGLProgram smaa_neighborhood_blending_frag;
OGLTexture smaa_area_tex;
OGLTexture smaa_search_tex;
OGLTexture smaa_edges_tex;
OGLTexture smaa_blend_tex;
std::unique_ptr<FSR> fsr;
/// OpenGL framebuffer data
std::vector<u8> gl_framebuffer_data;
/// Used for transforming the framebuffer orientation
Service::android::BufferTransformFlags framebuffer_transform_flags{};
Common::Rectangle<int> framebuffer_crop_rect;
u32 framebuffer_width;
u32 framebuffer_height;
std::unique_ptr<BlitScreen> blit_screen;
};
} // namespace OpenGL

View File

@@ -98,9 +98,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
surface),
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
scheduler, screen_info),
rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator,
state_tracker, scheduler) {
scheduler),
rasterizer(render_window, gpu, cpu_memory, device, memory_allocator, state_tracker,
scheduler) {
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
turbo_mode.emplace(instance, dld);
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
@@ -124,17 +124,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (!render_window.IsShown()) {
return;
}
// Update screen info if the framebuffer size has changed.
screen_info.width = framebuffer->width;
screen_info.height = framebuffer->height;
const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
const bool use_accelerated =
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
RenderScreenshot(*framebuffer, use_accelerated);
RenderScreenshot(*framebuffer);
Frame* frame = present_manager.GetRenderFrame();
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated);
blit_screen.DrawToSwapchain(rasterizer, frame, *framebuffer);
scheduler.Flush(*frame->render_ready);
present_manager.Present(frame);
@@ -168,8 +161,7 @@ void RendererVulkan::Report() const {
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
}
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer,
bool use_accelerated) {
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
if (!renderer_settings.screenshot_requested) {
return;
}
@@ -221,7 +213,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
});
const VkExtent2D render_area{.width = layout.width, .height = layout.height};
const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area);
blit_screen.Draw(framebuffer, *screenshot_fb, layout, render_area, use_accelerated);
blit_screen.Draw(rasterizer, framebuffer, *screenshot_fb, layout, render_area);
const auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4);
const VkBufferCreateInfo dst_buffer_info{

View File

@@ -59,7 +59,7 @@ public:
private:
void Report() const;
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated);
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
Core::TelemetrySession& telemetry_session;
Core::Memory::Memory& cpu_memory;
@@ -72,8 +72,6 @@ private:
vk::DebugUtilsMessenger debug_messenger;
vk::SurfaceKHR surface;
ScreenInfo screen_info;
Device device;
MemoryAllocator memory_allocator;
StateTracker state_tracker;

View File

@@ -124,10 +124,10 @@ struct BlitScreen::BufferData {
BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWindow& render_window_,
const Device& device_, MemoryAllocator& memory_allocator_,
Swapchain& swapchain_, PresentManager& present_manager_,
Scheduler& scheduler_, const ScreenInfo& screen_info_)
Scheduler& scheduler_)
: cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
scheduler{scheduler_}, image_count{swapchain.GetImageCount()} {
resource_ticks.resize(image_count);
swapchain_view_format = swapchain.GetImageViewFormat();
@@ -137,56 +137,6 @@ BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWin
BlitScreen::~BlitScreen() = default;
static Common::Rectangle<f32> NormalizeCrop(const Tegra::FramebufferConfig& framebuffer,
const ScreenInfo& screen_info) {
f32 left, top, right, bottom;
if (!framebuffer.crop_rect.IsEmpty()) {
// If crop rectangle is not empty, apply properties from rectangle.
left = static_cast<f32>(framebuffer.crop_rect.left);
top = static_cast<f32>(framebuffer.crop_rect.top);
right = static_cast<f32>(framebuffer.crop_rect.right);
bottom = static_cast<f32>(framebuffer.crop_rect.bottom);
} else {
// Otherwise, fall back to framebuffer dimensions.
left = 0;
top = 0;
right = static_cast<f32>(framebuffer.width);
bottom = static_cast<f32>(framebuffer.height);
}
// Apply transformation flags.
auto framebuffer_transform_flags = framebuffer.transform_flags;
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
// Switch left and right.
std::swap(left, right);
}
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
// Switch top and bottom.
std::swap(top, bottom);
}
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
if (True(framebuffer_transform_flags)) {
UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
static_cast<u32>(framebuffer_transform_flags));
}
// Get the screen properties.
const f32 screen_width = static_cast<f32>(screen_info.width);
const f32 screen_height = static_cast<f32>(screen_info.height);
// Normalize coordinate space.
left /= screen_width;
top /= screen_height;
right /= screen_width;
bottom /= screen_height;
return Common::Rectangle<f32>(left, top, right, bottom);
}
void BlitScreen::Recreate() {
present_manager.WaitPresent();
scheduler.Finish();
@@ -194,9 +144,16 @@ void BlitScreen::Recreate() {
CreateDynamicResources();
}
void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
VkExtent2D render_area, bool use_accelerated) {
VkExtent2D render_area) {
const auto texture_info = rasterizer.AccelerateDisplay(
framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride);
const u32 texture_width = texture_info ? texture_info->width : framebuffer.width;
const u32 texture_height = texture_info ? texture_info->height : framebuffer.height;
const bool use_accelerated = texture_info.has_value();
RefreshResources(framebuffer);
// Finish any pending renderpass
@@ -205,13 +162,13 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
scheduler.Wait(resource_ticks[image_index]);
resource_ticks[image_index] = scheduler.CurrentTick();
VkImage source_image = use_accelerated ? screen_info.image : *raw_images[image_index];
VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index];
VkImageView source_image_view =
use_accelerated ? screen_info.image_view : *raw_image_views[image_index];
texture_info ? texture_info->image_view : *raw_image_views[image_index];
BufferData data;
SetUniformData(data, layout);
SetVertexData(data, framebuffer, layout);
SetVertexData(data, framebuffer, layout, texture_width, texture_height);
const std::span<u8> mapped_span = buffer.Mapped();
std::memcpy(mapped_span.data(), &data, sizeof(data));
@@ -404,10 +361,10 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
}
if (fsr) {
const auto crop_rect = NormalizeCrop(framebuffer, screen_info);
const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
const VkExtent2D fsr_input_size{
.width = Settings::values.resolution_info.ScaleUp(screen_info.width),
.height = Settings::values.resolution_info.ScaleUp(screen_info.height),
.width = Settings::values.resolution_info.ScaleUp(texture_width),
.height = Settings::values.resolution_info.ScaleUp(texture_height),
};
VkImageView fsr_image_view =
fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect);
@@ -479,8 +436,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
});
}
void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
bool use_accelerated) {
void BlitScreen::DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
const Tegra::FramebufferConfig& framebuffer) {
// Recreate dynamic resources if the the image count or input format changed
const VkFormat current_framebuffer_format =
std::exchange(framebuffer_view_format, GetFormat(framebuffer));
@@ -499,7 +456,7 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f
}
const VkExtent2D render_area{frame->width, frame->height};
Draw(framebuffer, *frame->framebuffer, layout, render_area, use_accelerated);
Draw(rasterizer, framebuffer, *frame->framebuffer, layout, render_area);
if (++image_index >= image_count) {
image_index = 0;
}
@@ -1433,7 +1390,8 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou
}
void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout layout) const {
const Layout::FramebufferLayout layout, u32 texture_width,
u32 texture_height) const {
f32 left, top, right, bottom;
if (fsr) {
@@ -1445,7 +1403,7 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
bottom = 1;
} else {
// Get the normalized crop rectangle.
const auto crop = NormalizeCrop(framebuffer, screen_info);
const auto crop = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
// Apply the crop.
left = crop.left;

View File

@@ -35,8 +35,6 @@ enum class PixelFormat : u32;
namespace Vulkan {
struct ScreenInfo;
class Device;
class FSR;
class RasterizerVulkan;
@@ -47,7 +45,7 @@ class PresentManager;
struct Frame;
struct ScreenInfo {
struct FramebufferTextureInfo {
VkImage image{};
VkImageView image_view{};
u32 width{};
@@ -58,17 +56,17 @@ class BlitScreen {
public:
explicit BlitScreen(Core::Memory::Memory& cpu_memory, Core::Frontend::EmuWindow& render_window,
const Device& device, MemoryAllocator& memory_manager, Swapchain& swapchain,
PresentManager& present_manager, Scheduler& scheduler,
const ScreenInfo& screen_info);
PresentManager& present_manager, Scheduler& scheduler);
~BlitScreen();
void Recreate();
void Draw(const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer,
const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated);
void Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
VkExtent2D render_area);
void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
bool use_accelerated);
void DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
const Tegra::FramebufferConfig& framebuffer);
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
VkExtent2D extent);
@@ -101,7 +99,8 @@ private:
void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout layout) const;
const Layout::FramebufferLayout layout, u32 texture_width,
u32 texture_height) const;
void CreateSMAA(VkExtent2D smaa_size);
void CreateFSR();
@@ -118,7 +117,6 @@ private:
Scheduler& scheduler;
std::size_t image_count;
std::size_t image_index{};
const ScreenInfo& screen_info;
vk::ShaderModule vertex_shader;
vk::ShaderModule fxaa_vertex_shader;

View File

@@ -163,10 +163,10 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
} // Anonymous namespace
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_,
const Device& device_, MemoryAllocator& memory_allocator_,
StateTracker& state_tracker_, Scheduler& scheduler_)
: RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, screen_info{screen_info_}, device{device_},
Core::Memory::Memory& cpu_memory_, const Device& device_,
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
Scheduler& scheduler_)
: RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, device{device_},
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler),
@@ -781,23 +781,25 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
query_cache.InvalidateRegion(*cpu_addr, copy_size);
}
bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, u32 pixel_stride) {
if (!framebuffer_addr) {
return false;
return {};
}
std::scoped_lock lock{texture_cache.mutex};
ImageView* const image_view =
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
if (!image_view) {
return false;
return {};
}
query_cache.NotifySegment(false);
screen_info.image = image_view->ImageHandle();
screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D);
screen_info.width = image_view->size.width;
screen_info.height = image_view->size.height;
return true;
FramebufferTextureInfo info{};
info.image = image_view->ImageHandle();
info.image_view = image_view->Handle(Shader::TextureType::Color2D);
info.width = image_view->size.width;
info.height = image_view->size.height;
return info;
}
void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_loading,

View File

@@ -40,7 +40,7 @@ class Maxwell3D;
namespace Vulkan {
struct ScreenInfo;
struct FramebufferTextureInfo;
class StateTracker;
@@ -74,9 +74,9 @@ class RasterizerVulkan final : public VideoCore::RasterizerAccelerated,
protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
public:
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_,
const Device& device_, MemoryAllocator& memory_allocator_,
StateTracker& state_tracker_, Scheduler& scheduler_);
Core::Memory::Memory& cpu_memory_, const Device& device_,
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
Scheduler& scheduler_);
~RasterizerVulkan() override;
void Draw(bool is_indexed, u32 instance_count) override;
@@ -122,8 +122,6 @@ public:
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
std::span<const u8> memory) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) override;
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -133,6 +131,10 @@ public:
void ReleaseChannel(s32 channel_id) override;
std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr,
u32 pixel_stride);
private:
static constexpr size_t MAX_TEXTURES = 192;
static constexpr size_t MAX_IMAGES = 48;
@@ -177,7 +179,6 @@ private:
Tegra::GPU& gpu;
ScreenInfo& screen_info;
const Device& device;
MemoryAllocator& memory_allocator;
StateTracker& state_tracker;

View File

@@ -46,7 +46,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/set/set_sys.h"
#include "core/hle/service/set/system_settings_server.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "yuzu/multiplayer/state.h"