mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-19 19:15:26 +00:00
Merge branch 'master' into alcGetString
This commit is contained in:
commit
0dd74675f2
92 changed files with 879 additions and 848 deletions
|
@ -145,6 +145,8 @@ export MACOSX_DEPLOYMENT_TARGET=14.0
|
|||
-DCMAKE_SYSTEM_PROCESSOR=arm64 \
|
||||
-DCMAKE_TOOLCHAIN_FILE=buildfiles/cmake/TCDarwinARM64.cmake \
|
||||
-DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
|
||||
-G Ninja
|
||||
|
||||
"$BREW_PATH/bin/ninja"; build_status=$?;
|
||||
|
|
|
@ -108,6 +108,8 @@ export MACOSX_DEPLOYMENT_TARGET=14.0
|
|||
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
||||
-DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \
|
||||
-DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
|
||||
-G Ninja
|
||||
|
||||
"$BREW_PATH/bin/ninja"; build_status=$?;
|
||||
|
|
|
@ -25,6 +25,13 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
|||
# Remove libvulkan because it causes issues with gamescope
|
||||
rm -f ./AppDir/usr/lib/libvulkan.so*
|
||||
|
||||
# Remove unused Qt6 libraries
|
||||
rm -f ./AppDir/usr/lib/libQt6OpenGL.so*
|
||||
rm -f ./AppDir/usr/lib/libQt6Qml*.so*
|
||||
rm -f ./AppDir/usr/lib/libQt6Quick.so*
|
||||
rm -f ./AppDir/usr/lib/libQt6VirtualKeyboard.so*
|
||||
rm -f ./AppDir/usr/plugins/platforminputcontexts/libqtvirtualkeyboardplugin.so*
|
||||
|
||||
# Remove git directory containing local commit history file
|
||||
rm -rf ./AppDir/usr/share/rpcs3/git
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ QT_SVG_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtsvg${QT_SUFFIX}"
|
|||
LLVMLIBS_URL="https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-${LLVM_VER}/llvmlibs_mt.7z"
|
||||
GLSLANG_URL='https://github.com/RPCS3/glslang/releases/latest/download/glslanglibs_mt.7z'
|
||||
VULKAN_SDK_URL="https://www.dropbox.com/scl/fi/sjjh0fc4ld281pjbl2xzu/VulkanSDK-${VULKAN_VER}-Installer.exe?rlkey=f6wzc0lvms5vwkt2z3qabfv9d&dl=1"
|
||||
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.10.2/ccache-4.10.2-windows-x86_64.zip"
|
||||
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.11.2/ccache-4.11.2-windows-x86_64.zip"
|
||||
|
||||
DEP_URLS=" \
|
||||
$QT_BASE_URL \
|
||||
|
|
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
@ -16,4 +16,4 @@ Submitting your test results for Commercial Games must be done on our forums. Pl
|
|||
|
||||
# Contributing
|
||||
|
||||
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.me/RPCS3) in the **#development** channel.
|
||||
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.gg/rpcs3) in the **#development** channel.
|
||||
|
|
|
@ -7,7 +7,7 @@ body:
|
|||
attributes:
|
||||
value: |
|
||||
# Summary
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
- type: textarea
|
||||
id: quick-summary
|
||||
attributes:
|
||||
|
@ -50,7 +50,7 @@ body:
|
|||
* Completely close RPCS3 and locate the log file.
|
||||
|
||||
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
|
||||
* On Windows it will be in the RPCS3 directory near the executable
|
||||
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
|
||||
* On Linux it will be in ```~/.cache/rpcs3/```
|
||||
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.
|
||||
- type: textarea
|
||||
|
|
4
.github/ISSUE_TEMPLATE/2-bug-report.yml
vendored
4
.github/ISSUE_TEMPLATE/2-bug-report.yml
vendored
|
@ -7,7 +7,7 @@ body:
|
|||
attributes:
|
||||
value: |
|
||||
# Summary
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
- type: textarea
|
||||
id: quick-summary
|
||||
attributes:
|
||||
|
@ -36,7 +36,7 @@ body:
|
|||
* Completely close RPCS3 and locate the log file.
|
||||
|
||||
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
|
||||
* On Windows it will be in the RPCS3 directory near the executable
|
||||
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
|
||||
* On Linux it will be in ```~/.cache/rpcs3/```
|
||||
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.
|
||||
- type: textarea
|
||||
|
|
4
.github/ISSUE_TEMPLATE/3-feature-request.yml
vendored
4
.github/ISSUE_TEMPLATE/3-feature-request.yml
vendored
|
@ -6,7 +6,7 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
- type: textarea
|
||||
id: quick-summary
|
||||
attributes:
|
||||
|
@ -31,6 +31,6 @@ body:
|
|||
* If this feature is something that a game is trying to use, upload a log file for it.
|
||||
|
||||
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
|
||||
* On Windows it will be in the RPCS3 directory near the executable
|
||||
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
|
||||
* On Linux it will be in ```~/.cache/rpcs3/```
|
||||
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.
|
||||
|
|
2
.github/ISSUE_TEMPLATE/4-advanced.md
vendored
2
.github/ISSUE_TEMPLATE/4-advanced.md
vendored
|
@ -7,7 +7,7 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
## Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
## Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
|
||||
|
||||
You're using the advanced template. You're expected to know what to write in order to fill in all the required information for proper report.
|
||||
|
||||
|
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -4,7 +4,7 @@ contact_links:
|
|||
url: https://rpcs3.net/quickstart
|
||||
about: Everything you need to know to install and configure emulator, and add games
|
||||
- name: Ask for help
|
||||
url: https://discord.me/RPCS3
|
||||
url: https://discord.gg/rpcs3
|
||||
about: If you have some questions or need help, please use our Discord server instead of GitHub
|
||||
- name: Report game compatibility
|
||||
url: https://forums.rpcs3.net/thread-196671.html
|
||||
|
|
18
.github/PR-BUILD.md
vendored
18
.github/PR-BUILD.md
vendored
|
@ -1,18 +0,0 @@
|
|||
## How to test a PR build
|
||||
|
||||
Please take into account, that RPCS3 build usually takes some time (about 15 mins), so you can't access a build if a PR was just submitted.
|
||||
|
||||
- Open a PR you want to test
|
||||
- Scroll to the very bottom and locate the **Checks** section
|
||||
- Click on **Show all checks**
|
||||
You are supposed to see something like this
|
||||

|
||||
- Click on __Details__ on either **Cirrus Linux GCC** or **Cirrus Windows**
|
||||
- Click **View more details on Cirrus CI** at the very bottom
|
||||

|
||||
- Click on the download button for **Artifact** on the **Artifacts** block
|
||||

|
||||
|
||||
- Congratulations! You are now downloading an RPCS3 build for that specific PR.
|
||||
|
||||
__Please note that PR builds are not supposed to be stable because they contain new changesets.__
|
3
.github/PULL_REQUEST_TEMPLATE/1-default.md
vendored
3
.github/PULL_REQUEST_TEMPLATE/1-default.md
vendored
|
@ -1,3 +0,0 @@
|
|||
<!-- Please include a summary of the change and which issue is fixed. -->
|
||||
|
||||
[How to test this PR](.github/PR-BUILD.md)
|
8
.github/workflows/rpcs3.yml
vendored
8
.github/workflows/rpcs3.yml
vendored
|
@ -25,17 +25,17 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.3"
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.4"
|
||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||
compiler: clang
|
||||
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
|
||||
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
|
||||
- os: ubuntu-24.04
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.3"
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.4"
|
||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||
compiler: gcc
|
||||
- os: ubuntu-24.04-arm
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.3"
|
||||
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.4"
|
||||
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
||||
compiler: clang
|
||||
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
|
||||
|
@ -111,7 +111,7 @@ jobs:
|
|||
LLVM_VER: '19.1.7'
|
||||
VULKAN_VER: '1.3.268.0'
|
||||
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||
CCACHE_SHA: '6252f081876a9a9f700fae13a5aec5d0d486b28261d7f1f72ac11c7ad9df4da9'
|
||||
CCACHE_SHA: '1f39f3ad5aae3fe915e99ad1302633bc8f6718e58fa7c0de2b0ba7e080f0f08c'
|
||||
CCACHE_BIN_DIR: 'C:\ccache_bin'
|
||||
CCACHE_DIR: 'C:\ccache'
|
||||
CCACHE_INODECACHE: 'true'
|
||||
|
|
2
3rdparty/FAudio
vendored
2
3rdparty/FAudio
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 486e33eef3f282e4ce3d29f32ded3e67bacdbe5c
|
||||
Subproject commit 091c6b4693ce507ac48037836a5a884e35cd2860
|
1
3rdparty/MoltenVK/CMakeLists.txt
vendored
1
3rdparty/MoltenVK/CMakeLists.txt
vendored
|
@ -1,4 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(moltenvk NONE)
|
||||
include(ExternalProject)
|
||||
|
||||
|
|
2
3rdparty/OpenAL/openal-soft
vendored
2
3rdparty/OpenAL/openal-soft
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 90191edd20bb877c5cbddfdac7ec0fe49ad93727
|
||||
Subproject commit dc7d7054a5b4f3bec1dc23a42fd616a0847af948
|
2
3rdparty/discord-rpc/CMakeLists.txt
vendored
2
3rdparty/discord-rpc/CMakeLists.txt
vendored
|
@ -9,5 +9,7 @@ if (USE_DISCORD_RPC AND (WIN32 OR CMAKE_SYSTEM MATCHES "Linux" OR APPLE))
|
|||
set(WARNINGS_AS_ERRORS FALSE CACHE BOOL "When enabled, compiles with `-Werror` (on *nix platforms).")
|
||||
|
||||
add_subdirectory(discord-rpc EXCLUDE_FROM_ALL)
|
||||
target_include_directories(3rdparty_discordRPC INTERFACE discord-rpc/include)
|
||||
target_compile_definitions(3rdparty_discordRPC INTERFACE -DWITH_DISCORD_RPC)
|
||||
target_link_libraries(3rdparty_discordRPC INTERFACE discord-rpc)
|
||||
endif()
|
||||
|
|
2
3rdparty/discord-rpc/discord-rpc
vendored
2
3rdparty/discord-rpc/discord-rpc
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 171b2142ac8acdf016c231e36dc7a8d48daff19c
|
||||
Subproject commit 3dc2c326cb4dc5815c6069970c13154898f58d48
|
2
3rdparty/libsdl-org/SDL
vendored
2
3rdparty/libsdl-org/SDL
vendored
|
@ -1 +1 @@
|
|||
Subproject commit f6864924f76e1a0b4abaefc76ae2ed22b1a8916e
|
||||
Subproject commit 877399b2b2cf21e67554ed9046410f268ce1d1b2
|
2
3rdparty/libusb/CMakeLists.txt
vendored
2
3rdparty/libusb/CMakeLists.txt
vendored
|
@ -1,5 +1,3 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(libusb)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.16.9)
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
project(rpcs3 LANGUAGES C CXX)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ RPCS3
|
|||
[](https://dev.azure.com/nekotekina/nekotekina/_build?definitionId=8&_a=summary&repositoryFilter=4)
|
||||
[](https://cirrus-ci.com/github/RPCS3/rpcs3)
|
||||
[](https://github.com/RPCS3/rpcs3/actions/workflows/rpcs3.yml)
|
||||
[](https://discord.me/rpcs3)
|
||||
[](https://discord.gg/rpcs3)
|
||||
|
||||
The world's first free and open-source PlayStation 3 emulator/debugger, written in C++ for Windows, Linux, macOS and FreeBSD.
|
||||
|
||||
|
@ -34,7 +34,7 @@ See [BUILDING.md](BUILDING.md) for more information about how to setup an enviro
|
|||
|
||||
Check our friendly [quickstart](https://rpcs3.net/quickstart) guide to make sure your computer meets the minimum system requirements to run RPCS3.
|
||||
|
||||
Don't forget to have your graphics driver up to date and to install the [Visual C++ Redistributable Packages for Visual Studio 2019](https://aka.ms/vs/16/release/VC_redist.x64.exe) if you are a Windows user.
|
||||
Don't forget to have your graphics driver up to date and to install the [Visual C++ Redistributable Packages for Visual Studio 2022](https://aka.ms/vs/17/release/VC_redist.x64.exe) if you are a Windows user.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ jobs:
|
|||
# displayName: ccache
|
||||
|
||||
# - bash: |
|
||||
# docker pull --quiet rpcs3/rpcs3-ci-jammy:1.3
|
||||
# docker pull --quiet rpcs3/rpcs3-ci-jammy:1.4
|
||||
# docker run \
|
||||
# -v $(pwd):/rpcs3 \
|
||||
# --env-file .ci/docker.env \
|
||||
# -v $CCACHE_DIR:/root/.ccache \
|
||||
# -v $BUILD_ARTIFACTSTAGINGDIRECTORY:/root/artifacts \
|
||||
# rpcs3/rpcs3-ci-jammy:1.3 \
|
||||
# rpcs3/rpcs3-ci-jammy:1.4 \
|
||||
# /rpcs3/.ci/build-linux.sh
|
||||
# displayName: Docker setup and build
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||
RSX/Overlays/overlay_trophy_notification.cpp
|
||||
RSX/Overlays/overlay_user_list_dialog.cpp
|
||||
RSX/Overlays/overlay_utils.cpp
|
||||
RSX/Overlays/overlay_video.cpp
|
||||
RSX/Overlays/Shaders/shader_loading_dialog.cpp
|
||||
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
|
||||
RSX/Program/CgBinaryFragmentProgram.cpp
|
||||
|
|
|
@ -195,7 +195,7 @@ struct audio_port
|
|||
// Handle copy ctor of atomic var
|
||||
audio_port(const audio_port& r)
|
||||
{
|
||||
std::memcpy(this, &r, sizeof(r));
|
||||
std::memcpy(static_cast<void*>(this), &r, sizeof(r));
|
||||
}
|
||||
|
||||
ENABLE_BITWISE_SERIALIZATION;
|
||||
|
|
|
@ -244,7 +244,7 @@ static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir,
|
|||
continue;
|
||||
}
|
||||
|
||||
SaveDataEntry save_entry;
|
||||
SaveDataEntry save_entry {};
|
||||
save_entry.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
|
||||
save_entry.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
|
||||
save_entry.title = psf::get_string(psf, "TITLE");
|
||||
|
@ -307,7 +307,7 @@ static error_code select_and_delete(ppu_thread& ppu)
|
|||
// Display a blocking Save Data List asynchronously in the GUI thread.
|
||||
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
|
||||
{
|
||||
selected = save_dialog->ShowSaveDataList(save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
}
|
||||
|
||||
// Reschedule after a blocking dialog returns
|
||||
|
@ -326,7 +326,7 @@ static error_code select_and_delete(ppu_thread& ppu)
|
|||
focused = save_entries.empty() ? -1 : selected;
|
||||
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
const SaveDataEntry& entry = ::at32(save_entries, selected);
|
||||
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
|
||||
|
||||
// Reusable display message string
|
||||
|
@ -760,7 +760,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
|
||||
result->userdata = userdata; // probably should be assigned only once (allows the callback to change it)
|
||||
|
||||
SaveDataEntry save_entry;
|
||||
SaveDataEntry save_entry {};
|
||||
|
||||
if (setList)
|
||||
{
|
||||
|
@ -820,7 +820,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
break;
|
||||
}
|
||||
|
||||
SaveDataEntry save_entry2;
|
||||
SaveDataEntry save_entry2 {};
|
||||
save_entry2.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
|
||||
save_entry2.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
|
||||
save_entry2.title = psf::get_string(psf, "TITLE");
|
||||
|
@ -1183,7 +1183,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
// Display a blocking Save Data List asynchronously in the GUI thread.
|
||||
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
|
||||
{
|
||||
selected = save_dialog->ShowSaveDataList(save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1214,8 +1214,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
else
|
||||
{
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
message = get_confirmation_message(operation, entry);
|
||||
message = get_confirmation_message(operation, ::at32(save_entries, selected));
|
||||
}
|
||||
|
||||
// Yield before a blocking dialog is being spawned
|
||||
|
@ -1345,14 +1344,14 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
|||
else
|
||||
{
|
||||
// Get information from the selected entry
|
||||
SaveDataEntry entry = save_entries[selected];
|
||||
message = get_confirmation_message(operation, entry);
|
||||
message = get_confirmation_message(operation, ::at32(save_entries, selected));
|
||||
}
|
||||
|
||||
// Yield before a blocking dialog is being spawned
|
||||
lv2_obj::sleep(ppu);
|
||||
|
||||
// Get user confirmation by opening a blocking dialog
|
||||
// TODO: show fixedSet->newIcon
|
||||
s32 return_code = CELL_MSGDIALOG_BUTTON_NONE;
|
||||
error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(message), msg_dialog_source::_cellSaveData, vm::null, vm::null, vm::null, &return_code);
|
||||
|
||||
|
|
|
@ -361,5 +361,5 @@ class SaveDialogBase
|
|||
public:
|
||||
virtual ~SaveDialogBase();
|
||||
|
||||
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
|
||||
virtual s32 ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
|
||||
};
|
||||
|
|
|
@ -4956,9 +4956,9 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||
return +code_ptr;
|
||||
}
|
||||
|
||||
constexpr auto abs_diff = [](u64 a, u64 b) { return a <= b ? b - a : a - b; };
|
||||
[[maybe_unused]] constexpr auto abs_diff = [](u64 a, u64 b) { return a <= b ? b - a : a - b; };
|
||||
|
||||
auto write_le = [](u8*& code, auto value)
|
||||
[[maybe_unused]] auto write_le = [](u8*& code, auto value)
|
||||
{
|
||||
write_to_ptr<le_t<std::remove_cvref_t<decltype(value)>>>(code, value);
|
||||
code += sizeof(value);
|
||||
|
@ -5823,7 +5823,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
|
|||
min_addr = std::min<u32>(min_addr, mod_func.addr);
|
||||
|
||||
// Translate
|
||||
if (const auto func = translator.Translate(mod_func))
|
||||
if ([[maybe_unused]] const auto func = translator.Translate(mod_func))
|
||||
{
|
||||
#ifdef ARCH_X64 // TODO
|
||||
// Run optimization passes
|
||||
|
@ -5841,7 +5841,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
|
|||
// Run this only in one module for all functions compiled
|
||||
if (module_part.jit_bounds)
|
||||
{
|
||||
if (const auto func = translator.GetSymbolResolver(module_part))
|
||||
if ([[maybe_unused]] const auto func = translator.GetSymbolResolver(module_part))
|
||||
{
|
||||
#ifdef ARCH_X64 // TODO
|
||||
// Run optimization passes
|
||||
|
|
|
@ -1290,7 +1290,7 @@ void PPUTranslator::VMADDFP(ppu_opcode_t op)
|
|||
void PPUTranslator::VMAXFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
|
||||
set_vr(op.vd, vec_handle_result(bitcast<f32[4]>(bitcast<u32[4]>(fmax(a, b)) & bitcast<u32[4]>(fmax(b, a)))));
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a < b) | fcmp_uno(b != b), b, a)));
|
||||
}
|
||||
|
||||
void PPUTranslator::VMAXSB(ppu_opcode_t op)
|
||||
|
@ -1352,7 +1352,7 @@ void PPUTranslator::VMHRADDSHS(ppu_opcode_t op)
|
|||
void PPUTranslator::VMINFP(ppu_opcode_t op)
|
||||
{
|
||||
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
|
||||
set_vr(op.vd, vec_handle_result(bitcast<f32[4]>(bitcast<u32[4]>(fmin(a, b)) | bitcast<u32[4]>(fmin(b, a)))));
|
||||
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a > b) | fcmp_uno(b != b), b, a)));
|
||||
}
|
||||
|
||||
void PPUTranslator::VMINSB(ppu_opcode_t op)
|
||||
|
|
|
@ -1237,7 +1237,7 @@ void spu_thread::dump_regs(std::string& ret, std::any& /*custom_data*/) const
|
|||
|
||||
if (const_value != r)
|
||||
{
|
||||
// Expectation of pretictable code path has not been met (such as a branch directly to the instruction)
|
||||
// Expectation of predictable code path has not been met (such as a branch directly to the instruction)
|
||||
is_const = false;
|
||||
}
|
||||
|
||||
|
@ -1447,7 +1447,7 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
|
|||
if (v != v128::from32r(addr))
|
||||
{
|
||||
// 1) Non-zero lower words are invalid (because BRSL-like instructions generate only zeroes)
|
||||
// 2) Bits normally masked out by indirect braches are considered invalid
|
||||
// 2) Bits normally masked out by indirect branches are considered invalid
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -752,6 +752,22 @@ void PadHandlerBase::process()
|
|||
|
||||
pad->move_data.orientation_enabled = b_has_orientation && device->config && device->config->orientation_enabled.get();
|
||||
|
||||
// Disable pad vibration if no new data was sent for 3 seconds
|
||||
if (pad->m_last_rumble_time_us > 0)
|
||||
{
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
if ((get_system_time() - pad->m_last_rumble_time_us) > 3'000'000)
|
||||
{
|
||||
for (VibrateMotor& motor : pad->m_vibrateMotors)
|
||||
{
|
||||
motor.m_value = 0;
|
||||
}
|
||||
|
||||
pad->m_last_rumble_time_us = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const connection status = update_connection(device);
|
||||
|
||||
switch (status)
|
||||
|
|
|
@ -522,6 +522,8 @@ struct Pad
|
|||
s32 m_orientation_reset_button_index{-1}; // Special button index. -1 if not set.
|
||||
bool get_orientation_reset_button_active();
|
||||
|
||||
u64 m_last_rumble_time_us{0};
|
||||
|
||||
// Cable State: 0 - 1 plugged in ?
|
||||
u8 m_cable_state{0};
|
||||
|
||||
|
|
|
@ -483,8 +483,6 @@ namespace vm
|
|||
}
|
||||
}
|
||||
|
||||
bool to_prepare_memory = true;
|
||||
|
||||
for (u64 i = 0;; i++)
|
||||
{
|
||||
auto& bits = get_range_lock_bits(true);
|
||||
|
@ -512,22 +510,11 @@ namespace vm
|
|||
|
||||
if (i < 100)
|
||||
{
|
||||
if (to_prepare_memory)
|
||||
{
|
||||
// We have some spare time, prepare cache lines (todo: reservation tests here)
|
||||
utils::prefetch_write(vm::get_super_ptr(addr));
|
||||
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
|
||||
to_prepare_memory = false;
|
||||
}
|
||||
|
||||
busy_wait(200);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::yield();
|
||||
|
||||
// Thread may have been switched or the cache clue has been undermined, cache needs to be prapred again
|
||||
to_prepare_memory = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,13 +578,6 @@ namespace vm
|
|||
break;
|
||||
}
|
||||
|
||||
if (to_prepare_memory)
|
||||
{
|
||||
utils::prefetch_write(vm::get_super_ptr(addr));
|
||||
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
|
||||
to_prepare_memory = false;
|
||||
}
|
||||
|
||||
utils::pause();
|
||||
}
|
||||
|
||||
|
@ -607,13 +587,6 @@ namespace vm
|
|||
{
|
||||
while (!(ptr->state & cpu_flag::wait))
|
||||
{
|
||||
if (to_prepare_memory)
|
||||
{
|
||||
utils::prefetch_write(vm::get_super_ptr(addr));
|
||||
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
|
||||
to_prepare_memory = false;
|
||||
}
|
||||
|
||||
utils::pause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,12 +218,12 @@ namespace gl
|
|||
m_input_filter = gl::filter::linear;
|
||||
}
|
||||
|
||||
gl::texture_view* ui_overlay_renderer::load_simple_image(rsx::overlays::image_info* desc, bool temp_resource, u32 owner_uid)
|
||||
gl::texture_view* ui_overlay_renderer::load_simple_image(rsx::overlays::image_info_base* desc, bool temp_resource, u32 owner_uid)
|
||||
{
|
||||
auto tex = std::make_unique<gl::texture>(GL_TEXTURE_2D, desc->w, desc->h, 1, 1, 1, GL_RGBA8, RSX_FORMAT_CLASS_COLOR);
|
||||
tex->copy_from(desc->get_data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8, {});
|
||||
|
||||
GLenum remap[] = { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
|
||||
const GLenum remap[] = { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
|
||||
auto view = std::make_unique<gl::texture_view>(tex.get(), remap);
|
||||
|
||||
auto result = view.get();
|
||||
|
@ -234,7 +234,7 @@ namespace gl
|
|||
}
|
||||
else
|
||||
{
|
||||
u64 key = reinterpret_cast<u64>(desc);
|
||||
const u64 key = reinterpret_cast<u64>(desc);
|
||||
temp_image_cache[key] = std::make_pair(owner_uid, std::move(tex));
|
||||
temp_view_cache[key] = std::move(view);
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ namespace gl
|
|||
rsx::overlays::resource_config configuration;
|
||||
configuration.load_files();
|
||||
|
||||
for (const auto &res : configuration.texture_raw_data)
|
||||
for (const auto& res : configuration.texture_raw_data)
|
||||
{
|
||||
load_simple_image(res.get(), false, -1);
|
||||
}
|
||||
|
@ -318,13 +318,22 @@ namespace gl
|
|||
return result;
|
||||
}
|
||||
|
||||
gl::texture_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info* desc, u32 owner_uid)
|
||||
gl::texture_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info_base* desc, u32 owner_uid)
|
||||
{
|
||||
auto key = reinterpret_cast<u64>(desc);
|
||||
const bool dirty = std::exchange(desc->dirty, false);
|
||||
const u64 key = reinterpret_cast<u64>(desc);
|
||||
|
||||
auto cached = temp_view_cache.find(key);
|
||||
if (cached != temp_view_cache.end())
|
||||
{
|
||||
return cached->second.get();
|
||||
gl::texture_view* view = cached->second.get();
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
view->image()->copy_from(desc->get_data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8, {});
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
return load_simple_image(desc, true, owner_uid);
|
||||
|
@ -420,7 +429,7 @@ namespace gl
|
|||
}
|
||||
case rsx::overlays::image_resource_id::raw_image:
|
||||
{
|
||||
cmd_->bind_texture(31, GL_TEXTURE_2D, find_temp_image(static_cast<rsx::overlays::image_info*>(cmd.config.external_data_ref), ui.uid)->id());
|
||||
cmd_->bind_texture(31, GL_TEXTURE_2D, find_temp_image(static_cast<rsx::overlays::image_info_base*>(cmd.config.external_data_ref), ui.uid)->id());
|
||||
break;
|
||||
}
|
||||
case rsx::overlays::image_resource_id::font_file:
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace gl
|
|||
|
||||
ui_overlay_renderer();
|
||||
|
||||
gl::texture_view* load_simple_image(rsx::overlays::image_info* desc, bool temp_resource, u32 owner_uid);
|
||||
gl::texture_view* load_simple_image(rsx::overlays::image_info_base* desc, bool temp_resource, u32 owner_uid);
|
||||
|
||||
void create();
|
||||
void destroy();
|
||||
|
@ -84,7 +84,7 @@ namespace gl
|
|||
|
||||
gl::texture_view* find_font(rsx::overlays::font* font);
|
||||
|
||||
gl::texture_view* find_temp_image(rsx::overlays::image_info* desc, u32 owner_uid);
|
||||
gl::texture_view* find_temp_image(rsx::overlays::image_info_base* desc, u32 owner_uid);
|
||||
|
||||
void set_primitive_type(rsx::overlays::primitive_type type);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace rsx
|
|||
{
|
||||
update_value();
|
||||
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
const f32 col = m_last_value ? 1.0f : 0.3f;
|
||||
const f32 bkg = m_last_value ? 0.3f : 1.0f;
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace rsx
|
|||
if (const T new_value = m_setting->get(); new_value != m_last_value || initializing)
|
||||
{
|
||||
m_last_value = new_value;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ namespace rsx
|
|||
{
|
||||
this->update_value();
|
||||
|
||||
if (!this->is_compiled)
|
||||
if (!this->is_compiled())
|
||||
{
|
||||
const std::string value_text = Emu.GetCallbacks().get_localized_setting(home_menu_setting<T, cfg::_enum<T>>::m_setting, static_cast<u32>(this->m_last_value));
|
||||
m_dropdown.set_text(value_text);
|
||||
|
@ -145,7 +145,7 @@ namespace rsx
|
|||
{
|
||||
this->update_value();
|
||||
|
||||
if (!this->is_compiled)
|
||||
if (!this->is_compiled())
|
||||
{
|
||||
const f64 percentage = std::clamp((this->m_last_value - static_cast<T>(m_minimum)) / std::fabs(m_maximum - m_minimum), 0.0, 1.0);
|
||||
m_slider.set_pos(m_slider.x, this->y + (this->h - m_slider.h) / 2);
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& home_menu_message_box::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resource& compiled = overlay_element::get_compiled();
|
||||
compiled.add(m_label.get_compiled());
|
||||
|
|
|
@ -258,9 +258,9 @@ namespace rsx
|
|||
|
||||
compiled_resource& home_menu_page::get_compiled()
|
||||
{
|
||||
if (!is_compiled || (m_message_box && !m_message_box->is_compiled))
|
||||
if (!is_compiled() || (m_message_box && !m_message_box->is_compiled()))
|
||||
{
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
|
||||
if (home_menu_page* page = get_current_page(false))
|
||||
{
|
||||
|
@ -281,7 +281,7 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
is_compiled = true;
|
||||
m_is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& animated_icon::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resources = image_view::get_compiled();
|
||||
}
|
||||
|
|
|
@ -302,7 +302,7 @@ namespace rsx
|
|||
void overlay_element::refresh()
|
||||
{
|
||||
// Just invalidate for draw when get_compiled() is called
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::translate(s16 _x, s16 _y)
|
||||
|
@ -310,7 +310,7 @@ namespace rsx
|
|||
x += _x;
|
||||
y += _y;
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::scale(f32 _x, f32 _y, bool origin_scaling)
|
||||
|
@ -324,7 +324,7 @@ namespace rsx
|
|||
w = static_cast<u16>(_x * w);
|
||||
h = static_cast<u16>(_y * h);
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_pos(s16 _x, s16 _y)
|
||||
|
@ -332,7 +332,7 @@ namespace rsx
|
|||
x = _x;
|
||||
y = _y;
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_size(u16 _w, u16 _h)
|
||||
|
@ -340,7 +340,7 @@ namespace rsx
|
|||
w = _w;
|
||||
h = _h;
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_padding(u16 left, u16 right, u16 top, u16 bottom)
|
||||
|
@ -350,13 +350,13 @@ namespace rsx
|
|||
padding_top = top;
|
||||
padding_bottom = bottom;
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_padding(u16 padding)
|
||||
{
|
||||
padding_left = padding_right = padding_top = padding_bottom = padding;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
// NOTE: Functions as a simple position offset. Top left corner is the anchor.
|
||||
|
@ -365,25 +365,36 @@ namespace rsx
|
|||
margin_left = left;
|
||||
margin_top = top;
|
||||
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_margin(u16 margin)
|
||||
{
|
||||
margin_left = margin_top = margin;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_text(const std::string& text)
|
||||
{
|
||||
this->text = utf8_to_u32string(text);
|
||||
is_compiled = false;
|
||||
std::u32string new_text = utf8_to_u32string(text);
|
||||
const bool is_dirty = this->text != new_text;
|
||||
this->text = std::move(new_text);
|
||||
|
||||
if (is_dirty)
|
||||
{
|
||||
m_is_compiled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void overlay_element::set_unicode_text(const std::u32string& text)
|
||||
{
|
||||
const bool is_dirty = this->text != text;
|
||||
this->text = text;
|
||||
is_compiled = false;
|
||||
|
||||
if (is_dirty)
|
||||
{
|
||||
m_is_compiled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void overlay_element::set_text(localized_string_id id)
|
||||
|
@ -394,19 +405,19 @@ namespace rsx
|
|||
void overlay_element::set_font(const char* font_name, u16 font_size)
|
||||
{
|
||||
font_ref = fontmgr::get(font_name, font_size);
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::align_text(text_align align)
|
||||
{
|
||||
alignment = align;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void overlay_element::set_wrap_text(bool state)
|
||||
{
|
||||
wrap_text = state;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
font* overlay_element::get_font() const
|
||||
|
@ -563,7 +574,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& overlay_element::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resources.clear();
|
||||
|
||||
|
@ -599,7 +610,7 @@ namespace rsx
|
|||
compiled_resources.add(std::move(compiled_resources_temp), margin_left - horizontal_scroll_offset, margin_top - vertical_scroll_offset);
|
||||
}
|
||||
|
||||
is_compiled = true;
|
||||
m_is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
|
@ -664,7 +675,7 @@ namespace rsx
|
|||
{
|
||||
overlay_element::translate(_x, _y);
|
||||
|
||||
for (auto &itm : m_items)
|
||||
for (auto& itm : m_items)
|
||||
itm->translate(_x, _y);
|
||||
}
|
||||
|
||||
|
@ -675,13 +686,23 @@ namespace rsx
|
|||
translate(dx, dy);
|
||||
}
|
||||
|
||||
bool layout_container::is_compiled()
|
||||
{
|
||||
if (m_is_compiled && std::any_of(m_items.cbegin(), m_items.cend(), [](const auto& item){ return item && !item->is_compiled(); }))
|
||||
{
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
return m_is_compiled;
|
||||
}
|
||||
|
||||
compiled_resource& layout_container::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resource result = overlay_element::get_compiled();
|
||||
|
||||
for (auto &itm : m_items)
|
||||
for (auto& itm : m_items)
|
||||
result.add(itm->get_compiled());
|
||||
|
||||
compiled_resources = result;
|
||||
|
@ -716,7 +737,7 @@ namespace rsx
|
|||
return m_items.back().get();
|
||||
}
|
||||
|
||||
auto result = item.get();
|
||||
overlay_element* result = item.get();
|
||||
m_items.insert(m_items.begin() + offset, std::move(item));
|
||||
return result;
|
||||
}
|
||||
|
@ -726,12 +747,12 @@ namespace rsx
|
|||
if (scroll_offset_value == 0 && auto_resize)
|
||||
return layout_container::get_compiled();
|
||||
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resource result = overlay_element::get_compiled();
|
||||
const f32 global_y_offset = static_cast<f32>(-scroll_offset_value);
|
||||
|
||||
for (auto &item : m_items)
|
||||
for (auto& item : m_items)
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
|
@ -808,7 +829,7 @@ namespace rsx
|
|||
if (scroll_offset_value == 0 && auto_resize)
|
||||
return layout_container::get_compiled();
|
||||
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resource result = overlay_element::get_compiled();
|
||||
const f32 global_x_offset = static_cast<f32>(-scroll_offset_value);
|
||||
|
@ -862,7 +883,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& image_view::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
auto& result = overlay_element::get_compiled();
|
||||
auto& cmd_img = result.draw_commands.front();
|
||||
|
@ -880,7 +901,7 @@ namespace rsx
|
|||
verts[2] += vertex(padding_left, -padding_top, 0, 0);
|
||||
verts[3] += vertex(-padding_right, -padding_top, 0, 0);
|
||||
|
||||
is_compiled = true;
|
||||
m_is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
|
@ -892,7 +913,7 @@ namespace rsx
|
|||
external_ref = nullptr;
|
||||
}
|
||||
|
||||
void image_view::set_raw_image(image_info* raw_image)
|
||||
void image_view::set_raw_image(image_info_base* raw_image)
|
||||
{
|
||||
image_resource_ref = image_resource_id::raw_image;
|
||||
external_ref = raw_image;
|
||||
|
@ -935,7 +956,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& image_button::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
auto& compiled = image_view::get_compiled();
|
||||
for (auto& cmd : compiled.draw_commands)
|
||||
|
@ -987,7 +1008,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& rounded_rect::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
compiled_resources.clear();
|
||||
|
||||
|
@ -1068,7 +1089,7 @@ namespace rsx
|
|||
compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top);
|
||||
}
|
||||
|
||||
is_compiled = true;
|
||||
m_is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
|
|
|
@ -30,23 +30,32 @@ namespace rsx
|
|||
triangle_fan = 4
|
||||
};
|
||||
|
||||
struct image_info
|
||||
struct image_info_base
|
||||
{
|
||||
int w = 0, h = 0, channels = 0;
|
||||
int bpp = 0;
|
||||
bool dirty = false;
|
||||
|
||||
image_info_base() {}
|
||||
virtual ~image_info_base() {}
|
||||
virtual const u8* get_data() const = 0;
|
||||
};
|
||||
|
||||
struct image_info : public image_info_base
|
||||
{
|
||||
private:
|
||||
u8* data = nullptr;
|
||||
std::vector<u8> data_grey;
|
||||
|
||||
public:
|
||||
int w = 0, h = 0, channels = 0;
|
||||
int bpp = 0;
|
||||
|
||||
using image_info_base::image_info_base;
|
||||
image_info(image_info&) = delete;
|
||||
image_info(const std::string& filename, bool grayscaled = false);
|
||||
image_info(const std::vector<u8>& bytes, bool grayscaled = false);
|
||||
~image_info();
|
||||
virtual ~image_info();
|
||||
|
||||
void load_data(const std::vector<u8>& bytes, bool grayscaled = false);
|
||||
const u8* get_data() const { return channels == 4 ? data : data_grey.empty() ? nullptr : data_grey.data(); }
|
||||
const u8* get_data() const override { return channels == 4 ? data : data_grey.empty() ? nullptr : data_grey.data(); }
|
||||
};
|
||||
|
||||
struct resource_config
|
||||
|
@ -165,7 +174,6 @@ namespace rsx
|
|||
void set_sinus_offset(f32 sinus_modifier);
|
||||
|
||||
compiled_resource compiled_resources;
|
||||
bool is_compiled = false;
|
||||
|
||||
bool visible = true;
|
||||
|
||||
|
@ -185,6 +193,7 @@ namespace rsx
|
|||
virtual ~overlay_element() = default;
|
||||
|
||||
virtual void refresh();
|
||||
virtual bool is_compiled() { return m_is_compiled; }
|
||||
virtual void translate(s16 _x, s16 _y);
|
||||
virtual void scale(f32 _x, f32 _y, bool origin_scaling);
|
||||
virtual void set_pos(s16 _x, s16 _y);
|
||||
|
@ -204,6 +213,10 @@ namespace rsx
|
|||
virtual std::vector<vertex> render_text(const char32_t* string, f32 x, f32 y);
|
||||
virtual compiled_resource& get_compiled();
|
||||
void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const;
|
||||
virtual void set_selected(bool selected) { static_cast<void>(selected); }
|
||||
|
||||
protected:
|
||||
bool m_is_compiled = false; // Only use m_is_compiled as a getter in is_compiled() if possible
|
||||
};
|
||||
|
||||
struct layout_container : public overlay_element
|
||||
|
@ -221,6 +234,8 @@ namespace rsx
|
|||
void translate(s16 _x, s16 _y) override;
|
||||
void set_pos(s16 _x, s16 _y) override;
|
||||
|
||||
bool is_compiled() override;
|
||||
|
||||
compiled_resource& get_compiled() override;
|
||||
|
||||
virtual u16 get_scroll_offset_px() = 0;
|
||||
|
@ -248,6 +263,7 @@ namespace rsx
|
|||
compiled_resource& get_compiled() override
|
||||
{
|
||||
// No draw
|
||||
m_is_compiled = true;
|
||||
return compiled_resources;
|
||||
}
|
||||
};
|
||||
|
@ -263,7 +279,7 @@ namespace rsx
|
|||
|
||||
struct image_view : public overlay_element
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
u8 image_resource_ref = image_resource_id::none;
|
||||
void* external_ref = nullptr;
|
||||
|
||||
|
@ -276,7 +292,7 @@ namespace rsx
|
|||
compiled_resource& get_compiled() override;
|
||||
|
||||
void set_image_resource(u8 resource_id);
|
||||
void set_raw_image(image_info* raw_image);
|
||||
void set_raw_image(image_info_base* raw_image);
|
||||
void clear_image();
|
||||
void set_blur_strength(u8 strength);
|
||||
};
|
||||
|
|
|
@ -196,7 +196,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& edit_text::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
auto renderer = get_font();
|
||||
const auto [caret_x, caret_y] = renderer->get_char_offset(text.c_str(), caret_position, clip_text ? w : -1, wrap_text);
|
||||
|
@ -252,7 +252,7 @@ namespace rsx
|
|||
cmd.config.clip_rect = {static_cast<f32>(x), static_cast<f32>(y), static_cast<f32>(x + w), static_cast<f32>(y + h)};
|
||||
}
|
||||
|
||||
is_compiled = true;
|
||||
m_is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
|
|
|
@ -91,6 +91,15 @@ namespace rsx
|
|||
void list_view::update_selection()
|
||||
{
|
||||
const overlay_element* current_element = get_selected_entry();
|
||||
|
||||
for (auto& item : m_items)
|
||||
{
|
||||
if (item)
|
||||
{
|
||||
item->set_selected(item.get() == current_element);
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_element)
|
||||
{
|
||||
return; // Ideally unreachable but it should still be possible to recover by user interaction.
|
||||
|
@ -195,7 +204,7 @@ namespace rsx
|
|||
m_cancel_btn->set_pos(x + 180, y + h + 20);
|
||||
|
||||
m_cancel_only = cancel_only;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
bool list_view::get_cancel_only() const
|
||||
|
@ -219,7 +228,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& list_view::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
auto& compiled = vertical_layout::get_compiled();
|
||||
compiled.add(m_highlight_box->get_compiled());
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace rsx
|
|||
}
|
||||
|
||||
// Disable caching
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
|
||||
compiled_resources = rounded_rect::get_compiled();
|
||||
compiled_resources.add(m_text.get_compiled());
|
||||
|
|
|
@ -814,7 +814,7 @@ namespace rsx
|
|||
|
||||
compiled_resource& graph::get_compiled()
|
||||
{
|
||||
if (is_compiled)
|
||||
if (is_compiled())
|
||||
{
|
||||
return compiled_resources;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace rsx
|
|||
void progress_bar::set_limit(f32 limit)
|
||||
{
|
||||
m_limit = limit;
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void progress_bar::set_value(f32 value)
|
||||
|
@ -32,7 +32,7 @@ namespace rsx
|
|||
|
||||
f32 indicator_width = (w * m_value) / m_limit;
|
||||
indicator.set_size(static_cast<u16>(indicator_width), h);
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
void progress_bar::set_pos(s16 _x, s16 _y)
|
||||
|
@ -68,12 +68,12 @@ namespace rsx
|
|||
text_view.set_size(w, text_h);
|
||||
|
||||
set_pos(text_view.x, text_view.y);
|
||||
is_compiled = false;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
|
||||
compiled_resource& progress_bar::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
if (!is_compiled())
|
||||
{
|
||||
auto& compiled = overlay_element::get_compiled();
|
||||
compiled.add(text_view.get_compiled());
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "overlay_save_dialog.h"
|
||||
#include "overlay_video.h"
|
||||
#include "Utilities/date_time.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
|
@ -7,26 +8,18 @@ namespace rsx
|
|||
{
|
||||
namespace overlays
|
||||
{
|
||||
save_dialog::save_dialog_entry::save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf)
|
||||
save_dialog::save_dialog_entry::save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf, const std::string& video_path)
|
||||
{
|
||||
std::unique_ptr<overlay_element> image = std::make_unique<image_view>();
|
||||
std::unique_ptr<overlay_element> image = resource_id != image_resource_id::raw_image
|
||||
? std::make_unique<video_view>(video_path, resource_id)
|
||||
: !icon_buf.empty() ? std::make_unique<video_view>(video_path, icon_buf)
|
||||
: std::make_unique<video_view>(video_path, resource_config::standard_image_resource::save); // Fallback
|
||||
image->set_size(160, 110);
|
||||
image->set_padding(36, 36, 11, 11); // Square image, 88x88
|
||||
|
||||
if (resource_id != image_resource_id::raw_image)
|
||||
{
|
||||
static_cast<image_view*>(image.get())->set_image_resource(resource_id);
|
||||
}
|
||||
else if (!icon_buf.empty())
|
||||
if (resource_id == image_resource_id::raw_image && !icon_buf.empty())
|
||||
{
|
||||
image->set_padding(0, 0, 11, 11); // Half sized icon, 320x176->160x88
|
||||
icon_data = std::make_unique<image_info>(icon_buf);
|
||||
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback
|
||||
static_cast<image_view*>(image.get())->set_image_resource(resource_config::standard_image_resource::save);
|
||||
}
|
||||
|
||||
std::unique_ptr<overlay_element> text_stack = std::make_unique<vertical_layout>();
|
||||
|
@ -74,10 +67,18 @@ namespace rsx
|
|||
|
||||
// Pack
|
||||
this->pack_padding = 15;
|
||||
add_element(image);
|
||||
m_image = add_element(image);
|
||||
add_element(text_stack);
|
||||
}
|
||||
|
||||
void save_dialog::save_dialog_entry::set_selected(bool selected)
|
||||
{
|
||||
if (m_image)
|
||||
{
|
||||
static_cast<video_view*>(m_image)->set_active(selected);
|
||||
}
|
||||
}
|
||||
|
||||
save_dialog::save_dialog()
|
||||
{
|
||||
m_dim_background = std::make_unique<overlay_element>();
|
||||
|
@ -197,7 +198,7 @@ namespace rsx
|
|||
return result;
|
||||
}
|
||||
|
||||
s32 save_dialog::show(std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
|
||||
s32 save_dialog::show(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
|
||||
{
|
||||
rsx_log.notice("Showing native UI save_dialog (save_entries=%d, focused=%d, op=0x%x, listSet=*0x%x, enable_overlay=%d)", save_entries.size(), focused, op, listSet, enable_overlay);
|
||||
|
||||
|
@ -218,7 +219,7 @@ namespace rsx
|
|||
{
|
||||
const std::string date_and_size = fmt::format("%s %s", entry.date(), entry.data_size());
|
||||
std::unique_ptr<overlay_element> e;
|
||||
e = std::make_unique<save_dialog_entry>(entry.subtitle, date_and_size, entry.details, image_resource_id::raw_image, entry.iconBuf);
|
||||
e = std::make_unique<save_dialog_entry>(entry.subtitle, date_and_size, entry.details, image_resource_id::raw_image, entry.iconBuf, base_dir + entry.dirName + "/ICON1.PAM");
|
||||
entries.emplace_back(std::move(e));
|
||||
}
|
||||
|
||||
|
@ -270,7 +271,7 @@ namespace rsx
|
|||
id = image_resource_id::raw_image;
|
||||
}
|
||||
|
||||
std::unique_ptr<overlay_element> new_stub = std::make_unique<save_dialog_entry>(title, get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_SUB_TITLE), "", id, icon);
|
||||
std::unique_ptr<overlay_element> new_stub = std::make_unique<save_dialog_entry>(title, get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_SUB_TITLE), "", id, icon, "");
|
||||
|
||||
m_list->add_entry(new_stub);
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@ namespace rsx
|
|||
private:
|
||||
struct save_dialog_entry : horizontal_layout
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<image_info> icon_data;
|
||||
|
||||
public:
|
||||
save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf);
|
||||
save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf, const std::string& video_path);
|
||||
void set_selected(bool selected) override;
|
||||
|
||||
private:
|
||||
overlay_element* m_image = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<overlay_element> m_dim_background;
|
||||
|
@ -38,7 +39,7 @@ namespace rsx
|
|||
|
||||
compiled_resource get_compiled() override;
|
||||
|
||||
s32 show(std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay);
|
||||
s32 show(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
116
rpcs3/Emu/RSX/Overlays/overlay_video.cpp
Normal file
116
rpcs3/Emu/RSX/Overlays/overlay_video.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
#include "stdafx.h"
|
||||
#include "overlay_video.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
video_view::video_view(const std::string& video_path, const std::string& thumbnail_path)
|
||||
{
|
||||
init_video(video_path);
|
||||
|
||||
if (!thumbnail_path.empty())
|
||||
{
|
||||
m_thumbnail_info = std::make_unique<image_info>(thumbnail_path);
|
||||
set_raw_image(m_thumbnail_info.get());
|
||||
}
|
||||
}
|
||||
|
||||
video_view::video_view(const std::string& video_path, const std::vector<u8>& thumbnail_buf)
|
||||
{
|
||||
init_video(video_path);
|
||||
|
||||
if (!thumbnail_buf.empty())
|
||||
{
|
||||
m_thumbnail_info = std::make_unique<image_info>(thumbnail_buf);
|
||||
set_raw_image(m_thumbnail_info.get());
|
||||
}
|
||||
}
|
||||
|
||||
video_view::video_view(const std::string& video_path, u8 thumbnail_id)
|
||||
: m_thumbnail_id(thumbnail_id)
|
||||
{
|
||||
init_video(video_path);
|
||||
set_image_resource(thumbnail_id);
|
||||
}
|
||||
|
||||
video_view::~video_view()
|
||||
{
|
||||
}
|
||||
|
||||
void video_view::init_video(const std::string& video_path)
|
||||
{
|
||||
if (video_path.empty()) return;
|
||||
|
||||
m_video_source = Emu.GetCallbacks().make_video_source();
|
||||
ensure(!!m_video_source);
|
||||
|
||||
m_video_source->set_update_callback([this]()
|
||||
{
|
||||
if (m_video_active)
|
||||
{
|
||||
m_is_compiled = false;
|
||||
}
|
||||
});
|
||||
m_video_source->set_video_path(video_path);
|
||||
}
|
||||
|
||||
void video_view::set_active(bool active)
|
||||
{
|
||||
if (m_video_source)
|
||||
{
|
||||
m_video_source->set_active(active);
|
||||
m_video_active = active;
|
||||
m_is_compiled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void video_view::update()
|
||||
{
|
||||
if (m_video_active && m_video_source && m_video_source->get_active())
|
||||
{
|
||||
if (!m_video_source->has_new())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer_index = (m_buffer_index + 1) % m_video_info.size();
|
||||
|
||||
auto& info = m_video_info.at(m_buffer_index);
|
||||
if (!info)
|
||||
{
|
||||
info = std::make_unique<video_info>();
|
||||
}
|
||||
|
||||
m_video_source->get_image(info->data, info->w, info->h, info->channels, info->bpp);
|
||||
info->dirty = true;
|
||||
|
||||
set_raw_image(info.get());
|
||||
m_is_compiled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_thumbnail_info && m_thumbnail_info.get() != external_ref)
|
||||
{
|
||||
set_raw_image(m_thumbnail_info.get());
|
||||
m_is_compiled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_thumbnail_id != image_resource_id::none && m_thumbnail_id != image_resource_ref)
|
||||
{
|
||||
set_image_resource(m_thumbnail_id);
|
||||
m_is_compiled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
compiled_resource& video_view::get_compiled()
|
||||
{
|
||||
update();
|
||||
|
||||
return external_ref ? image_view::get_compiled() : overlay_element::get_compiled();
|
||||
}
|
||||
}
|
||||
}
|
43
rpcs3/Emu/RSX/Overlays/overlay_video.h
Normal file
43
rpcs3/Emu/RSX/Overlays/overlay_video.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "overlay_controls.h"
|
||||
#include "util/video_source.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
struct video_info : public image_info_base
|
||||
{
|
||||
using image_info_base::image_info_base;
|
||||
virtual ~video_info() {}
|
||||
const u8* get_data() const override { return data.empty() ? nullptr : data.data(); }
|
||||
|
||||
std::vector<u8> data;
|
||||
};
|
||||
|
||||
class video_view final : public image_view
|
||||
{
|
||||
public:
|
||||
video_view(const std::string& video_path, const std::string& thumbnail_path);
|
||||
video_view(const std::string& video_path, const std::vector<u8>& thumbnail_buf);
|
||||
video_view(const std::string& video_path, u8 thumbnail_id);
|
||||
virtual ~video_view();
|
||||
|
||||
void set_active(bool active);
|
||||
|
||||
void update();
|
||||
compiled_resource& get_compiled() override;
|
||||
|
||||
private:
|
||||
void init_video(const std::string& video_path);
|
||||
|
||||
usz m_buffer_index = 0;
|
||||
std::array<std::unique_ptr<video_info>, 2> m_video_info; // double buffer
|
||||
std::unique_ptr<video_source> m_video_source;
|
||||
std::unique_ptr<image_info> m_thumbnail_info;
|
||||
u8 m_thumbnail_id = image_resource_id::none;
|
||||
bool m_video_active = false; // This is the expected state. The actual state is found in the video source.
|
||||
};
|
||||
}
|
||||
}
|
|
@ -76,6 +76,8 @@ vec4 _fetch_constant(const in uint base_offset)
|
|||
// uint override
|
||||
return _fetch_constant(int(base_offset));
|
||||
}
|
||||
#elif defined(VULKAN)
|
||||
#define _fetch_constant(x) vc[x + xform_constants_offset]
|
||||
#else
|
||||
#define _fetch_constant(x) vc[x]
|
||||
#endif
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ARM64
|
||||
#define AVX512_ICL_FUNC
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define AVX512_ICL_FUNC
|
||||
#else
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace vk
|
|||
|
||||
idx++;
|
||||
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
bindings[idx].descriptorCount = 1;
|
||||
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
bindings[idx].binding = binding_table.vertex_constant_buffers_bind_slot;
|
||||
|
@ -101,7 +101,8 @@ namespace vk
|
|||
return bindings;
|
||||
}
|
||||
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout> get_common_pipeline_layout(VkDevice dev)
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>>
|
||||
get_common_pipeline_layout(VkDevice dev)
|
||||
{
|
||||
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
|
||||
auto bindings = get_common_binding_table();
|
||||
|
@ -135,13 +136,13 @@ namespace vk
|
|||
|
||||
std::array<VkPushConstantRange, 1> push_constants;
|
||||
push_constants[0].offset = 0;
|
||||
push_constants[0].size = 16;
|
||||
push_constants[0].size = 20;
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
// Conditional render toggle
|
||||
push_constants[0].size = 20;
|
||||
push_constants[0].size = 24;
|
||||
}
|
||||
|
||||
const auto set_layout = vk::descriptors::create_layout(bindings);
|
||||
|
@ -155,6 +156,25 @@ namespace vk
|
|||
|
||||
VkPipelineLayout result;
|
||||
CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result));
|
||||
return std::make_tuple(result, set_layout);
|
||||
return std::make_tuple(result, set_layout, bindings);
|
||||
}
|
||||
|
||||
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings)
|
||||
{
|
||||
// Compile descriptor pool sizes
|
||||
const u32 num_ubo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? y.descriptorCount : 0)));
|
||||
const u32 num_texel_buffers = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? y.descriptorCount : 0)));
|
||||
const u32 num_combined_image_sampler = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? y.descriptorCount : 0)));
|
||||
const u32 num_ssbo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? y.descriptorCount : 0)));
|
||||
|
||||
ensure(num_ubo > 0 && num_texel_buffers > 0 && num_combined_image_sampler > 0 && num_ssbo > 0);
|
||||
|
||||
return
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , num_ubo },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , num_texel_buffers },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , num_combined_image_sampler },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_ssbo }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@ namespace vk
|
|||
{
|
||||
// Grab standard layout for decompiled RSX programs. Also used by the interpreter.
|
||||
// FIXME: This generates a bloated monstrosity that needs to die.
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout> get_common_pipeline_layout(VkDevice dev);
|
||||
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>> get_common_pipeline_layout(VkDevice dev);
|
||||
|
||||
// Returns the standard binding layout without texture slots. Those have special handling depending on the consumer.
|
||||
rsx::simple_array<VkDescriptorSetLayoutBinding> get_common_binding_table();
|
||||
|
||||
// Returns an array of pool sizes that can be used to generate a proper descriptor pool
|
||||
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings);
|
||||
}
|
||||
|
|
|
@ -491,7 +491,8 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
|||
m_secondary_cb_list.create(m_secondary_command_buffer_pool, vk::command_buffer::access_type_hint::all);
|
||||
|
||||
//Precalculated stuff
|
||||
std::tie(m_pipeline_layout, m_descriptor_layouts) = vk::get_common_pipeline_layout(*m_device);
|
||||
rsx::simple_array<VkDescriptorSetLayoutBinding> binding_layout;
|
||||
std::tie(m_pipeline_layout, m_descriptor_layouts, binding_layout) = vk::get_common_pipeline_layout(*m_device);
|
||||
|
||||
//Occlusion
|
||||
m_occlusion_query_manager = std::make_unique<vk::query_pool_manager>(*m_device, VK_QUERY_TYPE_OCCLUSION, OCCLUSION_MAX_POOL_SIZE);
|
||||
|
@ -507,18 +508,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
|||
|
||||
// Generate frame contexts
|
||||
const u32 max_draw_calls = m_device->get_descriptor_max_draw_calls();
|
||||
const auto& binding_table = m_device->get_pipeline_binding_table();
|
||||
const u32 num_fs_samplers = binding_table.vertex_textures_first_bind_slot - binding_table.textures_first_bind_slot;
|
||||
|
||||
rsx::simple_array<VkDescriptorPoolSize> descriptor_type_sizes =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 6 },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , 3 },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , (num_fs_samplers + 4) },
|
||||
|
||||
// Conditional rendering predicate slot; refactor to allow skipping this when not needed
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 }
|
||||
};
|
||||
const auto descriptor_type_sizes = vk::get_descriptor_pool_sizes(binding_layout);
|
||||
m_descriptor_pool.create(*m_device, descriptor_type_sizes, max_draw_calls);
|
||||
|
||||
VkSemaphoreCreateInfo semaphore_info = {};
|
||||
|
@ -531,7 +521,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
|||
m_fragment_texture_params_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment texture params buffer");
|
||||
m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer", 0x10000, VK_TRUE);
|
||||
m_fragment_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment constants buffer");
|
||||
m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer");
|
||||
m_transform_constants_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer");
|
||||
m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer");
|
||||
m_texture_upload_buffer_ring_info.create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M * 0x100000, "texture upload buffer", 32 * 0x100000);
|
||||
m_raster_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "raster env buffer");
|
||||
|
@ -2107,7 +2097,7 @@ void VKGSRender::load_program_env()
|
|||
usz mem_offset = 0;
|
||||
auto alloc_storage = [&](usz size) -> std::pair<void*, usz>
|
||||
{
|
||||
const auto alignment = m_device->gpu().get_limits().minUniformBufferOffsetAlignment;
|
||||
const auto alignment = m_device->gpu().get_limits().minStorageBufferOffsetAlignment;
|
||||
mem_offset = m_transform_constants_ring_info.alloc<1>(utils::align(size, alignment));
|
||||
return std::make_pair(m_transform_constants_ring_info.map(mem_offset, size), size);
|
||||
};
|
||||
|
@ -2118,7 +2108,8 @@ void VKGSRender::load_program_env()
|
|||
if (!io_buf.empty())
|
||||
{
|
||||
m_transform_constants_ring_info.unmap();
|
||||
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, mem_offset, io_buf.size() };
|
||||
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, VK_WHOLE_SIZE };
|
||||
m_xform_constants_dynamic_offset = mem_offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2225,7 +2216,7 @@ void VKGSRender::load_program_env()
|
|||
const auto& binding_table = m_device->get_pipeline_binding_table();
|
||||
|
||||
m_program->bind_uniform(m_vertex_env_buffer_info, binding_table.vertex_params_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_vertex_constants_buffer_info, binding_table.vertex_constant_buffers_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_buffer(m_vertex_constants_buffer_info, binding_table.vertex_constant_buffers_bind_slot, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_fragment_env_buffer_info, binding_table.fragment_state_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_fragment_texture_params_buffer_info, binding_table.fragment_texture_params_bind_slot, m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(m_raster_env_buffer_info, binding_table.rasterizer_env_bind_slot, m_current_frame->descriptor_set);
|
||||
|
@ -2320,21 +2311,31 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_
|
|||
base_offset = 0;
|
||||
}
|
||||
|
||||
u8 data_size = 16;
|
||||
u32 draw_info[5];
|
||||
const u32 vertex_layout_offset = (id * 16) + (base_offset / 8);
|
||||
const volatile u32 constant_id_offset = static_cast<volatile u32>(m_xform_constants_dynamic_offset) / 16u;
|
||||
|
||||
draw_info[0] = vertex_info.vertex_index_base;
|
||||
draw_info[1] = vertex_info.vertex_index_offset;
|
||||
draw_info[2] = id;
|
||||
draw_info[3] = (id * 16) + (base_offset / 8);
|
||||
u32 push_constants[6];
|
||||
u32 data_length = 20;
|
||||
|
||||
push_constants[0] = vertex_info.vertex_index_base;
|
||||
push_constants[1] = vertex_info.vertex_index_offset;
|
||||
push_constants[2] = id;
|
||||
push_constants[3] = vertex_layout_offset;
|
||||
push_constants[4] = constant_id_offset;
|
||||
|
||||
if (vk::emulate_conditional_rendering())
|
||||
{
|
||||
draw_info[4] = cond_render_ctrl.hw_cond_active ? 1 : 0;
|
||||
data_size = 20;
|
||||
push_constants[5] = cond_render_ctrl.hw_cond_active ? 1 : 0;
|
||||
data_length += 4;
|
||||
}
|
||||
|
||||
vkCmdPushConstants(*m_current_command_buffer, m_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, data_size, draw_info);
|
||||
vkCmdPushConstants(
|
||||
*m_current_command_buffer,
|
||||
m_pipeline_layout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0,
|
||||
data_length,
|
||||
push_constants);
|
||||
|
||||
const usz data_offset = (id * 128) + m_vertex_layout_stream_info.offset;
|
||||
auto dst = m_vertex_layout_ring_info.map(data_offset, 128);
|
||||
|
@ -2351,7 +2352,7 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_
|
|||
m_vertex_layout_ring_info.unmap();
|
||||
}
|
||||
|
||||
void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count)
|
||||
void VKGSRender::patch_transform_constants(rsx::context* /*ctx*/, u32 index, u32 count)
|
||||
{
|
||||
if (!m_program || !m_vertex_prog)
|
||||
{
|
||||
|
@ -2366,83 +2367,16 @@ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou
|
|||
return;
|
||||
}
|
||||
|
||||
// Hot-patching transform constants mid-draw (instanced draw)
|
||||
std::pair<VkDeviceSize, VkDeviceSize> data_range;
|
||||
void* data_source = nullptr;
|
||||
|
||||
if (m_vertex_prog->has_indexed_constants)
|
||||
// Buffer updates mid-pass violate the spec and destroy performance on NVIDIA
|
||||
auto allocate_mem = [&](usz size) -> std::pair<void*, usz>
|
||||
{
|
||||
// We're working with a full range. We can do a direct patch in this case since no index translation is required.
|
||||
const auto byte_count = count * 16;
|
||||
const auto byte_offset = index * 16;
|
||||
|
||||
data_range = { m_vertex_constants_buffer_info.offset + byte_offset, byte_count };
|
||||
data_source = ®S(ctx)->transform_constants[index];
|
||||
}
|
||||
else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0)
|
||||
{
|
||||
const auto write_offset = xform_id * 16;
|
||||
const auto byte_count = count * 16;
|
||||
|
||||
data_range = { m_vertex_constants_buffer_info.offset + write_offset, byte_count };
|
||||
data_source = ®S(ctx)->transform_constants[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indexed. This is a bit trickier. Use scratchpad to avoid UAF
|
||||
auto allocate_mem = [&](usz size) -> std::pair<void*, usz>
|
||||
{
|
||||
m_scratch_mem.resize(size);
|
||||
return { m_scratch_mem.data(), size };
|
||||
};
|
||||
|
||||
rsx::io_buffer iobuf(allocate_mem);
|
||||
upload_transform_constants(iobuf);
|
||||
|
||||
ensure(iobuf.size() >= m_vertex_constants_buffer_info.range);
|
||||
data_range = { m_vertex_constants_buffer_info.offset, m_vertex_constants_buffer_info.range };
|
||||
data_source = iobuf.data();
|
||||
}
|
||||
|
||||
// Preserving an active renderpass across a transfer operation is illegal vulkan. However, splitting up the CB into thousands of renderpasses incurs an overhead.
|
||||
// We cheat here for specific cases where we already know the driver can let us get away with this.
|
||||
static const std::set<vk::driver_vendor> s_allowed_vendors =
|
||||
{
|
||||
vk::driver_vendor::AMD,
|
||||
vk::driver_vendor::RADV,
|
||||
vk::driver_vendor::LAVAPIPE,
|
||||
vk::driver_vendor::NVIDIA,
|
||||
vk::driver_vendor::NVK
|
||||
const usz alignment = m_device->gpu().get_limits().minStorageBufferOffsetAlignment;
|
||||
m_xform_constants_dynamic_offset = m_transform_constants_ring_info.alloc<1>(utils::align(size, alignment));
|
||||
return std::make_pair(m_transform_constants_ring_info.map(m_xform_constants_dynamic_offset, size), size);
|
||||
};
|
||||
|
||||
const auto driver_vendor = vk::get_driver_vendor();
|
||||
const bool preserve_renderpass = !g_cfg.video.strict_rendering_mode && s_allowed_vendors.contains(driver_vendor);
|
||||
|
||||
vk::insert_buffer_memory_barrier(
|
||||
*m_current_command_buffer,
|
||||
m_vertex_constants_buffer_info.buffer,
|
||||
data_range.first,
|
||||
data_range.second,
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_UNIFORM_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
preserve_renderpass);
|
||||
|
||||
// FIXME: This is illegal during a renderpass
|
||||
vkCmdUpdateBuffer(
|
||||
*m_current_command_buffer,
|
||||
m_vertex_constants_buffer_info.buffer,
|
||||
data_range.first,
|
||||
data_range.second,
|
||||
data_source);
|
||||
|
||||
vk::insert_buffer_memory_barrier(
|
||||
*m_current_command_buffer,
|
||||
m_vertex_constants_buffer_info.buffer,
|
||||
data_range.first,
|
||||
data_range.second,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT,
|
||||
preserve_renderpass);
|
||||
rsx::io_buffer iobuf(allocate_mem);
|
||||
upload_transform_constants(iobuf);
|
||||
}
|
||||
|
||||
void VKGSRender::init_buffers(rsx::framebuffer_creation_context context, bool)
|
||||
|
|
|
@ -160,6 +160,8 @@ private:
|
|||
VkDescriptorBufferInfo m_vertex_instructions_buffer_info {};
|
||||
VkDescriptorBufferInfo m_fragment_instructions_buffer_info {};
|
||||
|
||||
u64 m_xform_constants_dynamic_offset = 0; // We manage transform_constants dynamic offset manually to alleviate performance penalty of doing a hot-patch of constants.
|
||||
|
||||
std::array<vk::frame_context_t, VK_MAX_ASYNC_FRAMES> frame_context_storage;
|
||||
//Temp frame context to use if the real frame queue is overburdened. Only used for storage
|
||||
vk::frame_context_t m_aux_frame_context;
|
||||
|
|
|
@ -386,22 +386,14 @@ namespace vk
|
|||
VK_BLEND_OP_ADD, VK_BLEND_OP_ADD);
|
||||
}
|
||||
|
||||
vk::image_view* ui_overlay_renderer::upload_simple_texture(vk::render_device& dev, vk::command_buffer& cmd,
|
||||
vk::data_heap& upload_heap, u64 key, u32 w, u32 h, u32 layers, bool font, bool temp, const void* pixel_src, u32 owner_uid)
|
||||
void ui_overlay_renderer::upload_simple_texture(vk::image* tex, vk::command_buffer& cmd,
|
||||
vk::data_heap& upload_heap, u32 w, u32 h, u32 layers, bool font, const void* pixel_src)
|
||||
{
|
||||
const VkFormat format = (font) ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM;
|
||||
const u32 pitch = (font) ? w : w * 4;
|
||||
const u32 data_size = pitch * h * layers;
|
||||
const auto offset = upload_heap.alloc<512>(data_size);
|
||||
const auto addr = upload_heap.map(offset, data_size);
|
||||
|
||||
const VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers };
|
||||
|
||||
auto tex = std::make_unique<vk::image>(dev, dev.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D, format, std::max(w, 1u), std::max(h, 1u), 1, 1, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
if (pixel_src && data_size)
|
||||
std::memcpy(addr, pixel_src, data_size);
|
||||
else if (data_size)
|
||||
|
@ -409,17 +401,32 @@ namespace vk
|
|||
|
||||
upload_heap.unmap();
|
||||
|
||||
VkBufferImageCopy region;
|
||||
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, layers };
|
||||
region.bufferOffset = offset;
|
||||
region.bufferRowLength = w;
|
||||
region.bufferImageHeight = h;
|
||||
region.imageOffset = {};
|
||||
region.imageExtent = { static_cast<u32>(w), static_cast<u32>(h), 1u };
|
||||
|
||||
change_image_layout(cmd, tex.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, range);
|
||||
const VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers };
|
||||
VkBufferImageCopy region
|
||||
{
|
||||
.bufferOffset = offset,
|
||||
.bufferRowLength = w,
|
||||
.bufferImageHeight = h,
|
||||
.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, layers },
|
||||
.imageOffset = {},
|
||||
.imageExtent = { static_cast<u32>(w), static_cast<u32>(h), 1u }
|
||||
};
|
||||
change_image_layout(cmd, tex, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, range);
|
||||
vkCmdCopyBufferToImage(cmd, upload_heap.heap->value, tex->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
change_image_layout(cmd, tex.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range);
|
||||
change_image_layout(cmd, tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range);
|
||||
}
|
||||
|
||||
vk::image_view* ui_overlay_renderer::upload_simple_texture(vk::render_device& dev, vk::command_buffer& cmd,
|
||||
vk::data_heap& upload_heap, u64 key, u32 w, u32 h, u32 layers, bool font, bool temp, const void* pixel_src, u32 owner_uid)
|
||||
{
|
||||
const VkFormat format = (font) ? VK_FORMAT_R8_UNORM : VK_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
auto tex = std::make_unique<vk::image>(dev, dev.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D, format, std::max(w, 1u), std::max(h, 1u), 1, 1, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
0, VMM_ALLOCATION_POOL_UNDEFINED);
|
||||
|
||||
upload_simple_texture(tex.get(), cmd, upload_heap, w, h, layers, font, pixel_src);
|
||||
|
||||
auto view = std::make_unique<vk::image_view>(dev, tex.get());
|
||||
|
||||
|
@ -521,12 +528,23 @@ namespace vk
|
|||
true, false, bytes.data(), -1);
|
||||
}
|
||||
|
||||
vk::image_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info* desc, vk::command_buffer& cmd, vk::data_heap& upload_heap, u32 owner_uid)
|
||||
vk::image_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info_base* desc, vk::command_buffer& cmd, vk::data_heap& upload_heap, u32 owner_uid)
|
||||
{
|
||||
u64 key = reinterpret_cast<u64>(desc);
|
||||
auto found = temp_view_cache.find(key);
|
||||
if (found != temp_view_cache.end())
|
||||
return found->second.get();
|
||||
const bool dirty = std::exchange(desc->dirty, false);
|
||||
const u64 key = reinterpret_cast<u64>(desc);
|
||||
|
||||
auto cached = temp_view_cache.find(key);
|
||||
if (cached != temp_view_cache.end())
|
||||
{
|
||||
vk::image_view* view = cached->second.get();
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
upload_simple_texture(view->image(), cmd, upload_heap, desc->w, desc->h, 1, false, desc->get_data());
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
return upload_simple_texture(cmd.get_command_pool().get_owner(), cmd, upload_heap, key, desc->w, desc->h, 1,
|
||||
false, true, desc->get_data(), owner_uid);
|
||||
|
@ -693,7 +711,7 @@ namespace vk
|
|||
: rsx::overlays::texture_sampling_mode::font3D;
|
||||
break;
|
||||
case rsx::overlays::image_resource_id::raw_image:
|
||||
src = find_temp_image(static_cast<rsx::overlays::image_info*>(command.config.external_data_ref), cmd, upload_heap, ui.uid);
|
||||
src = find_temp_image(static_cast<rsx::overlays::image_info_base*>(command.config.external_data_ref), cmd, upload_heap, ui.uid);
|
||||
break;
|
||||
default:
|
||||
src = view_cache[command.config.texture_ref].get();
|
||||
|
|
|
@ -154,6 +154,9 @@ namespace vk
|
|||
|
||||
ui_overlay_renderer();
|
||||
|
||||
void upload_simple_texture(vk::image* tex, vk::command_buffer& cmd,
|
||||
vk::data_heap& upload_heap, u32 w, u32 h, u32 layers, bool font, const void* pixel_src);
|
||||
|
||||
vk::image_view* upload_simple_texture(vk::render_device& dev, vk::command_buffer& cmd,
|
||||
vk::data_heap& upload_heap, u64 key, u32 w, u32 h, u32 layers, bool font, bool temp, const void* pixel_src, u32 owner_uid);
|
||||
|
||||
|
@ -164,7 +167,7 @@ namespace vk
|
|||
void remove_temp_resources(u32 key);
|
||||
|
||||
vk::image_view* find_font(rsx::overlays::font* font, vk::command_buffer& cmd, vk::data_heap& upload_heap);
|
||||
vk::image_view* find_temp_image(rsx::overlays::image_info* desc, vk::command_buffer& cmd, vk::data_heap& upload_heap, u32 owner_uid);
|
||||
vk::image_view* find_temp_image(rsx::overlays::image_info_base* desc, vk::command_buffer& cmd, vk::data_heap& upload_heap, u32 owner_uid);
|
||||
|
||||
std::vector<VkPushConstantRange> get_push_constants() override;
|
||||
|
||||
|
|
|
@ -330,21 +330,7 @@ namespace vk
|
|||
idx++;
|
||||
bindings.resize(idx);
|
||||
|
||||
// Compile descriptor pool sizes
|
||||
const u32 num_ubo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? y.descriptorCount : 0)));
|
||||
const u32 num_texel_buffers = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? y.descriptorCount : 0)));
|
||||
const u32 num_combined_image_sampler = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? y.descriptorCount : 0)));
|
||||
const u32 num_ssbo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? y.descriptorCount : 0)));
|
||||
|
||||
ensure(num_ubo > 0 && num_texel_buffers > 0 && num_combined_image_sampler > 0 && num_ssbo > 0);
|
||||
|
||||
m_descriptor_pool_sizes =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , num_ubo },
|
||||
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , num_texel_buffers },
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , num_combined_image_sampler },
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_ssbo }
|
||||
};
|
||||
m_descriptor_pool_sizes = get_descriptor_pool_sizes(bindings);
|
||||
|
||||
std::array<VkPushConstantRange, 1> push_constants;
|
||||
push_constants[0].offset = 0;
|
||||
|
|
|
@ -29,8 +29,9 @@ std::string VKVertexDecompilerThread::compareFunction(COMPARE f, const std::stri
|
|||
|
||||
void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
|
||||
{
|
||||
OS << "#version 450\n\n";
|
||||
OS << "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||
OS <<
|
||||
"#version 450\n\n"
|
||||
"#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||
|
||||
OS <<
|
||||
"layout(std140, set = 0, binding = 0) uniform VertexContextBuffer\n"
|
||||
|
@ -59,7 +60,8 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
|
|||
" uint vertex_base_index;\n"
|
||||
" uint vertex_index_offset;\n"
|
||||
" uint draw_id;\n"
|
||||
" uint layout_ptr_offset;\n";
|
||||
" uint layout_ptr_offset;\n"
|
||||
" uint xform_constants_offset;\n";
|
||||
|
||||
if (m_device_props.emulate_conditional_rendering)
|
||||
{
|
||||
|
@ -115,15 +117,15 @@ void VKVertexDecompilerThread::insertConstants(std::stringstream & OS, const std
|
|||
{
|
||||
if (!(m_prog.ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS))
|
||||
{
|
||||
OS << "layout(std140, set=0, binding=" << static_cast<int>(m_binding_table.vertex_constant_buffers_bind_slot) << ") uniform VertexConstantsBuffer\n";
|
||||
OS << "layout(std430, set=0, binding=" << static_cast<int>(m_binding_table.vertex_constant_buffers_bind_slot) << ") readonly buffer VertexConstantsBuffer\n";
|
||||
OS << "{\n";
|
||||
OS << " vec4 " << PI.name << ";\n";
|
||||
OS << " vec4 vc[];\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
in.location = m_binding_table.vertex_constant_buffers_bind_slot;
|
||||
in.domain = glsl::glsl_vertex_program;
|
||||
in.name = "VertexConstantsBuffer";
|
||||
in.type = vk::glsl::input_type_uniform_buffer;
|
||||
in.type = vk::glsl::input_type_storage_buffer;
|
||||
|
||||
inputs.push_back(in);
|
||||
continue;
|
||||
|
|
|
@ -430,6 +430,17 @@ namespace vk
|
|||
}
|
||||
}
|
||||
|
||||
void descriptor_set::push(const descriptor_set_dynamic_offset_t& offset)
|
||||
{
|
||||
ensure(offset.location >= 0 && offset.location <= 16);
|
||||
while (m_dynamic_offsets.size() < (static_cast<u32>(offset.location) + 1u))
|
||||
{
|
||||
m_dynamic_offsets.push_back(0);
|
||||
}
|
||||
|
||||
m_dynamic_offsets[offset.location] = offset.value;
|
||||
}
|
||||
|
||||
void descriptor_set::bind(const vk::command_buffer& cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout)
|
||||
{
|
||||
if ((m_push_type_mask & ~m_update_after_bind_mask) || (m_pending_writes.size() >= max_cache_size))
|
||||
|
@ -437,7 +448,7 @@ namespace vk
|
|||
flush();
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets(cmd, bind_point, layout, 0, 1, &m_handle, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(cmd, bind_point, layout, 0, 1, &m_handle, ::size32(m_dynamic_offsets), m_dynamic_offsets.data());
|
||||
}
|
||||
|
||||
void descriptor_set::flush()
|
||||
|
|
|
@ -27,6 +27,12 @@ namespace vk
|
|||
}
|
||||
};
|
||||
|
||||
struct descriptor_set_dynamic_offset_t
|
||||
{
|
||||
int location;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
class descriptor_pool
|
||||
{
|
||||
public:
|
||||
|
@ -95,6 +101,7 @@ namespace vk
|
|||
void push(const VkDescriptorImageInfo& image_info, VkDescriptorType type, u32 binding);
|
||||
void push(const VkDescriptorImageInfo* image_info, u32 count, VkDescriptorType type, u32 binding);
|
||||
void push(rsx::simple_array<VkCopyDescriptorSet>& copy_cmd, u32 type_mask = umax);
|
||||
void push(const descriptor_set_dynamic_offset_t& offset);
|
||||
|
||||
void bind(const vk::command_buffer& cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout);
|
||||
|
||||
|
@ -109,6 +116,7 @@ namespace vk
|
|||
rsx::simple_array<VkBufferView> m_buffer_view_pool;
|
||||
rsx::simple_array<VkDescriptorBufferInfo> m_buffer_info_pool;
|
||||
rsx::simple_array<VkDescriptorImageInfo> m_image_info_pool;
|
||||
rsx::simple_array<u32> m_dynamic_offsets;
|
||||
|
||||
#ifdef __clang__
|
||||
// Clang (pre 16.x) does not support LWG 2089, std::construct_at for POD types
|
||||
|
|
|
@ -111,6 +111,7 @@ struct EmuCallbacks
|
|||
std::function<bool()> display_sleep_control_supported;
|
||||
std::function<void(bool)> enable_display_sleep;
|
||||
std::function<void()> check_microphone_permissions;
|
||||
std::function<std::unique_ptr<class video_source>()> make_video_source;
|
||||
};
|
||||
|
||||
namespace utils
|
||||
|
|
|
@ -236,6 +236,7 @@ void pad_thread::SetRumble(const u32 pad, u8 large_motor, bool small_motor)
|
|||
if (pad >= m_pads.size())
|
||||
return;
|
||||
|
||||
m_pads[pad]->m_last_rumble_time_us = get_system_time();
|
||||
m_pads[pad]->m_vibrateMotors[0].m_value = large_motor;
|
||||
m_pads[pad]->m_vibrateMotors[1].m_value = small_motor ? 255 : 0;
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
<ClCompile Include="Emu\RSX\Overlays\overlay_compile_notification.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_user_list_dialog.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_utils.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_video.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\Shaders\shader_loading_dialog.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\Shaders\shader_loading_dialog_native.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\Trophies\overlay_trophy_list_dialog.cpp" />
|
||||
|
@ -682,6 +683,7 @@
|
|||
<ClInclude Include="Emu\RSX\Overlays\overlay_manager.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_media_list_dialog.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_progress_bar.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_video.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\Trophies\overlay_trophy_list_dialog.h" />
|
||||
<ClInclude Include="Emu\RSX\Program\FragmentProgramRegister.h" />
|
||||
<ClInclude Include="Emu\RSX\Program\GLSLTypes.h" />
|
||||
|
|
|
@ -1354,6 +1354,9 @@
|
|||
<ClCompile Include="Emu\RSX\Common\texture_cache_types.cpp">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_video.cpp">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
@ -2719,6 +2722,9 @@
|
|||
<ClInclude Include="util\video_source.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_video.h">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Emu/Cell/Modules/sceNpTrophy.h"
|
||||
#include "Emu/Io/Null/null_camera_handler.h"
|
||||
#include "Emu/Io/Null/null_music_handler.h"
|
||||
#include "util/video_source.h"
|
||||
|
||||
#include <clocale>
|
||||
|
||||
|
@ -173,6 +174,8 @@ void headless_application::InitializeCallbacks()
|
|||
|
||||
callbacks.check_microphone_permissions = [](){};
|
||||
|
||||
callbacks.make_video_source = [](){ return nullptr; };
|
||||
|
||||
Emu.SetCallbacks(std::move(callbacks));
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,7 +28,7 @@ namespace rpcs3
|
|||
// Currently accessible by Windows and Linux build scripts, see implementations when doing MACOSX
|
||||
const utils::version& get_version()
|
||||
{
|
||||
static constexpr utils::version version{ 0, 0, 35, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
|
||||
static constexpr utils::version version{ 0, 0, 36, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
|
||||
return version;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ about_dialog::about_dialog(QWidget* parent) : QDialog(parent), ui(new Ui::about_
|
|||
connect(ui->website, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://rpcs3.net")); });
|
||||
connect(ui->forum, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://forums.rpcs3.net")); });
|
||||
connect(ui->patreon, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://rpcs3.net/patreon")); });
|
||||
connect(ui->discord, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://discord.me/RPCS3")); });
|
||||
connect(ui->discord, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://discord.gg/rpcs3")); });
|
||||
connect(ui->wiki, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://wiki.rpcs3.net/index.php?title=Main_Page")); });
|
||||
connect(ui->close, &QPushButton::clicked, this, &QWidget::close);
|
||||
}
|
||||
|
|
|
@ -2363,7 +2363,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set
|
|||
|
||||
connect(future_watcher, &QFutureWatcher<void>::finished, this, [=, this]()
|
||||
{
|
||||
pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size));
|
||||
pdlg->setLabelText(progressLabel.arg(+*index).arg(serials_size));
|
||||
pdlg->setCancelButtonText(tr("OK"));
|
||||
QApplication::beep();
|
||||
|
||||
|
@ -2396,7 +2396,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set
|
|||
return;
|
||||
}
|
||||
|
||||
pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size));
|
||||
pdlg->setLabelText(progressLabel.arg(+*index).arg(serials_size));
|
||||
pdlg->setCancelButtonText(tr("OK"));
|
||||
connect(pdlg, &progress_dialog::canceled, this, [pdlg](){ pdlg->deleteLater(); });
|
||||
QApplication::beep();
|
||||
|
|
|
@ -68,8 +68,6 @@ gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon,
|
|||
, m_start_games_fullscreen(force_fullscreen)
|
||||
, m_renderer(g_cfg.video.renderer)
|
||||
{
|
||||
load_gui_settings();
|
||||
|
||||
m_window_title = Emu.GetFormattedTitle(0);
|
||||
|
||||
if (!g_cfg_recording.load())
|
||||
|
@ -121,8 +119,7 @@ gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon,
|
|||
create();
|
||||
}
|
||||
|
||||
m_shortcut_handler = new shortcut_handler(gui::shortcuts::shortcut_handler_id::game_window, this, m_gui_settings);
|
||||
connect(m_shortcut_handler, &shortcut_handler::shortcut_activated, this, &gs_frame::handle_shortcut);
|
||||
load_gui_settings();
|
||||
|
||||
// Change cursor when in fullscreen.
|
||||
connect(this, &QWindow::visibilityChanged, this, [this](QWindow::Visibility visibility)
|
||||
|
@ -174,6 +171,20 @@ void gs_frame::load_gui_settings()
|
|||
m_lock_mouse_in_fullscreen = m_gui_settings->GetValue(gui::gs_lockMouseFs).toBool();
|
||||
m_hide_mouse_after_idletime = m_gui_settings->GetValue(gui::gs_hideMouseIdle).toBool();
|
||||
m_hide_mouse_idletime = m_gui_settings->GetValue(gui::gs_hideMouseIdleTime).toUInt();
|
||||
|
||||
if (m_disable_kb_hotkeys)
|
||||
{
|
||||
if (m_shortcut_handler)
|
||||
{
|
||||
m_shortcut_handler->deleteLater();
|
||||
m_shortcut_handler = nullptr;
|
||||
}
|
||||
}
|
||||
else if (!m_shortcut_handler)
|
||||
{
|
||||
m_shortcut_handler = new shortcut_handler(gui::shortcuts::shortcut_handler_id::game_window, this, m_gui_settings);
|
||||
connect(m_shortcut_handler, &shortcut_handler::shortcut_activated, this, &gs_frame::handle_shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_frame::update_shortcuts()
|
||||
|
@ -650,9 +661,6 @@ void gs_frame::show()
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// if we do this before show, the QWinTaskbarProgress won't show
|
||||
m_progress_indicator->show(this);
|
||||
}
|
||||
|
||||
display_handle_t gs_frame::handle() const
|
||||
|
@ -1101,7 +1109,7 @@ void gs_frame::handle_cursor(QWindow::Visibility visibility, bool visibility_cha
|
|||
|
||||
void gs_frame::mouse_hide_timeout()
|
||||
{
|
||||
// Our idle timeout occured, so we update the cursor
|
||||
// Our idle timeout occurred, so we update the cursor
|
||||
if (m_hide_mouse_after_idletime && m_show_mouse)
|
||||
{
|
||||
handle_cursor(visibility(), false, false, false);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Emu/vfs_config.h"
|
||||
#include "util/init_mutex.hpp"
|
||||
#include "util/console.h"
|
||||
#include "qt_video_source.h"
|
||||
#include "trophy_notification_helper.h"
|
||||
#include "save_data_dialog.h"
|
||||
#include "msg_dialog_frame.h"
|
||||
|
@ -955,6 +956,8 @@ void gui_application::InitializeCallbacks()
|
|||
});
|
||||
};
|
||||
|
||||
callbacks.make_video_source = [](){ return std::make_unique<qt_video_source_wrapper>(); };
|
||||
|
||||
Emu.SetCallbacks(std::move(callbacks));
|
||||
}
|
||||
|
||||
|
|
|
@ -226,49 +226,6 @@ bool main_window::Init([[maybe_unused]] bool with_cli_boot)
|
|||
ui->sysPauseAct->setEnabled(enable_play_last);
|
||||
ui->toolbar_start->setEnabled(enable_play_last);
|
||||
|
||||
// create tool buttons for the taskbar thumbnail
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_bar = new QWinThumbnailToolBar(this);
|
||||
m_thumb_bar->setWindow(windowHandle());
|
||||
|
||||
m_thumb_playPause = new QWinThumbnailToolButton(m_thumb_bar);
|
||||
m_thumb_playPause->setToolTip(start_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_play);
|
||||
m_thumb_playPause->setEnabled(enable_play_last);
|
||||
|
||||
m_thumb_stop = new QWinThumbnailToolButton(m_thumb_bar);
|
||||
m_thumb_stop->setToolTip(tr("Stop"));
|
||||
m_thumb_stop->setIcon(m_icon_thumb_stop);
|
||||
m_thumb_stop->setEnabled(false);
|
||||
|
||||
m_thumb_restart = new QWinThumbnailToolButton(m_thumb_bar);
|
||||
m_thumb_restart->setToolTip(tr("Restart"));
|
||||
m_thumb_restart->setIcon(m_icon_thumb_restart);
|
||||
m_thumb_restart->setEnabled(false);
|
||||
|
||||
m_thumb_bar->addButton(m_thumb_playPause);
|
||||
m_thumb_bar->addButton(m_thumb_stop);
|
||||
m_thumb_bar->addButton(m_thumb_restart);
|
||||
|
||||
RepaintThumbnailIcons();
|
||||
|
||||
connect(m_thumb_stop, &QWinThumbnailToolButton::clicked, this, []()
|
||||
{
|
||||
gui_log.notice("User clicked the stop button on thumbnail toolbar");
|
||||
Emu.GracefulShutdown(false, true);
|
||||
});
|
||||
connect(m_thumb_restart, &QWinThumbnailToolButton::clicked, this, []()
|
||||
{
|
||||
gui_log.notice("User clicked the restart button on thumbnail toolbar");
|
||||
Emu.Restart();
|
||||
});
|
||||
connect(m_thumb_playPause, &QWinThumbnailToolButton::clicked, this, [this]()
|
||||
{
|
||||
gui_log.notice("User clicked the playPause button on thumbnail toolbar");
|
||||
OnPlayOrPause();
|
||||
});
|
||||
#endif
|
||||
|
||||
// RPCS3 Updater
|
||||
|
||||
QMenu* download_menu = new QMenu(tr("Update Available!"));
|
||||
|
@ -1868,19 +1825,6 @@ void main_window::RepaintThumbnailIcons()
|
|||
{
|
||||
return gui::utils::get_colorized_icon(QPixmap::fromImage(gui::utils::get_opaque_image_area(path)), Qt::black, new_color);
|
||||
};
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
if (!m_thumb_bar) return;
|
||||
|
||||
m_icon_thumb_play = icon(":/Icons/play.png");
|
||||
m_icon_thumb_pause = icon(":/Icons/pause.png");
|
||||
m_icon_thumb_stop = icon(":/Icons/stop.png");
|
||||
m_icon_thumb_restart = icon(":/Icons/restart.png");
|
||||
|
||||
m_thumb_playPause->setIcon(Emu.IsRunning() || Emu.IsStarting() ? m_icon_thumb_pause : m_icon_thumb_play);
|
||||
m_thumb_stop->setIcon(m_icon_thumb_stop);
|
||||
m_thumb_restart->setIcon(m_icon_thumb_restart);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main_window::RepaintToolBarIcons()
|
||||
|
@ -1971,12 +1915,6 @@ void main_window::OnEmuRun(bool /*start_playtime*/)
|
|||
|
||||
m_debugger_frame->EnableButtons(true);
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_stop->setToolTip(stop_tooltip);
|
||||
m_thumb_restart->setToolTip(restart_tooltip);
|
||||
m_thumb_playPause->setToolTip(pause_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_pause);
|
||||
#endif
|
||||
ui->sysPauseAct->setText(tr("&Pause"));
|
||||
ui->sysPauseAct->setIcon(m_icon_pause);
|
||||
ui->toolbar_start->setIcon(m_icon_pause);
|
||||
|
@ -1996,12 +1934,6 @@ void main_window::OnEmuResume() const
|
|||
const QString pause_tooltip = tr("Pause %0").arg(title);
|
||||
const QString stop_tooltip = tr("Stop %0").arg(title);
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_stop->setToolTip(stop_tooltip);
|
||||
m_thumb_restart->setToolTip(restart_tooltip);
|
||||
m_thumb_playPause->setToolTip(pause_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_pause);
|
||||
#endif
|
||||
ui->sysPauseAct->setText(tr("&Pause"));
|
||||
ui->sysPauseAct->setIcon(m_icon_pause);
|
||||
ui->toolbar_start->setIcon(m_icon_pause);
|
||||
|
@ -2015,10 +1947,6 @@ void main_window::OnEmuPause() const
|
|||
const QString title = GetCurrentTitle();
|
||||
const QString resume_tooltip = tr("Resume %0").arg(title);
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setToolTip(resume_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_play);
|
||||
#endif
|
||||
ui->sysPauseAct->setText(tr("&Resume"));
|
||||
ui->sysPauseAct->setIcon(m_icon_play);
|
||||
ui->toolbar_start->setIcon(m_icon_play);
|
||||
|
@ -2039,10 +1967,6 @@ void main_window::OnEmuStop()
|
|||
|
||||
ui->sysPauseAct->setText(tr("&Play"));
|
||||
ui->sysPauseAct->setIcon(m_icon_play);
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setToolTip(play_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_play);
|
||||
#endif
|
||||
|
||||
EnableMenus(false);
|
||||
|
||||
|
@ -2061,10 +1985,6 @@ void main_window::OnEmuStop()
|
|||
ui->toolbar_start->setText(tr("Restart"));
|
||||
ui->toolbar_start->setToolTip(restart_tooltip);
|
||||
ui->sysRebootAct->setEnabled(true);
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_restart->setToolTip(restart_tooltip);
|
||||
m_thumb_restart->setEnabled(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
ui->batchRemoveShaderCachesAct->setEnabled(true);
|
||||
|
@ -2106,10 +2026,7 @@ void main_window::OnEmuReady() const
|
|||
const QString play_tooltip = tr("Play %0").arg(title);
|
||||
|
||||
m_debugger_frame->EnableButtons(true);
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setToolTip(play_tooltip);
|
||||
m_thumb_playPause->setIcon(m_icon_thumb_play);
|
||||
#endif
|
||||
|
||||
ui->sysPauseAct->setText(tr("&Play"));
|
||||
ui->sysPauseAct->setIcon(m_icon_play);
|
||||
ui->toolbar_start->setIcon(m_icon_play);
|
||||
|
@ -2133,13 +2050,6 @@ void main_window::OnEmuReady() const
|
|||
|
||||
void main_window::EnableMenus(bool enabled) const
|
||||
{
|
||||
// Thumbnail Buttons
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setEnabled(enabled);
|
||||
m_thumb_stop->setEnabled(enabled);
|
||||
m_thumb_restart->setEnabled(enabled);
|
||||
#endif
|
||||
|
||||
// Toolbar
|
||||
ui->toolbar_start->setEnabled(enabled);
|
||||
ui->toolbar_stop->setEnabled(enabled);
|
||||
|
@ -3588,16 +3498,10 @@ void main_window::CreateDockWindows()
|
|||
|
||||
ui->toolbar_start->setEnabled(enable_play_buttons);
|
||||
ui->sysPauseAct->setEnabled(enable_play_buttons);
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setEnabled(enable_play_buttons);
|
||||
#endif
|
||||
|
||||
if (!tooltip.isEmpty())
|
||||
{
|
||||
ui->toolbar_start->setToolTip(tooltip);
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_thumb_playPause->setToolTip(tooltip);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
#include <QWinThumbnailToolBar>
|
||||
#include <QWinThumbnailToolButton>
|
||||
#endif
|
||||
|
||||
#include <QActionGroup>
|
||||
#include <QMainWindow>
|
||||
#include <QIcon>
|
||||
|
@ -61,17 +56,6 @@ class main_window : public QMainWindow
|
|||
QIcon m_icon_fullscreen_on;
|
||||
QIcon m_icon_fullscreen_off;
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
QIcon m_icon_thumb_play;
|
||||
QIcon m_icon_thumb_pause;
|
||||
QIcon m_icon_thumb_stop;
|
||||
QIcon m_icon_thumb_restart;
|
||||
QWinThumbnailToolBar *m_thumb_bar = nullptr;
|
||||
QWinThumbnailToolButton *m_thumb_playPause = nullptr;
|
||||
QWinThumbnailToolButton *m_thumb_stop = nullptr;
|
||||
QWinThumbnailToolButton *m_thumb_restart = nullptr;
|
||||
#endif
|
||||
|
||||
enum class drop_type
|
||||
{
|
||||
drop_error,
|
||||
|
|
|
@ -131,9 +131,6 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
|
|||
// Fix size
|
||||
m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
m_dialog->show();
|
||||
|
||||
// if we do this before, the QWinTaskbarProgress won't show
|
||||
if (m_progress_indicator) m_progress_indicator->show(m_dialog->windowHandle());
|
||||
}
|
||||
|
||||
void msg_dialog_frame::Close(bool success)
|
||||
|
|
|
@ -51,34 +51,3 @@ void progress_dialog::SignalFailure() const
|
|||
|
||||
QApplication::beep();
|
||||
}
|
||||
|
||||
void progress_dialog::show_progress_indicator()
|
||||
{
|
||||
// Try to find a window handle first
|
||||
QWindow* handle = windowHandle();
|
||||
|
||||
for (QWidget* ancestor = this; !handle && ancestor;)
|
||||
{
|
||||
ancestor = static_cast<QWidget*>(ancestor->parent());
|
||||
if (ancestor) handle = ancestor->windowHandle();
|
||||
}
|
||||
|
||||
m_progress_indicator->show(handle);
|
||||
}
|
||||
|
||||
void progress_dialog::setVisible(bool visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
if (!isVisible())
|
||||
{
|
||||
show_progress_indicator();
|
||||
}
|
||||
}
|
||||
else if (isVisible())
|
||||
{
|
||||
m_progress_indicator->hide();
|
||||
}
|
||||
|
||||
QProgressDialog::setVisible(visible);
|
||||
}
|
||||
|
|
|
@ -14,10 +14,6 @@ public:
|
|||
void SetDeleteOnClose();
|
||||
void SignalFailure() const;
|
||||
|
||||
void show_progress_indicator();
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<progress_indicator> m_progress_indicator;
|
||||
};
|
||||
|
|
|
@ -1,106 +1,57 @@
|
|||
#include "stdafx.h"
|
||||
#include "progress_indicator.h"
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
#include <QCoreApplication>
|
||||
#include <QWinTaskbarProgress>
|
||||
#elif HAVE_QTDBUS
|
||||
#if HAVE_QTDBUS
|
||||
#include <QtDBus/QDBusMessage>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#endif
|
||||
|
||||
progress_indicator::progress_indicator(int minimum, int maximum)
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button = std::make_unique<QWinTaskbarButton>();
|
||||
m_tb_button->progress()->setRange(minimum, maximum);
|
||||
m_tb_button->progress()->setVisible(false);
|
||||
#else
|
||||
m_minimum = minimum;
|
||||
m_maximum = maximum;
|
||||
#if HAVE_QTDBUS
|
||||
update_progress(0, true, false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
progress_indicator::~progress_indicator()
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
// QWinTaskbarProgress::hide() will crash if the application is already about to close, even if the object is not null.
|
||||
if (!QCoreApplication::closingDown())
|
||||
{
|
||||
m_tb_button->progress()->hide();
|
||||
}
|
||||
#elif HAVE_QTDBUS
|
||||
#if HAVE_QTDBUS
|
||||
update_progress(0, false, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::show(QWindow* window)
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->setWindow(window);
|
||||
m_tb_button->progress()->show();
|
||||
#else
|
||||
Q_UNUSED(window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::hide()
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->progress()->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
int progress_indicator::value() const
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
return m_tb_button->progress()->value();
|
||||
#else
|
||||
return m_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::set_value(int value)
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->progress()->setValue(std::clamp(value, m_tb_button->progress()->minimum(), m_tb_button->progress()->maximum()));
|
||||
#else
|
||||
m_value = std::clamp(value, m_minimum, m_maximum);
|
||||
#if HAVE_QTDBUS
|
||||
update_progress(m_value, true, false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::set_range(int minimum, int maximum)
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->progress()->setRange(minimum, maximum);
|
||||
#else
|
||||
m_minimum = minimum;
|
||||
m_maximum = maximum;
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::reset()
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->progress()->reset();
|
||||
#else
|
||||
m_value = m_minimum;
|
||||
#if HAVE_QTDBUS
|
||||
update_progress(m_value, false, false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void progress_indicator::signal_failure()
|
||||
{
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
m_tb_button->progress()->stop();
|
||||
#elif HAVE_QTDBUS
|
||||
#if HAVE_QTDBUS
|
||||
update_progress(0, false, true);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,20 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWindow>
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
#include <QWinTaskbarButton>
|
||||
#endif
|
||||
|
||||
class progress_indicator
|
||||
{
|
||||
public:
|
||||
progress_indicator(int minimum, int maximum);
|
||||
~progress_indicator();
|
||||
|
||||
void show(QWindow* window);
|
||||
void hide();
|
||||
|
||||
int value() const;
|
||||
|
||||
void set_value(int value);
|
||||
|
@ -23,15 +14,10 @@ public:
|
|||
void signal_failure();
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAS_QT_WIN_STUFF
|
||||
std::unique_ptr<QWinTaskbarButton> m_tb_button;
|
||||
#else
|
||||
int m_value = 0;
|
||||
int m_minimum = 0;
|
||||
int m_maximum = 100;
|
||||
#if HAVE_QTDBUS
|
||||
void update_progress(int progress, bool progress_visible, bool urgent);
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -14,9 +14,9 @@ qt_video_source::~qt_video_source()
|
|||
stop_movie();
|
||||
}
|
||||
|
||||
void qt_video_source::set_video_path(const std::string& path)
|
||||
void qt_video_source::set_video_path(const std::string& video_path)
|
||||
{
|
||||
m_video_path = QString::fromStdString(path);
|
||||
m_video_path = QString::fromStdString(video_path);
|
||||
}
|
||||
|
||||
void qt_video_source::set_active(bool active)
|
||||
|
@ -209,14 +209,14 @@ qt_video_source_wrapper::~qt_video_source_wrapper()
|
|||
});
|
||||
}
|
||||
|
||||
void qt_video_source_wrapper::set_video_path(const std::string& path)
|
||||
void qt_video_source_wrapper::set_video_path(const std::string& video_path)
|
||||
{
|
||||
Emu.BlockingCallFromMainThread([this, &path]()
|
||||
Emu.CallFromMainThread([this, path = video_path]()
|
||||
{
|
||||
m_qt_video_source = std::make_unique<qt_video_source>();
|
||||
m_qt_video_source->m_image_change_callback = [this](const QVideoFrame& frame)
|
||||
{
|
||||
std::lock_guard lock(m_qt_video_source->m_image_mutex);
|
||||
std::unique_lock lock(m_qt_video_source->m_image_mutex);
|
||||
|
||||
if (m_qt_video_source->m_movie)
|
||||
{
|
||||
|
@ -236,12 +236,30 @@ void qt_video_source_wrapper::set_video_path(const std::string& path)
|
|||
{
|
||||
m_qt_video_source->m_image.convertTo(QImage::Format_RGBA8888);
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
notify_update();
|
||||
};
|
||||
m_qt_video_source->set_video_path(path);
|
||||
});
|
||||
}
|
||||
|
||||
void qt_video_source_wrapper::set_active(bool active)
|
||||
{
|
||||
Emu.CallFromMainThread([this, active]()
|
||||
{
|
||||
m_qt_video_source->set_active(true);
|
||||
});
|
||||
}
|
||||
|
||||
bool qt_video_source_wrapper::get_active() const
|
||||
{
|
||||
ensure(m_qt_video_source);
|
||||
|
||||
return m_qt_video_source->get_active();
|
||||
}
|
||||
|
||||
void qt_video_source_wrapper::get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp)
|
||||
{
|
||||
ensure(m_qt_video_source);
|
||||
|
|
|
@ -17,17 +17,14 @@ public:
|
|||
qt_video_source();
|
||||
virtual ~qt_video_source();
|
||||
|
||||
void set_video_path(const std::string& path) override;
|
||||
void set_video_path(const std::string& video_path) override;
|
||||
const QString& video_path() const { return m_video_path; }
|
||||
|
||||
void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) override;
|
||||
bool has_new() const override { return m_has_new; }
|
||||
|
||||
virtual void set_active(bool active);
|
||||
[[nodiscard]] bool get_active() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
void set_active(bool active) override;
|
||||
bool get_active() const override { return m_active; }
|
||||
|
||||
void start_movie();
|
||||
void stop_movie();
|
||||
|
@ -67,9 +64,11 @@ public:
|
|||
qt_video_source_wrapper() : video_source() {}
|
||||
virtual ~qt_video_source_wrapper();
|
||||
|
||||
void set_video_path(const std::string& path) override;
|
||||
void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) override;
|
||||
void set_video_path(const std::string& video_path) override;
|
||||
void set_active(bool active) override;
|
||||
bool get_active() const override;
|
||||
bool has_new() const override { return m_qt_video_source && m_qt_video_source->has_new(); }
|
||||
void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<qt_video_source> m_qt_video_source;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
LOG_CHANNEL(cellSaveData);
|
||||
|
||||
s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
|
||||
s32 save_data_dialog::ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
|
||||
{
|
||||
cellSaveData.notice("ShowSaveDataList(save_entries=%d, focused=%d, op=0x%x, listSet=*0x%x, enable_overlay=%d)", save_entries.size(), focused, op, listSet, enable_overlay);
|
||||
|
||||
|
@ -29,7 +29,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
|
|||
{
|
||||
cellSaveData.notice("ShowSaveDataList: Showing native UI dialog");
|
||||
|
||||
const s32 result = manager->create<rsx::overlays::save_dialog>()->show(save_entries, focused, op, listSet, enable_overlay);
|
||||
const s32 result = manager->create<rsx::overlays::save_dialog>()->show(base_dir, save_entries, focused, op, listSet, enable_overlay);
|
||||
if (result != rsx::overlays::user_interface::selection_code::error)
|
||||
{
|
||||
cellSaveData.notice("ShowSaveDataList: Native UI dialog returned with selection %d", result);
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
class save_data_dialog : public SaveDialogBase
|
||||
{
|
||||
public:
|
||||
s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) override;
|
||||
s32 ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) override;
|
||||
};
|
||||
|
|
|
@ -270,13 +270,12 @@ std::vector<SaveDataEntry> save_manager_dialog::GetSaveEntries(const std::string
|
|||
return;
|
||||
}
|
||||
|
||||
SaveDataEntry save_entry2;
|
||||
SaveDataEntry save_entry2 {};
|
||||
save_entry2.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
|
||||
save_entry2.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
|
||||
save_entry2.title = psf::get_string(psf, "TITLE");
|
||||
save_entry2.subtitle = psf::get_string(psf, "SUB_TITLE");
|
||||
save_entry2.details = psf::get_string(psf, "DETAIL");
|
||||
save_entry2.size = 0;
|
||||
|
||||
for (const auto& entry2 : fs::dir(base_dir + entry.name))
|
||||
{
|
||||
|
@ -586,7 +585,7 @@ void save_manager_dialog::OnEntriesRemove()
|
|||
}
|
||||
|
||||
// Pop-up a small context-menu, being a replacement for save_data_manage_dialog
|
||||
void save_manager_dialog::ShowContextMenu(const QPoint &pos)
|
||||
void save_manager_dialog::ShowContextMenu(const QPoint& pos)
|
||||
{
|
||||
const int idx = m_list->currentRow();
|
||||
if (idx == -1)
|
||||
|
|
|
@ -42,7 +42,7 @@ private:
|
|||
void Init();
|
||||
void UpdateList();
|
||||
void UpdateIcons();
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
void ShowContextMenu(const QPoint& pos);
|
||||
void WaitForRepaintThreads(bool abort);
|
||||
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
|
|
@ -76,9 +76,9 @@ shortcut_settings::shortcut_settings()
|
|||
{ shortcut::gw_frame_limit, shortcut_info{ "game_window_frame_limit", tr("Toggle Framelimit"), "Ctrl+F10", shortcut_handler_id::game_window, false } },
|
||||
{ shortcut::gw_toggle_mouse_and_keyboard, shortcut_info{ "game_window_toggle_mouse_and_keyboard", tr("Toggle Keyboard"), "Ctrl+F11", shortcut_handler_id::game_window, false } },
|
||||
{ shortcut::gw_home_menu, shortcut_info{ "gw_home_menu", tr("Open Home Menu"), "Shift+F10", shortcut_handler_id::game_window, false } },
|
||||
{ shortcut::gw_mute_unmute, shortcut_info{ "gw_mute_unmute", tr("Mute/Unmute Audio"), "Shift+M", shortcut_handler_id::game_window, false } },
|
||||
{ shortcut::gw_volume_up, shortcut_info{ "gw_volume_up", tr("Volume Up"), "Shift++", shortcut_handler_id::game_window, true } },
|
||||
{ shortcut::gw_volume_down, shortcut_info{ "gw_volume_down", tr("Volume Down"), "Shift+-", shortcut_handler_id::game_window, true } },
|
||||
{ shortcut::gw_mute_unmute, shortcut_info{ "gw_mute_unmute", tr("Mute/Unmute Audio"), "Ctrl+Shift+M", shortcut_handler_id::game_window, false } },
|
||||
{ shortcut::gw_volume_up, shortcut_info{ "gw_volume_up", tr("Volume Up"), "Ctrl+Shift++", shortcut_handler_id::game_window, true } },
|
||||
{ shortcut::gw_volume_down, shortcut_info{ "gw_volume_down", tr("Volume Down"), "Ctrl+Shift+-", shortcut_handler_id::game_window, true } },
|
||||
})
|
||||
{
|
||||
}
|
||||
|
|
|
@ -504,11 +504,29 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
ISzAlloc allocImp = g_Alloc;
|
||||
ISzAlloc allocTempImp = g_Alloc;
|
||||
|
||||
if (const WRes res = InFile_Open(&archiveStream.file, tmpfile_path.c_str()))
|
||||
const auto WRes_to_string = [](WRes res)
|
||||
{
|
||||
update_log.error("Failed to open temporary storage file: '%s' (error=%d)", tmpfile_path, static_cast<u64>(res));
|
||||
#ifdef _WIN32
|
||||
return fmt::format("0x%x='%s'", res, std::system_category().message(HRESULT_FROM_WIN32(res)));
|
||||
#else
|
||||
return fmt::format("0x%x='%s'", res, strerror(res));
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
const std::wstring tmpfile_path_w = utf8_to_wchar(tmpfile_path);
|
||||
if (const WRes res = InFile_OpenW(&archiveStream.file, tmpfile_path_w.c_str()))
|
||||
{
|
||||
update_log.error("Failed to open temporary storage file: '%s' (error=%s)", tmpfile_path_w.c_str(), WRes_to_string(res));
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (const WRes res = InFile_Open(&archiveStream.file, tmpfile_path.c_str()))
|
||||
{
|
||||
update_log.error("Failed to open temporary storage file: '%s' (error=%s)", tmpfile_path, WRes_to_string(res));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead2_CreateVTable(&lookStream, False);
|
||||
|
@ -529,22 +547,14 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
CrcGenerateTable();
|
||||
SzArEx_Init(&db);
|
||||
|
||||
auto error_free7z = [&]()
|
||||
const auto error_free7z = [&]()
|
||||
{
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
ISzAlloc_Free(&allocImp, lookStream.buf);
|
||||
|
||||
const WRes res2 = File_Close(&archiveStream.file);
|
||||
if (res2) update_log.warning("7z failed to close file (error=%d)", static_cast<u64>(res2));
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: break;
|
||||
case SZ_ERROR_UNSUPPORTED: update_log.error("7z decoder doesn't support this archive"); break;
|
||||
case SZ_ERROR_MEM: update_log.error("7z decoder failed to allocate memory"); break;
|
||||
case SZ_ERROR_CRC: update_log.error("7z decoder CRC error"); break;
|
||||
default: update_log.error("7z decoder error: %d", static_cast<u64>(res)); break;
|
||||
}
|
||||
if (res2) update_log.warning("7z failed to close file (error=%s)", WRes_to_string(res2));
|
||||
if (res) update_log.error("7z decoder error: %s", WRes_to_string(res));
|
||||
};
|
||||
|
||||
if (res != SZ_OK)
|
||||
|
@ -588,7 +598,7 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
const DWORD permissions = (attribs >> 16) & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
const bool is_symlink = (attribs & FILE_ATTRIBUTE_UNIX_EXTENSION) != 0 && S_ISLNK(attribs >> 16);
|
||||
#endif
|
||||
const usz len = SzArEx_GetFileNameUtf16(&db, i, nullptr);
|
||||
const usz len = SzArEx_GetFileNameUtf16(&db, i, nullptr);
|
||||
|
||||
if (len >= PATH_MAX)
|
||||
{
|
||||
|
@ -598,7 +608,7 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
}
|
||||
|
||||
SzArEx_GetFileNameUtf16(&db, i, temp_u16);
|
||||
memset(temp_u8, 0, sizeof(temp_u8));
|
||||
std::memset(temp_u8, 0, sizeof(temp_u8));
|
||||
// Simplistic conversion to UTF-8
|
||||
for (usz index = 0; index < len; index++)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,7 @@ welcome_dialog::welcome_dialog(std::shared_ptr<gui_settings> gui_settings, bool
|
|||
.arg(gui::utils::make_link(tr("Quickstart"), "https://rpcs3.net/quickstart"))
|
||||
.arg(gui::utils::make_link(tr("FAQ"), "https://rpcs3.net/faq"))
|
||||
.arg(gui::utils::make_link(tr("Forums"), "https://forums.rpcs3.net"))
|
||||
.arg(gui::utils::make_link(tr("Discord"), "https://discord.me/RPCS3"))));
|
||||
.arg(gui::utils::make_link(tr("Discord"), "https://discord.gg/rpcs3"))));
|
||||
|
||||
#ifdef __APPLE__
|
||||
ui->create_applications_menu_shortcut->setText(tr("&Create Launchpad shortcut"));
|
||||
|
|
|
@ -1192,7 +1192,7 @@ constexpr void write_to_ptr(U&& array, usz pos, const T& value)
|
|||
{
|
||||
static_assert(sizeof(T) % sizeof(array[0]) == 0);
|
||||
if (!std::is_constant_evaluated())
|
||||
std::memcpy(&array[pos], &value, sizeof(value));
|
||||
std::memcpy(static_cast<void*>(&array[pos]), &value, sizeof(value));
|
||||
else
|
||||
ensure(!"Unimplemented");
|
||||
}
|
||||
|
|
|
@ -1,20 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.hpp"
|
||||
#include <functional>
|
||||
|
||||
class video_source
|
||||
{
|
||||
public:
|
||||
video_source() {};
|
||||
virtual ~video_source() {};
|
||||
virtual void set_video_path(const std::string& path) { static_cast<void>(path); }
|
||||
virtual bool has_new() const { return false; };
|
||||
virtual void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp)
|
||||
virtual void set_video_path(const std::string& video_path) = 0;
|
||||
virtual void set_active(bool active) = 0;
|
||||
virtual bool get_active() const = 0;
|
||||
virtual bool has_new() const = 0;
|
||||
virtual void get_image(std::vector<u8>& data, int& w, int& h, int& ch, int& bpp) = 0;
|
||||
|
||||
void set_update_callback(std::function<void()> callback)
|
||||
{
|
||||
static_cast<void>(data);
|
||||
static_cast<void>(w);
|
||||
static_cast<void>(h);
|
||||
static_cast<void>(ch);
|
||||
static_cast<void>(bpp);
|
||||
m_update_callback = callback;
|
||||
}
|
||||
|
||||
protected:
|
||||
void notify_update()
|
||||
{
|
||||
if (m_update_callback)
|
||||
{
|
||||
m_update_callback();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_update_callback;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue