Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9266aa1317 | |||
| f753bfac94 | |||
| 772e605617 | |||
| 90ac2b3399 | |||
| da3843e871 | |||
| 5765b47bee | |||
| 8aca7f4808 | |||
| 1968027229 | |||
| 827bed69b5 | |||
| 77ada8e7dc | |||
| 6ef87d39f6 | |||
| ba53fe9cee | |||
| 0190c0e9d3 | |||
| 02bb79e245 | |||
| 335fb6456e | |||
| 91b73dafd5 | |||
| c65dba7862 | |||
| 711e117dd2 | |||
| 1f62da8a70 | |||
| aa2aa70875 | |||
| fe7cba5eac | |||
| cf18699748 | |||
| 49cff4ed4b | |||
| e630c828c3 | |||
| c2806c8d11 |
+1
-1
@@ -5,7 +5,7 @@ IndentWidth: 1
|
||||
AccessModifierOffset: -1
|
||||
PointerAlignment: Left
|
||||
NamespaceIndentation: All
|
||||
ColumnLimit: 200
|
||||
ColumnLimit: 100
|
||||
BreakBeforeBraces: Allman
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakBeforeBinaryOperators: false
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<!---
|
||||
|
||||
THIS IS NOT A SUPPORT FORUM, FOR SUPPORT GO TO:
|
||||
https://forums.rpcs3.net
|
||||
or our discord:
|
||||
https://discord.me/RPCS3
|
||||
|
||||
PLEASE READ THE GUIDELINES BEFORE OPENING AN ISSUE:
|
||||
https://github.com/RPCS3/rpcs3/blob/master/CONTRIBUTING.md
|
||||
|
||||
====================================================
|
||||
|
||||
When submitting an issue, please check the following:
|
||||
|
||||
- You have read the above.
|
||||
- You have provided the version (commit hash) of RPCS3 you are using.
|
||||
- You have provided sufficient detail for the issue to be reproduced.
|
||||
- You have provided system specs.
|
||||
- Please also provide:
|
||||
- For crashes, a backtrace.
|
||||
- For graphical issues, comparison screenshots with real hardware.
|
||||
|
||||
Remember that the GitHub Issue Tracker is not the place to ask for support or to submit Game Compatibility reports. You must use our forums for that.
|
||||
--->
|
||||
+3
-14
@@ -41,10 +41,7 @@
|
||||
/Vulkan/Vulkan-build
|
||||
/Vulkan/glslang-build
|
||||
|
||||
# Themes
|
||||
!/bin/GuiConfigs/
|
||||
/bin/GuiConfigs/*.ini
|
||||
|
||||
/wxWidgets/lib
|
||||
/bin/rpcs3.ini
|
||||
/bin/rpcs3.ipdb
|
||||
/bin/rpcs3.iobj
|
||||
@@ -58,12 +55,9 @@
|
||||
rpcs3/git-version.h
|
||||
|
||||
# Visual Studio Files
|
||||
.vs/*
|
||||
*.ipch
|
||||
*.vspx
|
||||
*.psess
|
||||
*.VC.*
|
||||
*.vcxproj.user
|
||||
|
||||
# Copyrighted files
|
||||
/bin/data/
|
||||
@@ -75,7 +69,6 @@ rpcs3/git-version.h
|
||||
!/bin/dev_hdd0/game/
|
||||
/bin/dev_hdd0/game/*
|
||||
!/bin/dev_hdd0/game/TEST12345/
|
||||
/bin/dev_hdd0/disc/*
|
||||
|
||||
# Ignore other system generated files
|
||||
bin/dev_hdd0/*.txt
|
||||
@@ -92,9 +85,5 @@ CMakeCache.txt
|
||||
# cotire
|
||||
rpcs3/cotire/*
|
||||
rpcs3/rpcs3_*_cotire.cmake
|
||||
|
||||
# Qt
|
||||
moc_*.cpp
|
||||
qrc_resources.cpp
|
||||
rpcs3_automoc.cpp
|
||||
ui_*.h
|
||||
/.vs/rpcs3/v15/ipch/AutoPCH/VKGSRENDER-1a48cf59/VKGSRENDER-717b8989/*.ipch
|
||||
/.vs/rpcs3/v15/ipch/EMUCORE-4bdb26ae/*.ipch
|
||||
|
||||
+12
-9
@@ -1,3 +1,7 @@
|
||||
[submodule "wxWidgets"]
|
||||
path = wxWidgets
|
||||
url = https://github.com/Zangetsu38/wxWidgets
|
||||
ignore = dirty
|
||||
[submodule "rpcs3-ffmpeg"]
|
||||
path = 3rdparty/ffmpeg
|
||||
url = https://github.com/hrydgard/ppsspp-ffmpeg
|
||||
@@ -8,13 +12,16 @@
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
url = https://github.com/llvm-mirror/llvm
|
||||
branch = release_50
|
||||
branch = release_39
|
||||
[submodule "rsx_program_decompiler"]
|
||||
path = rsx_program_decompiler
|
||||
url = https://github.com/Zangetsu38/rsx_program_decompiler
|
||||
[submodule "GSL"]
|
||||
path = 3rdparty/GSL
|
||||
url = https://github.com/Microsoft/GSL.git
|
||||
[submodule "libpng"]
|
||||
path = 3rdparty/libpng
|
||||
url = https://github.com/Zangetsu38/libpng
|
||||
url = https://github.com/RPCS3/libpng
|
||||
ignore = dirty
|
||||
[submodule "Vulkan/glslang"]
|
||||
path = Vulkan/glslang
|
||||
@@ -31,10 +38,6 @@
|
||||
[submodule "3rdparty/cereal"]
|
||||
path = 3rdparty/cereal
|
||||
url = https://github.com/USCiLab/cereal.git
|
||||
[submodule "3rdparty/zlib"]
|
||||
path = 3rdparty/zlib
|
||||
url = https://github.com/madler/zlib
|
||||
[submodule "3rdparty/hidapi"]
|
||||
path = 3rdparty/hidapi
|
||||
url = https://github.com/Zangetsu38/hidapi
|
||||
branch = master
|
||||
[submodule "rsx-debugger"]
|
||||
path = rsx-debugger
|
||||
url = https://github.com/RPCS3/rsx-debugger.git
|
||||
|
||||
+60
-92
@@ -1,122 +1,90 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- linux
|
||||
#- osx
|
||||
- linux
|
||||
# - osx
|
||||
|
||||
# osx_image: xcode6.4
|
||||
osx_image: xcode6.4
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- $HOME/hombebrew_cache
|
||||
env:
|
||||
global:
|
||||
- secure: "Vf+FY48nip9JppMnq11105NealdErSWsoUhHo63/V3V+LKfA9guenxCp93/qoSIdSGC/sJwb0yIIMGvkTT/rxDJNh6Z+BWUTb2E0WEIIQbvTJNOSUzoq7dfF1LT61XjVjByFzcbC2xjtaBowmcAYEs1jGUUuEjYVCMmD5lY8hUg="
|
||||
# Which Travis environment to run Coverity on
|
||||
- coverity_scan_run_condition='"$TRAVIS_OS_NAME" = linux -a "$CC" = gcc'
|
||||
# Test mode is for testing if it's working with Coverity. Change to true if testing, to avoid reaching the quota.
|
||||
- coverity_scan_script_test_mode=false
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
|
||||
git:
|
||||
submodules: false
|
||||
|
||||
before_install:
|
||||
- if [ "$CC" = "clang" ]; then
|
||||
export CXX="clang++-4.0" CC="clang-4.0";
|
||||
fi;
|
||||
# shutdown services on Travis, which may have a memory impact
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
sudo apt-get install -y libwxgtk3.0-dev;
|
||||
fi;
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$CXX" = "g++" ]; then
|
||||
export CXX="g++-5" CC="gcc-5" CXXFLAGS="-Wno-format-security";
|
||||
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01';
|
||||
fi;
|
||||
# Add coverall for C++ so coverall.io could be triggered. Even it should be --coverage and gcov.
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
wget http://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run ;
|
||||
chmod a+x ./qt-unified-linux-x64-online.run ;
|
||||
export QT_QPA_PLATFORM=minimal ;
|
||||
./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations ;
|
||||
fi;
|
||||
|
||||
# Install updated libglew-dev since the version provided by trusty is outdated
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew-dev_1.13.0-2_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew1.13_1.13.0-2_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
sudo dpkg -i libglew1.13_1.13.0-2_amd64.deb libglew-dev_1.13.0-2_amd64.deb libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
sudo pip install cpp-coveralls requests[security];
|
||||
else
|
||||
brew update;
|
||||
brew install ccache glew llvm40;
|
||||
brew update; brew update;
|
||||
brew install glew wxwidgets llvm38;
|
||||
fi;
|
||||
|
||||
before_script:
|
||||
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal 3rdparty/hidapi Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
- mkdir build
|
||||
- cd build
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
|
||||
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
|
||||
else
|
||||
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/#$TRAVIS_PULL_REQUEST";
|
||||
fi;
|
||||
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
|
||||
- make -j 3
|
||||
- # AppImage generation
|
||||
- if [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.9.1/gcc_64/lib;
|
||||
make DESTDIR=appdir install ; find appdir/ ;
|
||||
find ../bin ;
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
|
||||
chmod a+x linuxdeployqt*.AppImage ;
|
||||
export PATH=~/Qt/5.9.1/gcc_64/bin/:${PATH} ;
|
||||
./linuxdeployqt*.AppImage --appimage-extract ;
|
||||
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
|
||||
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
mkdir ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ;
|
||||
./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ;
|
||||
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq ;
|
||||
curl ${UPLOAD_URL}${TRAVIS_COMMIT:0:7}-${TRAVIS_BUILD_NUMBER}_linux64 --upload-file ./RPCS3*.AppImage;
|
||||
fi;
|
||||
- git submodule update --init rsx_program_decompiler asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cmake ..; else cmake .. -DLLVM_DIR=/usr/local/opt/llvm38/lib/llvm-3.8/share/llvm/cmake; fi
|
||||
|
||||
script:
|
||||
# Add a command to show all the variables. May be useful for debugging Travis.
|
||||
#- echo "--Shell Export Lists START--" ; export -p; echo "--Shell Export Lists STOP--";
|
||||
# And to ensure the versions of toolchain
|
||||
- echo "--CXX version?"; "$CXX" --version; echo "--CXX version confirmed";
|
||||
# Add a command to show all the variables. May be useful for debugging Travis.
|
||||
# - echo "--Shell Export Lists START--" ; export -p; echo "--Shell Export Lists STOP--";
|
||||
# And to ensure the versions of toolchain
|
||||
- echo "--CXX version?"; "$CXX" --version; echo "--CXX version confirmed";
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j 4; fi
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:jonathonf/binutils' # We need to update binutils to a newer version to link against the ffmpeg libs on.
|
||||
- ubuntu-toolchain-r-test
|
||||
# - llvm-toolchain-trusty-3.8 temporarily disabled
|
||||
packages:
|
||||
- binutils
|
||||
- cmake
|
||||
- libasound2-dev
|
||||
- libopenal-dev
|
||||
- freeglut3-dev
|
||||
#- libglew-dev
|
||||
#- libvulkan1
|
||||
#- libvulkan-dev
|
||||
- libc6-dev
|
||||
- llvm-4.0
|
||||
- llvm-4.0-dev
|
||||
- clang-4.0
|
||||
- libedit-dev
|
||||
- g++-5
|
||||
- gcc-5
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
# We need to install qt 5.9.1 manually because the version trusty provides is too old.
|
||||
#- qtbase5-dev
|
||||
- libudev-dev
|
||||
- libevdev-dev
|
||||
- libpulse-dev
|
||||
- cmake
|
||||
- libopenal-dev
|
||||
- freeglut3-dev
|
||||
- libglew-dev
|
||||
- libc6-dev
|
||||
# - llvm-3.8
|
||||
# - llvm-3.8-dev
|
||||
- libedit-dev
|
||||
- g++-5
|
||||
- gcc-5
|
||||
# - clang-3.6
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
coverity_scan:
|
||||
project:
|
||||
name: $TRAVIS_REPO_SLUG
|
||||
description: "PS3 emulator/debugger"
|
||||
notification_email: raul.tambre@gmail.com
|
||||
build_command: "make -j 4"
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
after_success:
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "$TRAVIS_OS_NAME" = linux ]; then coveralls --extension .c --extension .cpp --extension .h; fi
|
||||
|
||||
Vendored
+6
-117
@@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2013-2017 The Khronos Group Inc.
|
||||
** Copyright (c) 2013-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
@@ -31,7 +31,9 @@ extern "C" {
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** https://github.com/KhronosGroup/OpenGL-Registry
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 33248 $ on $Date: 2016-10-24 01:22:03 -0400 (Mon, 24 Oct 2016) $
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||
@@ -51,7 +53,7 @@ extern "C" {
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
|
||||
#define GL_GLEXT_VERSION 20170305
|
||||
#define GL_GLEXT_VERSION 20161024
|
||||
|
||||
/* Generated C header for:
|
||||
* API: gl
|
||||
@@ -3353,16 +3355,6 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen
|
||||
#define GL_ARB_get_texture_sub_image 1
|
||||
#endif /* GL_ARB_get_texture_sub_image */
|
||||
|
||||
#ifndef GL_ARB_gl_spirv
|
||||
#define GL_ARB_gl_spirv 1
|
||||
#define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551
|
||||
#define GL_SPIR_V_BINARY_ARB 0x9552
|
||||
typedef void (APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glSpecializeShaderARB (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
|
||||
#endif
|
||||
#endif /* GL_ARB_gl_spirv */
|
||||
|
||||
#ifndef GL_ARB_gpu_shader5
|
||||
#define GL_ARB_gpu_shader5 1
|
||||
#endif /* GL_ARB_gpu_shader5 */
|
||||
@@ -5382,24 +5374,6 @@ GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRG
|
||||
#endif
|
||||
#endif /* GL_AMD_draw_buffers_blend */
|
||||
|
||||
#ifndef GL_AMD_framebuffer_sample_positions
|
||||
#define GL_AMD_framebuffer_sample_positions 1
|
||||
#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
|
||||
#define GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE
|
||||
#define GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF
|
||||
#define GL_ALL_PIXELS_AMD 0xFFFFFFFF
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC) (GLenum target, GLuint numsamples, GLuint pixelindex, const GLfloat *values);
|
||||
typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC) (GLuint framebuffer, GLuint numsamples, GLuint pixelindex, const GLfloat *values);
|
||||
typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERFVAMDPROC) (GLenum target, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values);
|
||||
typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERFVAMDPROC) (GLuint framebuffer, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glFramebufferSamplePositionsfvAMD (GLenum target, GLuint numsamples, GLuint pixelindex, const GLfloat *values);
|
||||
GLAPI void APIENTRY glNamedFramebufferSamplePositionsfvAMD (GLuint framebuffer, GLuint numsamples, GLuint pixelindex, const GLfloat *values);
|
||||
GLAPI void APIENTRY glGetFramebufferParameterfvAMD (GLenum target, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values);
|
||||
GLAPI void APIENTRY glGetNamedFramebufferParameterfvAMD (GLuint framebuffer, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values);
|
||||
#endif
|
||||
#endif /* GL_AMD_framebuffer_sample_positions */
|
||||
|
||||
#ifndef GL_AMD_gcn_shader
|
||||
#define GL_AMD_gcn_shader 1
|
||||
#endif /* GL_AMD_gcn_shader */
|
||||
@@ -5620,6 +5594,7 @@ GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname
|
||||
|
||||
#ifndef GL_AMD_sample_positions
|
||||
#define GL_AMD_sample_positions 1
|
||||
#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
|
||||
typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val);
|
||||
@@ -8994,10 +8969,6 @@ GLAPI void APIENTRY glResizeBuffersMESA (void);
|
||||
#endif
|
||||
#endif /* GL_MESA_resize_buffers */
|
||||
|
||||
#ifndef GL_MESA_shader_integer_functions
|
||||
#define GL_MESA_shader_integer_functions 1
|
||||
#endif /* GL_MESA_shader_integer_functions */
|
||||
|
||||
#ifndef GL_MESA_window_pos
|
||||
#define GL_MESA_window_pos 1
|
||||
typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
|
||||
@@ -9059,10 +9030,6 @@ GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v);
|
||||
#define GL_YCBCR_MESA 0x8757
|
||||
#endif /* GL_MESA_ycbcr_texture */
|
||||
|
||||
#ifndef GL_NVX_blend_equation_advanced_multi_draw_buffers
|
||||
#define GL_NVX_blend_equation_advanced_multi_draw_buffers 1
|
||||
#endif /* GL_NVX_blend_equation_advanced_multi_draw_buffers */
|
||||
|
||||
#ifndef GL_NVX_conditional_render
|
||||
#define GL_NVX_conditional_render 1
|
||||
typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
|
||||
@@ -9082,32 +9049,6 @@ GLAPI void APIENTRY glEndConditionalRenderNVX (void);
|
||||
#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
|
||||
#endif /* GL_NVX_gpu_memory_info */
|
||||
|
||||
#ifndef GL_NVX_linked_gpu_multicast
|
||||
#define GL_NVX_linked_gpu_multicast 1
|
||||
#define GL_LGPU_SEPARATE_STORAGE_BIT_NVX 0x0800
|
||||
#define GL_MAX_LGPU_GPUS_NVX 0x92BA
|
||||
typedef void (APIENTRYP PFNGLLGPUNAMEDBUFFERSUBDATANVXPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
typedef void (APIENTRYP PFNGLLGPUCOPYIMAGESUBDATANVXPROC) (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
|
||||
typedef void (APIENTRYP PFNGLLGPUINTERLOCKNVXPROC) (void);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glLGPUNamedBufferSubDataNVX (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
GLAPI void APIENTRY glLGPUCopyImageSubDataNVX (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
|
||||
GLAPI void APIENTRY glLGPUInterlockNVX (void);
|
||||
#endif
|
||||
#endif /* GL_NVX_linked_gpu_multicast */
|
||||
|
||||
#ifndef GL_NV_alpha_to_coverage_dither_control
|
||||
#define GL_NV_alpha_to_coverage_dither_control 1
|
||||
#define GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV 0x934D
|
||||
#define GL_ALPHA_TO_COVERAGE_DITHER_ENABLE_NV 0x934E
|
||||
#define GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV 0x934F
|
||||
#define GL_ALPHA_TO_COVERAGE_DITHER_MODE_NV 0x92BF
|
||||
typedef void (APIENTRYP PFNGLALPHATOCOVERAGEDITHERCONTROLNVPROC) (GLenum mode);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glAlphaToCoverageDitherControlNV (GLenum mode);
|
||||
#endif
|
||||
#endif /* GL_NV_alpha_to_coverage_dither_control */
|
||||
|
||||
#ifndef GL_NV_bindless_multi_draw_indirect
|
||||
#define GL_NV_bindless_multi_draw_indirect 1
|
||||
typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
|
||||
@@ -9401,23 +9342,6 @@ GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0,
|
||||
#endif
|
||||
#endif /* GL_NV_draw_texture */
|
||||
|
||||
#ifndef GL_NV_draw_vulkan_image
|
||||
#define GL_NV_draw_vulkan_image 1
|
||||
typedef void (APIENTRY *GLVULKANPROCNV)(void);
|
||||
typedef void (APIENTRYP PFNGLDRAWVKIMAGENVPROC) (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
|
||||
typedef GLVULKANPROCNV (APIENTRYP PFNGLGETVKPROCADDRNVPROC) (const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLWAITVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
|
||||
typedef void (APIENTRYP PFNGLSIGNALVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
|
||||
typedef void (APIENTRYP PFNGLSIGNALVKFENCENVPROC) (GLuint64 vkFence);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawVkImageNV (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
|
||||
GLAPI GLVULKANPROCNV APIENTRY glGetVkProcAddrNV (const GLchar *name);
|
||||
GLAPI void APIENTRY glWaitVkSemaphoreNV (GLuint64 vkSemaphore);
|
||||
GLAPI void APIENTRY glSignalVkSemaphoreNV (GLuint64 vkSemaphore);
|
||||
GLAPI void APIENTRY glSignalVkFenceNV (GLuint64 vkFence);
|
||||
#endif
|
||||
#endif /* GL_NV_draw_vulkan_image */
|
||||
|
||||
#ifndef GL_NV_evaluators
|
||||
#define GL_NV_evaluators 1
|
||||
#define GL_EVAL_2D_NV 0x86C0
|
||||
@@ -9652,41 +9576,6 @@ GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachmen
|
||||
#define GL_NV_geometry_shader_passthrough 1
|
||||
#endif /* GL_NV_geometry_shader_passthrough */
|
||||
|
||||
#ifndef GL_NV_gpu_multicast
|
||||
#define GL_NV_gpu_multicast 1
|
||||
#define GL_PER_GPU_STORAGE_BIT_NV 0x0800
|
||||
#define GL_MULTICAST_GPUS_NV 0x92BA
|
||||
#define GL_RENDER_GPU_MASK_NV 0x9558
|
||||
#define GL_PER_GPU_STORAGE_NV 0x9548
|
||||
#define GL_MULTICAST_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9549
|
||||
typedef void (APIENTRYP PFNGLRENDERGPUMASKNVPROC) (GLbitfield mask);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTBUFFERSUBDATANVPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC) (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTCOPYIMAGESUBDATANVPROC) (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTBLITFRAMEBUFFERNVPROC) (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTBARRIERNVPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTWAITSYNCNVPROC) (GLuint signalGpu, GLbitfield waitGpuMask);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint *params);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint64 *params);
|
||||
typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glRenderGpuMaskNV (GLbitfield mask);
|
||||
GLAPI void APIENTRY glMulticastBufferSubDataNV (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
|
||||
GLAPI void APIENTRY glMulticastCopyBufferSubDataNV (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
GLAPI void APIENTRY glMulticastCopyImageSubDataNV (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
|
||||
GLAPI void APIENTRY glMulticastBlitFramebufferNV (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
GLAPI void APIENTRY glMulticastFramebufferSampleLocationsfvNV (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
|
||||
GLAPI void APIENTRY glMulticastBarrierNV (void);
|
||||
GLAPI void APIENTRY glMulticastWaitSyncNV (GLuint signalGpu, GLbitfield waitGpuMask);
|
||||
GLAPI void APIENTRY glMulticastGetQueryObjectivNV (GLuint gpu, GLuint id, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glMulticastGetQueryObjectuivNV (GLuint gpu, GLuint id, GLenum pname, GLuint *params);
|
||||
GLAPI void APIENTRY glMulticastGetQueryObjecti64vNV (GLuint gpu, GLuint id, GLenum pname, GLint64 *params);
|
||||
GLAPI void APIENTRY glMulticastGetQueryObjectui64vNV (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params);
|
||||
#endif
|
||||
#endif /* GL_NV_gpu_multicast */
|
||||
|
||||
#ifndef GL_NV_gpu_program4
|
||||
#define GL_NV_gpu_program4 1
|
||||
#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/GSL updated: 2b8d20425e...fc5fce4f4f
Vendored
+1
-1
Submodule 3rdparty/ffmpeg updated: 7b7ae7b067...2f6023d14a
Vendored
-1
Submodule 3rdparty/hidapi deleted from 4c2750112e
Vendored
+1
-1
Submodule 3rdparty/libpng updated: bbbcaf1122...ea77a6fd49
-25
@@ -1,25 +0,0 @@
|
||||
//---------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This file is automatically generated. Please do not edit it directly.
|
||||
//
|
||||
// File name: D2DBaseTypes.h
|
||||
//---------------------------------------------------------------------------
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif // #ifdef _MSC_VER
|
||||
|
||||
#ifndef _D2DBASETYPES_INCLUDED
|
||||
#define _D2DBASETYPES_INCLUDED
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif // #ifndef COM_NO_WINDOWS_H
|
||||
#ifndef __dxgitype_h__
|
||||
#include <dxgitype.h>
|
||||
#endif // #ifndef __dxgitype_h__
|
||||
#ifndef DCOMMON_H_INCLUDED
|
||||
#include <dcommon.h>
|
||||
#endif // #ifndef DCOMMON_H_INCLUDED
|
||||
typedef D3DCOLORVALUE D2D_COLOR_F;
|
||||
#endif // #ifndef _D2DBASETYPES_INCLUDED
|
||||
Vendored
+48
-48
@@ -1022,54 +1022,6 @@ typedef struct D2D1_FACTORY_OPTIONS
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region Application Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1Resource;
|
||||
EXTERN_C CONST IID IID_ID2D1Image;
|
||||
EXTERN_C CONST IID IID_ID2D1Bitmap;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientStopCollection;
|
||||
EXTERN_C CONST IID IID_ID2D1Brush;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1SolidColorBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1LinearGradientBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1RadialGradientBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1StrokeStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1Geometry;
|
||||
EXTERN_C CONST IID IID_ID2D1RectangleGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1RoundedRectangleGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1EllipseGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1GeometryGroup;
|
||||
EXTERN_C CONST IID IID_ID2D1TransformedGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1SimplifiedGeometrySink;
|
||||
EXTERN_C CONST IID IID_ID2D1GeometrySink;
|
||||
EXTERN_C CONST IID IID_ID2D1TessellationSink;
|
||||
EXTERN_C CONST IID IID_ID2D1PathGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1Mesh;
|
||||
EXTERN_C CONST IID IID_ID2D1Layer;
|
||||
EXTERN_C CONST IID IID_ID2D1DrawingStateBlock;
|
||||
EXTERN_C CONST IID IID_ID2D1RenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1HwndRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1DCRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory;
|
||||
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Desktop Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GdiInteropRenderTarget;
|
||||
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
@@ -3567,6 +3519,54 @@ interface DX_DECLARE_INTERFACE("06152247-6f50-465a-9245-118bfd3b6007") ID2D1Fact
|
||||
#endif
|
||||
|
||||
|
||||
#pragma region Application Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1Resource;
|
||||
EXTERN_C CONST IID IID_ID2D1Image;
|
||||
EXTERN_C CONST IID IID_ID2D1Bitmap;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientStopCollection;
|
||||
EXTERN_C CONST IID IID_ID2D1Brush;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1SolidColorBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1LinearGradientBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1RadialGradientBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1StrokeStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1Geometry;
|
||||
EXTERN_C CONST IID IID_ID2D1RectangleGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1RoundedRectangleGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1EllipseGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1GeometryGroup;
|
||||
EXTERN_C CONST IID IID_ID2D1TransformedGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1SimplifiedGeometrySink;
|
||||
EXTERN_C CONST IID IID_ID2D1GeometrySink;
|
||||
EXTERN_C CONST IID IID_ID2D1TessellationSink;
|
||||
EXTERN_C CONST IID IID_ID2D1PathGeometry;
|
||||
EXTERN_C CONST IID IID_ID2D1Mesh;
|
||||
EXTERN_C CONST IID IID_ID2D1Layer;
|
||||
EXTERN_C CONST IID IID_ID2D1DrawingStateBlock;
|
||||
EXTERN_C CONST IID IID_ID2D1RenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1HwndRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1DCRenderTarget;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory;
|
||||
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Desktop Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GdiInteropRenderTarget;
|
||||
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#ifdef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
|
||||
Vendored
+21
-22
@@ -344,7 +344,6 @@ typedef enum D2D1_PRIMITIVE_BLEND
|
||||
D2D1_PRIMITIVE_BLEND_COPY = 1,
|
||||
D2D1_PRIMITIVE_BLEND_MIN = 2,
|
||||
D2D1_PRIMITIVE_BLEND_ADD = 3,
|
||||
D2D1_PRIMITIVE_BLEND_MAX = 4,
|
||||
D2D1_PRIMITIVE_BLEND_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_PRIMITIVE_BLEND;
|
||||
@@ -643,27 +642,6 @@ typedef struct D2D1_CREATION_PROPERTIES
|
||||
} D2D1_CREATION_PROPERTIES;
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafileSink;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafile;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandList;
|
||||
EXTERN_C CONST IID IID_ID2D1PrintControl;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapBrush1;
|
||||
EXTERN_C CONST IID IID_ID2D1StrokeStyle1;
|
||||
EXTERN_C CONST IID IID_ID2D1PathGeometry1;
|
||||
EXTERN_C CONST IID IID_ID2D1Properties;
|
||||
EXTERN_C CONST IID IID_ID2D1Effect;
|
||||
EXTERN_C CONST IID IID_ID2D1Bitmap1;
|
||||
EXTERN_C CONST IID IID_ID2D1ColorContext;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientStopCollection1;
|
||||
EXTERN_C CONST IID IID_ID2D1DrawingStateBlock1;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext;
|
||||
EXTERN_C CONST IID IID_ID2D1Device;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory1;
|
||||
EXTERN_C CONST IID IID_ID2D1Multithread;
|
||||
|
||||
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
@@ -2396,6 +2374,27 @@ interface DX_DECLARE_INTERFACE("31e6e7bc-e0ff-4d46-8c64-a0a8c41c15d3") ID2D1Mult
|
||||
#endif
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafileSink;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafile;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandList;
|
||||
EXTERN_C CONST IID IID_ID2D1PrintControl;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageBrush;
|
||||
EXTERN_C CONST IID IID_ID2D1BitmapBrush1;
|
||||
EXTERN_C CONST IID IID_ID2D1StrokeStyle1;
|
||||
EXTERN_C CONST IID IID_ID2D1PathGeometry1;
|
||||
EXTERN_C CONST IID IID_ID2D1Properties;
|
||||
EXTERN_C CONST IID IID_ID2D1Effect;
|
||||
EXTERN_C CONST IID IID_ID2D1Bitmap1;
|
||||
EXTERN_C CONST IID IID_ID2D1ColorContext;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientStopCollection1;
|
||||
EXTERN_C CONST IID IID_ID2D1DrawingStateBlock1;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext;
|
||||
EXTERN_C CONST IID IID_ID2D1Device;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory1;
|
||||
EXTERN_C CONST IID IID_ID2D1Multithread;
|
||||
|
||||
|
||||
#ifdef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
|
||||
Vendored
+7
-7
@@ -45,13 +45,6 @@ typedef enum D2D1_RENDERING_PRIORITY
|
||||
} D2D1_RENDERING_PRIORITY;
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GeometryRealization;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext1;
|
||||
EXTERN_C CONST IID IID_ID2D1Device1;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory2;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink1;
|
||||
|
||||
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
@@ -164,6 +157,13 @@ interface DX_DECLARE_INTERFACE("9eb767fd-4269-4467-b8c2-eb30cb305743") ID2D1Comm
|
||||
#endif
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1GeometryRealization;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext1;
|
||||
EXTERN_C CONST IID IID_ID2D1Device1;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory2;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink1;
|
||||
|
||||
|
||||
#ifdef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
|
||||
Vendored
+23
-263
@@ -18,9 +18,6 @@
|
||||
#ifndef _D2D1_EFFECTS_2_
|
||||
#include <d2d1effects_2.h>
|
||||
#endif // #ifndef _D2D1_EFFECTS_2_
|
||||
#ifndef _D2D1_SVG_
|
||||
#include <d2d1svg.h>
|
||||
#endif // #ifndef _D2D1_SVG_
|
||||
|
||||
#include <winapifamily.h>
|
||||
|
||||
@@ -388,113 +385,11 @@ typedef enum D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION
|
||||
} D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This determines what gamma is used for interpolation/blending.
|
||||
/// </summary>
|
||||
typedef enum D2D1_GAMMA1
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Colors are manipulated in 2.2 gamma color space.
|
||||
/// </summary>
|
||||
D2D1_GAMMA1_G22 = D2D1_GAMMA_2_2,
|
||||
|
||||
/// <summary>
|
||||
/// Colors are manipulated in 1.0 gamma color space.
|
||||
/// </summary>
|
||||
D2D1_GAMMA1_G10 = D2D1_GAMMA_1_0,
|
||||
|
||||
/// <summary>
|
||||
/// Colors are manipulated in ST.2084 PQ gamma color space.
|
||||
/// </summary>
|
||||
D2D1_GAMMA1_G2084 = 2,
|
||||
D2D1_GAMMA1_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_GAMMA1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Simple description of a color space.
|
||||
/// </summary>
|
||||
typedef struct D2D1_SIMPLE_COLOR_PROFILE
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The XY coordinates of the red primary in CIEXYZ space.
|
||||
/// </summary>
|
||||
D2D1_POINT_2F redPrimary;
|
||||
|
||||
/// <summary>
|
||||
/// The XY coordinates of the green primary in CIEXYZ space.
|
||||
/// </summary>
|
||||
D2D1_POINT_2F greenPrimary;
|
||||
|
||||
/// <summary>
|
||||
/// The XY coordinates of the blue primary in CIEXYZ space.
|
||||
/// </summary>
|
||||
D2D1_POINT_2F bluePrimary;
|
||||
|
||||
/// <summary>
|
||||
/// The X/Z tristimulus values for the whitepoint, normalized for relative
|
||||
/// luminance.
|
||||
/// </summary>
|
||||
D2D1_POINT_2F whitePointXZ;
|
||||
|
||||
/// <summary>
|
||||
/// The gamma encoding to use for this color space.
|
||||
/// </summary>
|
||||
D2D1_GAMMA1 gamma;
|
||||
|
||||
} D2D1_SIMPLE_COLOR_PROFILE;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which way a color profile is defined.
|
||||
/// </summary>
|
||||
typedef enum D2D1_COLOR_CONTEXT_TYPE
|
||||
{
|
||||
D2D1_COLOR_CONTEXT_TYPE_ICC = 0,
|
||||
D2D1_COLOR_CONTEXT_TYPE_SIMPLE = 1,
|
||||
D2D1_COLOR_CONTEXT_TYPE_DXGI = 2,
|
||||
D2D1_COLOR_CONTEXT_TYPE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_COLOR_CONTEXT_TYPE;
|
||||
|
||||
|
||||
|
||||
typedef enum DWRITE_GLYPH_IMAGE_FORMATS DWRITE_GLYPH_IMAGE_FORMATS;
|
||||
|
||||
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1InkStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1Ink;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientMesh;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageSource;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageSourceFromWic;
|
||||
EXTERN_C CONST IID IID_ID2D1TransformedImageSource;
|
||||
EXTERN_C CONST IID IID_ID2D1LookupTable3D;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext2;
|
||||
EXTERN_C CONST IID IID_ID2D1Device2;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory3;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink2;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafile1;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafileSink1;
|
||||
EXTERN_C CONST IID IID_ID2D1SpriteBatch;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext3;
|
||||
EXTERN_C CONST IID IID_ID2D1Device3;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory4;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink3;
|
||||
EXTERN_C CONST IID IID_ID2D1SvgGlyphStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext4;
|
||||
EXTERN_C CONST IID IID_ID2D1Device4;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory5;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink4;
|
||||
EXTERN_C CONST IID IID_ID2D1ColorContext1;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext5;
|
||||
EXTERN_C CONST IID IID_ID2D1Device5;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory6;
|
||||
|
||||
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
@@ -1541,167 +1436,32 @@ interface DX_DECLARE_INTERFACE("c4349994-838e-4b0f-8cab-44997d9eeacc") ID2D1Fact
|
||||
|
||||
|
||||
#endif // #if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS2
|
||||
|
||||
interface DX_DECLARE_INTERFACE("c78a6519-40d6-4218-b2de-beeeb744bb3e") ID2D1CommandSink4 : public ID2D1CommandSink3
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A new function to set blend mode that respects the new MAX blend.
|
||||
///
|
||||
/// Implementers of SetPrimitiveBlend2 should expect and handle blend mode:
|
||||
/// D2D1_PRIMITIVE_BLEND_MAX
|
||||
///
|
||||
/// Implementers of SetPrimitiveBlend1 should expect and handle blend modes:
|
||||
/// D2D1_PRIMITIVE_BLEND_MIN and D2D1_PRIMITIVE_BLEND_ADD
|
||||
///
|
||||
/// Implementers of SetPrimitiveBlend should expect and handle blend modes:
|
||||
/// D2D1_PRIMITIVE_BLEND_SOURCE_OVER and D2D1_PRIMITIVE_BLEND_COPY
|
||||
/// </summary>
|
||||
STDMETHOD(SetPrimitiveBlend2)(
|
||||
D2D1_PRIMITIVE_BLEND primitiveBlend
|
||||
) PURE;
|
||||
}; // interface ID2D1CommandSink4
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a color context to be used with the Color Management Effect.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("1ab42875-c57f-4be9-bd85-9cd78d6f55ee") ID2D1ColorContext1 : public ID2D1ColorContext
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the color context type.
|
||||
/// </summary>
|
||||
STDMETHOD_(D2D1_COLOR_CONTEXT_TYPE, GetColorContextType)(
|
||||
) CONST PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the DXGI color space of this context. Returns DXGI_COLOR_SPACE_CUSTOM
|
||||
/// when color context type is ICC.
|
||||
/// </summary>
|
||||
STDMETHOD_(DXGI_COLOR_SPACE_TYPE, GetDXGIColorSpace)(
|
||||
) CONST PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a set simple color profile.
|
||||
/// </summary>
|
||||
STDMETHOD(GetSimpleColorProfile)(
|
||||
_Out_ D2D1_SIMPLE_COLOR_PROFILE *simpleProfile
|
||||
) CONST PURE;
|
||||
}; // interface ID2D1ColorContext1
|
||||
|
||||
|
||||
interface DX_DECLARE_INTERFACE("7836d248-68cc-4df6-b9e8-de991bf62eb7") ID2D1DeviceContext5 : public ID2D1DeviceContext4
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates an SVG document from a stream.
|
||||
/// </summary>
|
||||
/// <param name="inputXmlStream">An input stream containing the SVG XML document. If
|
||||
/// null, an empty document is created.</param>
|
||||
/// <param name="viewportSize">Size of the initial viewport of the document.</param>
|
||||
/// <param name="svgDocument">When this method returns, contains a pointer to the
|
||||
/// SVG document.</param>
|
||||
STDMETHOD(CreateSvgDocument)(
|
||||
_In_opt_ IStream *inputXmlStream,
|
||||
D2D1_SIZE_F viewportSize,
|
||||
_COM_Outptr_ ID2D1SvgDocument **svgDocument
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Draw an SVG document.
|
||||
/// </summary>
|
||||
STDMETHOD_(void, DrawSvgDocument)(
|
||||
_In_ ID2D1SvgDocument *svgDocument
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a color context from a DXGI color space type. It is only valid to use
|
||||
/// this with the Color Management Effect in 'Best' mode.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateColorContextFromDxgiColorSpace)(
|
||||
DXGI_COLOR_SPACE_TYPE colorSpace,
|
||||
_COM_Outptr_ ID2D1ColorContext1 **colorContext
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a color context from a simple color profile. It is only valid to use
|
||||
/// this with the Color Management Effect in 'Best' mode.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateColorContextFromSimpleColorProfile)(
|
||||
_In_ CONST D2D1_SIMPLE_COLOR_PROFILE *simpleProfile,
|
||||
_COM_Outptr_ ID2D1ColorContext1 **colorContext
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a color context from a simple color profile.
|
||||
/// </summary>
|
||||
COM_DECLSPEC_NOTHROW
|
||||
HRESULT
|
||||
CreateColorContextFromSimpleColorProfile(
|
||||
CONST D2D1_SIMPLE_COLOR_PROFILE &simpleProfile,
|
||||
_COM_Outptr_ ID2D1ColorContext1 **colorContext
|
||||
)
|
||||
{
|
||||
return CreateColorContextFromSimpleColorProfile(&simpleProfile, colorContext);
|
||||
}
|
||||
}; // interface ID2D1DeviceContext5
|
||||
|
||||
|
||||
interface DX_DECLARE_INTERFACE("d55ba0a4-6405-4694-aef5-08ee1a4358b4") ID2D1Device5 : public ID2D1Device4
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new device context with no initially assigned target.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateDeviceContext)(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS options,
|
||||
_COM_Outptr_ ID2D1DeviceContext5 **deviceContext5
|
||||
) PURE;
|
||||
|
||||
using ID2D1Device4::CreateDeviceContext;
|
||||
|
||||
using ID2D1Device3::CreateDeviceContext;
|
||||
|
||||
using ID2D1Device2::CreateDeviceContext;
|
||||
|
||||
using ID2D1Device1::CreateDeviceContext;
|
||||
|
||||
using ID2D1Device::CreateDeviceContext;
|
||||
}; // interface ID2D1Device5
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates Direct2D resources. This interface also enables the creation of
|
||||
/// ID2D1Device5 objects.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("f9976f46-f642-44c1-97ca-da32ea2a2635") ID2D1Factory6 : public ID2D1Factory5
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This creates a new Direct2D device from the given IDXGIDevice.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateDevice)(
|
||||
_In_ IDXGIDevice *dxgiDevice,
|
||||
_COM_Outptr_ ID2D1Device5 **d2dDevice5
|
||||
) PURE;
|
||||
|
||||
using ID2D1Factory5::CreateDevice;
|
||||
|
||||
using ID2D1Factory4::CreateDevice;
|
||||
|
||||
using ID2D1Factory3::CreateDevice;
|
||||
|
||||
using ID2D1Factory2::CreateDevice;
|
||||
|
||||
using ID2D1Factory1::CreateDevice;
|
||||
}; // interface ID2D1Factory6
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C CONST IID IID_ID2D1InkStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1Ink;
|
||||
EXTERN_C CONST IID IID_ID2D1GradientMesh;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageSource;
|
||||
EXTERN_C CONST IID IID_ID2D1ImageSourceFromWic;
|
||||
EXTERN_C CONST IID IID_ID2D1TransformedImageSource;
|
||||
EXTERN_C CONST IID IID_ID2D1LookupTable3D;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext2;
|
||||
EXTERN_C CONST IID IID_ID2D1Device2;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory3;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink2;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafile1;
|
||||
EXTERN_C CONST IID IID_ID2D1GdiMetafileSink1;
|
||||
EXTERN_C CONST IID IID_ID2D1SpriteBatch;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext3;
|
||||
EXTERN_C CONST IID IID_ID2D1Device3;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory4;
|
||||
EXTERN_C CONST IID IID_ID2D1CommandSink3;
|
||||
EXTERN_C CONST IID IID_ID2D1SvgGlyphStyle;
|
||||
EXTERN_C CONST IID IID_ID2D1DeviceContext4;
|
||||
EXTERN_C CONST IID IID_ID2D1Device4;
|
||||
EXTERN_C CONST IID IID_ID2D1Factory5;
|
||||
|
||||
|
||||
#ifdef D2D_USE_C_DEFINITIONS
|
||||
|
||||
-22
@@ -225,28 +225,6 @@ namespace D2D1
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
COM_DECLSPEC_NOTHROW
|
||||
D2D1FORCEINLINE
|
||||
D2D1_SIMPLE_COLOR_PROFILE
|
||||
SimpleColorProfile(
|
||||
const D2D1_POINT_2F &redPrimary,
|
||||
const D2D1_POINT_2F &greenPrimary,
|
||||
const D2D1_POINT_2F &bluePrimary,
|
||||
const D2D1_GAMMA1 gamma,
|
||||
const D2D1_POINT_2F &whitePointXZ
|
||||
)
|
||||
{
|
||||
D2D1_SIMPLE_COLOR_PROFILE simpleColorProfile;
|
||||
|
||||
simpleColorProfile.redPrimary = redPrimary;
|
||||
simpleColorProfile.greenPrimary = greenPrimary;
|
||||
simpleColorProfile.bluePrimary = bluePrimary;
|
||||
simpleColorProfile.gamma = gamma;
|
||||
simpleColorProfile.whitePointXZ = whitePointXZ;
|
||||
|
||||
return simpleColorProfile;
|
||||
}
|
||||
} // namespace D2D1
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
|
||||
Vendored
-1832
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+2
-16
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -7307,8 +7307,7 @@ enum D3D11_FEATURE
|
||||
D3D11_FEATURE_D3D11_OPTIONS2 = ( D3D11_FEATURE_D3D9_OPTIONS1 + 1 ) ,
|
||||
D3D11_FEATURE_D3D11_OPTIONS3 = ( D3D11_FEATURE_D3D11_OPTIONS2 + 1 ) ,
|
||||
D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT = ( D3D11_FEATURE_D3D11_OPTIONS3 + 1 ) ,
|
||||
D3D11_FEATURE_D3D11_OPTIONS4 = ( D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT + 1 ) ,
|
||||
D3D11_FEATURE_SHADER_CACHE = ( D3D11_FEATURE_D3D11_OPTIONS4 + 1 )
|
||||
D3D11_FEATURE_D3D11_OPTIONS4 = ( D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT + 1 )
|
||||
} D3D11_FEATURE;
|
||||
|
||||
typedef struct D3D11_FEATURE_DATA_THREADING
|
||||
@@ -7465,19 +7464,6 @@ typedef struct D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT
|
||||
UINT MaxGPUVirtualAddressBitsPerProcess;
|
||||
} D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT;
|
||||
|
||||
typedef
|
||||
enum D3D11_SHADER_CACHE_SUPPORT_FLAGS
|
||||
{
|
||||
D3D11_SHADER_CACHE_SUPPORT_NONE = 0,
|
||||
D3D11_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x1,
|
||||
D3D11_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x2
|
||||
} D3D11_SHADER_CACHE_SUPPORT_FLAGS;
|
||||
|
||||
typedef struct D3D11_FEATURE_DATA_SHADER_CACHE
|
||||
{
|
||||
UINT SupportFlags;
|
||||
} D3D11_FEATURE_DATA_SHADER_CACHE;
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d11_0000_0029_v0_0_c_ifspec;
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+4
-2019
File diff suppressed because it is too large
Load Diff
Vendored
+4
-868
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -51,13 +51,6 @@ typedef interface ID3D11Device4 ID3D11Device4;
|
||||
#endif /* __ID3D11Device4_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D11Device5_FWD_DEFINED__
|
||||
#define __ID3D11Device5_FWD_DEFINED__
|
||||
typedef interface ID3D11Device5 ID3D11Device5;
|
||||
|
||||
#endif /* __ID3D11Device5_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D11Multithread_FWD_DEFINED__
|
||||
#define __ID3D11Multithread_FWD_DEFINED__
|
||||
typedef interface ID3D11Multithread ID3D11Multithread;
|
||||
@@ -922,862 +915,6 @@ EXTERN_C const IID IID_ID3D11Device4;
|
||||
#endif /* __ID3D11Device4_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D11Device5_INTERFACE_DEFINED__
|
||||
#define __ID3D11Device5_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3D11Device5 */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D11Device5;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("8ffde202-a0e7-45df-9e01-e837801b5ea0")
|
||||
ID3D11Device5 : public ID3D11Device4
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE OpenSharedFence(
|
||||
/* [annotation] */
|
||||
_In_ HANDLE hFence,
|
||||
/* [annotation] */
|
||||
_In_ REFIID ReturnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ void **ppFence) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateFence(
|
||||
/* [annotation] */
|
||||
_In_ UINT64 InitialValue,
|
||||
/* [annotation] */
|
||||
_In_ D3D11_FENCE_FLAG Flags,
|
||||
/* [annotation] */
|
||||
_In_ REFIID ReturnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ void **ppFence) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D11Device5Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D11Device5 * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateBuffer )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_BUFFER_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Buffer **ppBuffer);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateTexture1D )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_TEXTURE1D_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Texture1D **ppTexture1D);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateTexture2D )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_TEXTURE2D_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Texture2D **ppTexture2D);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateTexture3D )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_TEXTURE3D_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(_Inexpressible_(pDesc->MipLevels)) const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Texture3D **ppTexture3D);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateShaderResourceView )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11ShaderResourceView **ppSRView);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateUnorderedAccessView )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11UnorderedAccessView **ppUAView);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateRenderTargetView )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11RenderTargetView **ppRTView);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDepthStencilView )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_DEPTH_STENCIL_VIEW_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DepthStencilView **ppDepthStencilView);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateInputLayout )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(NumElements) const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
|
||||
/* [annotation] */
|
||||
_In_range_( 0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT ) UINT NumElements,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecodeWithInputSignature,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11InputLayout **ppInputLayout);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateVertexShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11VertexShader **ppVertexShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateGeometryShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11GeometryShader **ppGeometryShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateGeometryShaderWithStreamOutput )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(NumEntries) const D3D11_SO_DECLARATION_ENTRY *pSODeclaration,
|
||||
/* [annotation] */
|
||||
_In_range_( 0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT ) UINT NumEntries,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(NumStrides) const UINT *pBufferStrides,
|
||||
/* [annotation] */
|
||||
_In_range_( 0, D3D11_SO_BUFFER_SLOT_COUNT ) UINT NumStrides,
|
||||
/* [annotation] */
|
||||
_In_ UINT RasterizedStream,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11GeometryShader **ppGeometryShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreatePixelShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11PixelShader **ppPixelShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateHullShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11HullShader **ppHullShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDomainShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DomainShader **ppDomainShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateComputeShader )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_reads_(BytecodeLength) const void *pShaderBytecode,
|
||||
/* [annotation] */
|
||||
_In_ SIZE_T BytecodeLength,
|
||||
/* [annotation] */
|
||||
_In_opt_ ID3D11ClassLinkage *pClassLinkage,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11ComputeShader **ppComputeShader);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateClassLinkage )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_ ID3D11ClassLinkage **ppLinkage);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateBlendState )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_BLEND_DESC *pBlendStateDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11BlendState **ppBlendState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDepthStencilState )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_DEPTH_STENCIL_DESC *pDepthStencilDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DepthStencilState **ppDepthStencilState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateRasterizerState )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_RASTERIZER_DESC *pRasterizerDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11RasterizerState **ppRasterizerState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateSamplerState )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_SAMPLER_DESC *pSamplerDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11SamplerState **ppSamplerState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateQuery )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_QUERY_DESC *pQueryDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Query **ppQuery);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreatePredicate )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_QUERY_DESC *pPredicateDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Predicate **ppPredicate);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateCounter )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_COUNTER_DESC *pCounterDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Counter **ppCounter);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDeferredContext )(
|
||||
ID3D11Device5 * This,
|
||||
UINT ContextFlags,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DeviceContext **ppDeferredContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *OpenSharedResource )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ HANDLE hResource,
|
||||
/* [annotation] */
|
||||
_In_ REFIID ReturnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ void **ppResource);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckFormatSupport )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ DXGI_FORMAT Format,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pFormatSupport);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckMultisampleQualityLevels )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ DXGI_FORMAT Format,
|
||||
/* [annotation] */
|
||||
_In_ UINT SampleCount,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pNumQualityLevels);
|
||||
|
||||
void ( STDMETHODCALLTYPE *CheckCounterInfo )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Out_ D3D11_COUNTER_INFO *pCounterInfo);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckCounter )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_COUNTER_DESC *pDesc,
|
||||
/* [annotation] */
|
||||
_Out_ D3D11_COUNTER_TYPE *pType,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pActiveCounters,
|
||||
/* [annotation] */
|
||||
_Out_writes_opt_(*pNameLength) LPSTR szName,
|
||||
/* [annotation] */
|
||||
_Inout_opt_ UINT *pNameLength,
|
||||
/* [annotation] */
|
||||
_Out_writes_opt_(*pUnitsLength) LPSTR szUnits,
|
||||
/* [annotation] */
|
||||
_Inout_opt_ UINT *pUnitsLength,
|
||||
/* [annotation] */
|
||||
_Out_writes_opt_(*pDescriptionLength) LPSTR szDescription,
|
||||
/* [annotation] */
|
||||
_Inout_opt_ UINT *pDescriptionLength);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckFeatureSupport )(
|
||||
ID3D11Device5 * This,
|
||||
D3D11_FEATURE Feature,
|
||||
/* [annotation] */
|
||||
_Out_writes_bytes_(FeatureSupportDataSize) void *pFeatureSupportData,
|
||||
UINT FeatureSupportDataSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ REFGUID guid,
|
||||
/* [annotation] */
|
||||
_Inout_ UINT *pDataSize,
|
||||
/* [annotation] */
|
||||
_Out_writes_bytes_opt_(*pDataSize) void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ REFGUID guid,
|
||||
/* [annotation] */
|
||||
_In_ UINT DataSize,
|
||||
/* [annotation] */
|
||||
_In_reads_bytes_opt_(DataSize) const void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ REFGUID guid,
|
||||
/* [annotation] */
|
||||
_In_opt_ const IUnknown *pData);
|
||||
|
||||
D3D_FEATURE_LEVEL ( STDMETHODCALLTYPE *GetFeatureLevel )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
UINT ( STDMETHODCALLTYPE *GetCreationFlags )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDeviceRemovedReason )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
void ( STDMETHODCALLTYPE *GetImmediateContext )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Outptr_ ID3D11DeviceContext **ppImmediateContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetExceptionMode )(
|
||||
ID3D11Device5 * This,
|
||||
UINT RaiseFlags);
|
||||
|
||||
UINT ( STDMETHODCALLTYPE *GetExceptionMode )(
|
||||
ID3D11Device5 * This);
|
||||
|
||||
void ( STDMETHODCALLTYPE *GetImmediateContext1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Outptr_ ID3D11DeviceContext1 **ppImmediateContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDeferredContext1 )(
|
||||
ID3D11Device5 * This,
|
||||
UINT ContextFlags,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DeviceContext1 **ppDeferredContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateBlendState1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_BLEND_DESC1 *pBlendStateDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11BlendState1 **ppBlendState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateRasterizerState1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_RASTERIZER_DESC1 *pRasterizerDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11RasterizerState1 **ppRasterizerState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDeviceContextState )(
|
||||
ID3D11Device5 * This,
|
||||
UINT Flags,
|
||||
/* [annotation] */
|
||||
_In_reads_( FeatureLevels ) const D3D_FEATURE_LEVEL *pFeatureLevels,
|
||||
UINT FeatureLevels,
|
||||
UINT SDKVersion,
|
||||
REFIID EmulatedInterface,
|
||||
/* [annotation] */
|
||||
_Out_opt_ D3D_FEATURE_LEVEL *pChosenFeatureLevel,
|
||||
/* [annotation] */
|
||||
_Out_opt_ ID3DDeviceContextState **ppContextState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *OpenSharedResource1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ HANDLE hResource,
|
||||
/* [annotation] */
|
||||
_In_ REFIID returnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_ void **ppResource);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *OpenSharedResourceByName )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ LPCWSTR lpName,
|
||||
/* [annotation] */
|
||||
_In_ DWORD dwDesiredAccess,
|
||||
/* [annotation] */
|
||||
_In_ REFIID returnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_ void **ppResource);
|
||||
|
||||
void ( STDMETHODCALLTYPE *GetImmediateContext2 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Outptr_ ID3D11DeviceContext2 **ppImmediateContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDeferredContext2 )(
|
||||
ID3D11Device5 * This,
|
||||
UINT ContextFlags,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DeviceContext2 **ppDeferredContext);
|
||||
|
||||
void ( STDMETHODCALLTYPE *GetResourceTiling )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pTiledResource,
|
||||
/* [annotation] */
|
||||
_Out_opt_ UINT *pNumTilesForEntireResource,
|
||||
/* [annotation] */
|
||||
_Out_opt_ D3D11_PACKED_MIP_DESC *pPackedMipDesc,
|
||||
/* [annotation] */
|
||||
_Out_opt_ D3D11_TILE_SHAPE *pStandardTileShapeForNonPackedMips,
|
||||
/* [annotation] */
|
||||
_Inout_opt_ UINT *pNumSubresourceTilings,
|
||||
/* [annotation] */
|
||||
_In_ UINT FirstSubresourceTilingToGet,
|
||||
/* [annotation] */
|
||||
_Out_writes_(*pNumSubresourceTilings) D3D11_SUBRESOURCE_TILING *pSubresourceTilingsForNonPackedMips);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckMultisampleQualityLevels1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ DXGI_FORMAT Format,
|
||||
/* [annotation] */
|
||||
_In_ UINT SampleCount,
|
||||
/* [annotation] */
|
||||
_In_ UINT Flags,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pNumQualityLevels);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateTexture2D1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_TEXTURE2D_DESC1 *pDesc1,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(_Inexpressible_(pDesc1->MipLevels * pDesc1->ArraySize)) const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Texture2D1 **ppTexture2D);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateTexture3D1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_TEXTURE3D_DESC1 *pDesc1,
|
||||
/* [annotation] */
|
||||
_In_reads_opt_(_Inexpressible_(pDesc1->MipLevels)) const D3D11_SUBRESOURCE_DATA *pInitialData,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Texture3D1 **ppTexture3D);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateRasterizerState2 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_RASTERIZER_DESC2 *pRasterizerDesc,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11RasterizerState2 **ppRasterizerState);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateShaderResourceView1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC1 *pDesc1,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11ShaderResourceView1 **ppSRView1);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateUnorderedAccessView1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC1 *pDesc1,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11UnorderedAccessView1 **ppUAView1);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateRenderTargetView1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pResource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC1 *pDesc1,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11RenderTargetView1 **ppRTView1);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateQuery1 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ const D3D11_QUERY_DESC1 *pQueryDesc1,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11Query1 **ppQuery1);
|
||||
|
||||
void ( STDMETHODCALLTYPE *GetImmediateContext3 )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Outptr_ ID3D11DeviceContext3 **ppImmediateContext);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateDeferredContext3 )(
|
||||
ID3D11Device5 * This,
|
||||
UINT ContextFlags,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ ID3D11DeviceContext3 **ppDeferredContext);
|
||||
|
||||
void ( STDMETHODCALLTYPE *WriteToSubresource )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pDstResource,
|
||||
/* [annotation] */
|
||||
_In_ UINT DstSubresource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_BOX *pDstBox,
|
||||
/* [annotation] */
|
||||
_In_ const void *pSrcData,
|
||||
/* [annotation] */
|
||||
_In_ UINT SrcRowPitch,
|
||||
/* [annotation] */
|
||||
_In_ UINT SrcDepthPitch);
|
||||
|
||||
void ( STDMETHODCALLTYPE *ReadFromSubresource )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_Out_ void *pDstData,
|
||||
/* [annotation] */
|
||||
_In_ UINT DstRowPitch,
|
||||
/* [annotation] */
|
||||
_In_ UINT DstDepthPitch,
|
||||
/* [annotation] */
|
||||
_In_ ID3D11Resource *pSrcResource,
|
||||
/* [annotation] */
|
||||
_In_ UINT SrcSubresource,
|
||||
/* [annotation] */
|
||||
_In_opt_ const D3D11_BOX *pSrcBox);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *RegisterDeviceRemovedEvent )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ HANDLE hEvent,
|
||||
/* [annotation] */
|
||||
_Out_ DWORD *pdwCookie);
|
||||
|
||||
void ( STDMETHODCALLTYPE *UnregisterDeviceRemoved )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ DWORD dwCookie);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *OpenSharedFence )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ HANDLE hFence,
|
||||
/* [annotation] */
|
||||
_In_ REFIID ReturnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ void **ppFence);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CreateFence )(
|
||||
ID3D11Device5 * This,
|
||||
/* [annotation] */
|
||||
_In_ UINT64 InitialValue,
|
||||
/* [annotation] */
|
||||
_In_ D3D11_FENCE_FLAG Flags,
|
||||
/* [annotation] */
|
||||
_In_ REFIID ReturnedInterface,
|
||||
/* [annotation] */
|
||||
_COM_Outptr_opt_ void **ppFence);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D11Device5Vtbl;
|
||||
|
||||
interface ID3D11Device5
|
||||
{
|
||||
CONST_VTBL struct ID3D11Device5Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D11Device5_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D11Device5_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D11Device5_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D11Device5_CreateBuffer(This,pDesc,pInitialData,ppBuffer) \
|
||||
( (This)->lpVtbl -> CreateBuffer(This,pDesc,pInitialData,ppBuffer) )
|
||||
|
||||
#define ID3D11Device5_CreateTexture1D(This,pDesc,pInitialData,ppTexture1D) \
|
||||
( (This)->lpVtbl -> CreateTexture1D(This,pDesc,pInitialData,ppTexture1D) )
|
||||
|
||||
#define ID3D11Device5_CreateTexture2D(This,pDesc,pInitialData,ppTexture2D) \
|
||||
( (This)->lpVtbl -> CreateTexture2D(This,pDesc,pInitialData,ppTexture2D) )
|
||||
|
||||
#define ID3D11Device5_CreateTexture3D(This,pDesc,pInitialData,ppTexture3D) \
|
||||
( (This)->lpVtbl -> CreateTexture3D(This,pDesc,pInitialData,ppTexture3D) )
|
||||
|
||||
#define ID3D11Device5_CreateShaderResourceView(This,pResource,pDesc,ppSRView) \
|
||||
( (This)->lpVtbl -> CreateShaderResourceView(This,pResource,pDesc,ppSRView) )
|
||||
|
||||
#define ID3D11Device5_CreateUnorderedAccessView(This,pResource,pDesc,ppUAView) \
|
||||
( (This)->lpVtbl -> CreateUnorderedAccessView(This,pResource,pDesc,ppUAView) )
|
||||
|
||||
#define ID3D11Device5_CreateRenderTargetView(This,pResource,pDesc,ppRTView) \
|
||||
( (This)->lpVtbl -> CreateRenderTargetView(This,pResource,pDesc,ppRTView) )
|
||||
|
||||
#define ID3D11Device5_CreateDepthStencilView(This,pResource,pDesc,ppDepthStencilView) \
|
||||
( (This)->lpVtbl -> CreateDepthStencilView(This,pResource,pDesc,ppDepthStencilView) )
|
||||
|
||||
#define ID3D11Device5_CreateInputLayout(This,pInputElementDescs,NumElements,pShaderBytecodeWithInputSignature,BytecodeLength,ppInputLayout) \
|
||||
( (This)->lpVtbl -> CreateInputLayout(This,pInputElementDescs,NumElements,pShaderBytecodeWithInputSignature,BytecodeLength,ppInputLayout) )
|
||||
|
||||
#define ID3D11Device5_CreateVertexShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppVertexShader) \
|
||||
( (This)->lpVtbl -> CreateVertexShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppVertexShader) )
|
||||
|
||||
#define ID3D11Device5_CreateGeometryShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppGeometryShader) \
|
||||
( (This)->lpVtbl -> CreateGeometryShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppGeometryShader) )
|
||||
|
||||
#define ID3D11Device5_CreateGeometryShaderWithStreamOutput(This,pShaderBytecode,BytecodeLength,pSODeclaration,NumEntries,pBufferStrides,NumStrides,RasterizedStream,pClassLinkage,ppGeometryShader) \
|
||||
( (This)->lpVtbl -> CreateGeometryShaderWithStreamOutput(This,pShaderBytecode,BytecodeLength,pSODeclaration,NumEntries,pBufferStrides,NumStrides,RasterizedStream,pClassLinkage,ppGeometryShader) )
|
||||
|
||||
#define ID3D11Device5_CreatePixelShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppPixelShader) \
|
||||
( (This)->lpVtbl -> CreatePixelShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppPixelShader) )
|
||||
|
||||
#define ID3D11Device5_CreateHullShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppHullShader) \
|
||||
( (This)->lpVtbl -> CreateHullShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppHullShader) )
|
||||
|
||||
#define ID3D11Device5_CreateDomainShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppDomainShader) \
|
||||
( (This)->lpVtbl -> CreateDomainShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppDomainShader) )
|
||||
|
||||
#define ID3D11Device5_CreateComputeShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppComputeShader) \
|
||||
( (This)->lpVtbl -> CreateComputeShader(This,pShaderBytecode,BytecodeLength,pClassLinkage,ppComputeShader) )
|
||||
|
||||
#define ID3D11Device5_CreateClassLinkage(This,ppLinkage) \
|
||||
( (This)->lpVtbl -> CreateClassLinkage(This,ppLinkage) )
|
||||
|
||||
#define ID3D11Device5_CreateBlendState(This,pBlendStateDesc,ppBlendState) \
|
||||
( (This)->lpVtbl -> CreateBlendState(This,pBlendStateDesc,ppBlendState) )
|
||||
|
||||
#define ID3D11Device5_CreateDepthStencilState(This,pDepthStencilDesc,ppDepthStencilState) \
|
||||
( (This)->lpVtbl -> CreateDepthStencilState(This,pDepthStencilDesc,ppDepthStencilState) )
|
||||
|
||||
#define ID3D11Device5_CreateRasterizerState(This,pRasterizerDesc,ppRasterizerState) \
|
||||
( (This)->lpVtbl -> CreateRasterizerState(This,pRasterizerDesc,ppRasterizerState) )
|
||||
|
||||
#define ID3D11Device5_CreateSamplerState(This,pSamplerDesc,ppSamplerState) \
|
||||
( (This)->lpVtbl -> CreateSamplerState(This,pSamplerDesc,ppSamplerState) )
|
||||
|
||||
#define ID3D11Device5_CreateQuery(This,pQueryDesc,ppQuery) \
|
||||
( (This)->lpVtbl -> CreateQuery(This,pQueryDesc,ppQuery) )
|
||||
|
||||
#define ID3D11Device5_CreatePredicate(This,pPredicateDesc,ppPredicate) \
|
||||
( (This)->lpVtbl -> CreatePredicate(This,pPredicateDesc,ppPredicate) )
|
||||
|
||||
#define ID3D11Device5_CreateCounter(This,pCounterDesc,ppCounter) \
|
||||
( (This)->lpVtbl -> CreateCounter(This,pCounterDesc,ppCounter) )
|
||||
|
||||
#define ID3D11Device5_CreateDeferredContext(This,ContextFlags,ppDeferredContext) \
|
||||
( (This)->lpVtbl -> CreateDeferredContext(This,ContextFlags,ppDeferredContext) )
|
||||
|
||||
#define ID3D11Device5_OpenSharedResource(This,hResource,ReturnedInterface,ppResource) \
|
||||
( (This)->lpVtbl -> OpenSharedResource(This,hResource,ReturnedInterface,ppResource) )
|
||||
|
||||
#define ID3D11Device5_CheckFormatSupport(This,Format,pFormatSupport) \
|
||||
( (This)->lpVtbl -> CheckFormatSupport(This,Format,pFormatSupport) )
|
||||
|
||||
#define ID3D11Device5_CheckMultisampleQualityLevels(This,Format,SampleCount,pNumQualityLevels) \
|
||||
( (This)->lpVtbl -> CheckMultisampleQualityLevels(This,Format,SampleCount,pNumQualityLevels) )
|
||||
|
||||
#define ID3D11Device5_CheckCounterInfo(This,pCounterInfo) \
|
||||
( (This)->lpVtbl -> CheckCounterInfo(This,pCounterInfo) )
|
||||
|
||||
#define ID3D11Device5_CheckCounter(This,pDesc,pType,pActiveCounters,szName,pNameLength,szUnits,pUnitsLength,szDescription,pDescriptionLength) \
|
||||
( (This)->lpVtbl -> CheckCounter(This,pDesc,pType,pActiveCounters,szName,pNameLength,szUnits,pUnitsLength,szDescription,pDescriptionLength) )
|
||||
|
||||
#define ID3D11Device5_CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) \
|
||||
( (This)->lpVtbl -> CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) )
|
||||
|
||||
#define ID3D11Device5_GetPrivateData(This,guid,pDataSize,pData) \
|
||||
( (This)->lpVtbl -> GetPrivateData(This,guid,pDataSize,pData) )
|
||||
|
||||
#define ID3D11Device5_SetPrivateData(This,guid,DataSize,pData) \
|
||||
( (This)->lpVtbl -> SetPrivateData(This,guid,DataSize,pData) )
|
||||
|
||||
#define ID3D11Device5_SetPrivateDataInterface(This,guid,pData) \
|
||||
( (This)->lpVtbl -> SetPrivateDataInterface(This,guid,pData) )
|
||||
|
||||
#define ID3D11Device5_GetFeatureLevel(This) \
|
||||
( (This)->lpVtbl -> GetFeatureLevel(This) )
|
||||
|
||||
#define ID3D11Device5_GetCreationFlags(This) \
|
||||
( (This)->lpVtbl -> GetCreationFlags(This) )
|
||||
|
||||
#define ID3D11Device5_GetDeviceRemovedReason(This) \
|
||||
( (This)->lpVtbl -> GetDeviceRemovedReason(This) )
|
||||
|
||||
#define ID3D11Device5_GetImmediateContext(This,ppImmediateContext) \
|
||||
( (This)->lpVtbl -> GetImmediateContext(This,ppImmediateContext) )
|
||||
|
||||
#define ID3D11Device5_SetExceptionMode(This,RaiseFlags) \
|
||||
( (This)->lpVtbl -> SetExceptionMode(This,RaiseFlags) )
|
||||
|
||||
#define ID3D11Device5_GetExceptionMode(This) \
|
||||
( (This)->lpVtbl -> GetExceptionMode(This) )
|
||||
|
||||
|
||||
#define ID3D11Device5_GetImmediateContext1(This,ppImmediateContext) \
|
||||
( (This)->lpVtbl -> GetImmediateContext1(This,ppImmediateContext) )
|
||||
|
||||
#define ID3D11Device5_CreateDeferredContext1(This,ContextFlags,ppDeferredContext) \
|
||||
( (This)->lpVtbl -> CreateDeferredContext1(This,ContextFlags,ppDeferredContext) )
|
||||
|
||||
#define ID3D11Device5_CreateBlendState1(This,pBlendStateDesc,ppBlendState) \
|
||||
( (This)->lpVtbl -> CreateBlendState1(This,pBlendStateDesc,ppBlendState) )
|
||||
|
||||
#define ID3D11Device5_CreateRasterizerState1(This,pRasterizerDesc,ppRasterizerState) \
|
||||
( (This)->lpVtbl -> CreateRasterizerState1(This,pRasterizerDesc,ppRasterizerState) )
|
||||
|
||||
#define ID3D11Device5_CreateDeviceContextState(This,Flags,pFeatureLevels,FeatureLevels,SDKVersion,EmulatedInterface,pChosenFeatureLevel,ppContextState) \
|
||||
( (This)->lpVtbl -> CreateDeviceContextState(This,Flags,pFeatureLevels,FeatureLevels,SDKVersion,EmulatedInterface,pChosenFeatureLevel,ppContextState) )
|
||||
|
||||
#define ID3D11Device5_OpenSharedResource1(This,hResource,returnedInterface,ppResource) \
|
||||
( (This)->lpVtbl -> OpenSharedResource1(This,hResource,returnedInterface,ppResource) )
|
||||
|
||||
#define ID3D11Device5_OpenSharedResourceByName(This,lpName,dwDesiredAccess,returnedInterface,ppResource) \
|
||||
( (This)->lpVtbl -> OpenSharedResourceByName(This,lpName,dwDesiredAccess,returnedInterface,ppResource) )
|
||||
|
||||
|
||||
#define ID3D11Device5_GetImmediateContext2(This,ppImmediateContext) \
|
||||
( (This)->lpVtbl -> GetImmediateContext2(This,ppImmediateContext) )
|
||||
|
||||
#define ID3D11Device5_CreateDeferredContext2(This,ContextFlags,ppDeferredContext) \
|
||||
( (This)->lpVtbl -> CreateDeferredContext2(This,ContextFlags,ppDeferredContext) )
|
||||
|
||||
#define ID3D11Device5_GetResourceTiling(This,pTiledResource,pNumTilesForEntireResource,pPackedMipDesc,pStandardTileShapeForNonPackedMips,pNumSubresourceTilings,FirstSubresourceTilingToGet,pSubresourceTilingsForNonPackedMips) \
|
||||
( (This)->lpVtbl -> GetResourceTiling(This,pTiledResource,pNumTilesForEntireResource,pPackedMipDesc,pStandardTileShapeForNonPackedMips,pNumSubresourceTilings,FirstSubresourceTilingToGet,pSubresourceTilingsForNonPackedMips) )
|
||||
|
||||
#define ID3D11Device5_CheckMultisampleQualityLevels1(This,Format,SampleCount,Flags,pNumQualityLevels) \
|
||||
( (This)->lpVtbl -> CheckMultisampleQualityLevels1(This,Format,SampleCount,Flags,pNumQualityLevels) )
|
||||
|
||||
|
||||
#define ID3D11Device5_CreateTexture2D1(This,pDesc1,pInitialData,ppTexture2D) \
|
||||
( (This)->lpVtbl -> CreateTexture2D1(This,pDesc1,pInitialData,ppTexture2D) )
|
||||
|
||||
#define ID3D11Device5_CreateTexture3D1(This,pDesc1,pInitialData,ppTexture3D) \
|
||||
( (This)->lpVtbl -> CreateTexture3D1(This,pDesc1,pInitialData,ppTexture3D) )
|
||||
|
||||
#define ID3D11Device5_CreateRasterizerState2(This,pRasterizerDesc,ppRasterizerState) \
|
||||
( (This)->lpVtbl -> CreateRasterizerState2(This,pRasterizerDesc,ppRasterizerState) )
|
||||
|
||||
#define ID3D11Device5_CreateShaderResourceView1(This,pResource,pDesc1,ppSRView1) \
|
||||
( (This)->lpVtbl -> CreateShaderResourceView1(This,pResource,pDesc1,ppSRView1) )
|
||||
|
||||
#define ID3D11Device5_CreateUnorderedAccessView1(This,pResource,pDesc1,ppUAView1) \
|
||||
( (This)->lpVtbl -> CreateUnorderedAccessView1(This,pResource,pDesc1,ppUAView1) )
|
||||
|
||||
#define ID3D11Device5_CreateRenderTargetView1(This,pResource,pDesc1,ppRTView1) \
|
||||
( (This)->lpVtbl -> CreateRenderTargetView1(This,pResource,pDesc1,ppRTView1) )
|
||||
|
||||
#define ID3D11Device5_CreateQuery1(This,pQueryDesc1,ppQuery1) \
|
||||
( (This)->lpVtbl -> CreateQuery1(This,pQueryDesc1,ppQuery1) )
|
||||
|
||||
#define ID3D11Device5_GetImmediateContext3(This,ppImmediateContext) \
|
||||
( (This)->lpVtbl -> GetImmediateContext3(This,ppImmediateContext) )
|
||||
|
||||
#define ID3D11Device5_CreateDeferredContext3(This,ContextFlags,ppDeferredContext) \
|
||||
( (This)->lpVtbl -> CreateDeferredContext3(This,ContextFlags,ppDeferredContext) )
|
||||
|
||||
#define ID3D11Device5_WriteToSubresource(This,pDstResource,DstSubresource,pDstBox,pSrcData,SrcRowPitch,SrcDepthPitch) \
|
||||
( (This)->lpVtbl -> WriteToSubresource(This,pDstResource,DstSubresource,pDstBox,pSrcData,SrcRowPitch,SrcDepthPitch) )
|
||||
|
||||
#define ID3D11Device5_ReadFromSubresource(This,pDstData,DstRowPitch,DstDepthPitch,pSrcResource,SrcSubresource,pSrcBox) \
|
||||
( (This)->lpVtbl -> ReadFromSubresource(This,pDstData,DstRowPitch,DstDepthPitch,pSrcResource,SrcSubresource,pSrcBox) )
|
||||
|
||||
|
||||
#define ID3D11Device5_RegisterDeviceRemovedEvent(This,hEvent,pdwCookie) \
|
||||
( (This)->lpVtbl -> RegisterDeviceRemovedEvent(This,hEvent,pdwCookie) )
|
||||
|
||||
#define ID3D11Device5_UnregisterDeviceRemoved(This,dwCookie) \
|
||||
( (This)->lpVtbl -> UnregisterDeviceRemoved(This,dwCookie) )
|
||||
|
||||
|
||||
#define ID3D11Device5_OpenSharedFence(This,hFence,ReturnedInterface,ppFence) \
|
||||
( (This)->lpVtbl -> OpenSharedFence(This,hFence,ReturnedInterface,ppFence) )
|
||||
|
||||
#define ID3D11Device5_CreateFence(This,InitialValue,Flags,ReturnedInterface,ppFence) \
|
||||
( (This)->lpVtbl -> CreateFence(This,InitialValue,Flags,ReturnedInterface,ppFence) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D11Device5_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D11Multithread_INTERFACE_DEFINED__
|
||||
#define __ID3D11Multithread_INTERFACE_DEFINED__
|
||||
|
||||
@@ -3065,7 +2202,7 @@ EXTERN_C const IID IID_ID3D11VideoContext2;
|
||||
#endif /* __ID3D11VideoContext2_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d11_4_0000_0004 */
|
||||
/* interface __MIDL_itf_d3d11_4_0000_0003 */
|
||||
/* [local] */
|
||||
|
||||
typedef struct D3D11_FEATURE_DATA_D3D11_OPTIONS4
|
||||
@@ -3076,13 +2213,12 @@ typedef struct D3D11_FEATURE_DATA_D3D11_OPTIONS4
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
DEFINE_GUID(IID_ID3D11Device4,0x8992ab71,0x02e6,0x4b8d,0xba,0x48,0xb0,0x56,0xdc,0xda,0x42,0xc4);
|
||||
DEFINE_GUID(IID_ID3D11Device5,0x8ffde202,0xa0e7,0x45df,0x9e,0x01,0xe8,0x37,0x80,0x1b,0x5e,0xa0);
|
||||
DEFINE_GUID(IID_ID3D11Multithread,0x9B7E4E00,0x342C,0x4106,0xA1,0x9F,0x4F,0x27,0x04,0xF6,0x89,0xF0);
|
||||
DEFINE_GUID(IID_ID3D11VideoContext2,0xC4E7374C,0x6243,0x4D1B,0xAE,0x87,0x52,0xB4,0xF7,0x40,0xE2,0x61);
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d11_4_0000_0004_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d11_4_0000_0004_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d11_4_0000_0003_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d11_4_0000_0003_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+12
-1667
File diff suppressed because it is too large
Load Diff
+35
-210
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
|
||||
|
||||
|
||||
@@ -57,13 +57,6 @@ typedef interface ID3D12Debug1 ID3D12Debug1;
|
||||
#endif /* __ID3D12Debug1_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12Debug2_FWD_DEFINED__
|
||||
#define __ID3D12Debug2_FWD_DEFINED__
|
||||
typedef interface ID3D12Debug2 ID3D12Debug2;
|
||||
|
||||
#endif /* __ID3D12Debug2_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugDevice1_FWD_DEFINED__
|
||||
#define __ID3D12DebugDevice1_FWD_DEFINED__
|
||||
typedef interface ID3D12DebugDevice1 ID3D12DebugDevice1;
|
||||
@@ -304,101 +297,6 @@ EXTERN_C const IID IID_ID3D12Debug1;
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0002 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
enum D3D12_GPU_BASED_VALIDATION_FLAGS
|
||||
{
|
||||
D3D12_GPU_BASED_VALIDATION_FLAGS_NONE = 0,
|
||||
D3D12_GPU_BASED_VALIDATION_FLAGS_DISABLE_STATE_TRACKING = 0x1
|
||||
} D3D12_GPU_BASED_VALIDATION_FLAGS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(D3D12_GPU_BASED_VALIDATION_FLAGS)
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12Debug2_INTERFACE_DEFINED__
|
||||
#define __ID3D12Debug2_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3D12Debug2 */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12Debug2;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("93a665c4-a3b2-4e5d-b692-a26ae14e3374")
|
||||
ID3D12Debug2 : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual void STDMETHODCALLTYPE SetGPUBasedValidationFlags(
|
||||
D3D12_GPU_BASED_VALIDATION_FLAGS Flags) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12Debug2Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12Debug2 * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12Debug2 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12Debug2 * This);
|
||||
|
||||
void ( STDMETHODCALLTYPE *SetGPUBasedValidationFlags )(
|
||||
ID3D12Debug2 * This,
|
||||
D3D12_GPU_BASED_VALIDATION_FLAGS Flags);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12Debug2Vtbl;
|
||||
|
||||
interface ID3D12Debug2
|
||||
{
|
||||
CONST_VTBL struct ID3D12Debug2Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12Debug2_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12Debug2_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12Debug2_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12Debug2_SetGPUBasedValidationFlags(This,Flags) \
|
||||
( (This)->lpVtbl -> SetGPUBasedValidationFlags(This,Flags) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12Debug2_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0003 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
enum D3D12_RLDO_FLAGS
|
||||
{
|
||||
@@ -413,8 +311,7 @@ typedef
|
||||
enum D3D12_DEBUG_DEVICE_PARAMETER_TYPE
|
||||
{
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_FEATURE_FLAGS = 0,
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_GPU_BASED_VALIDATION_SETTINGS = ( D3D12_DEBUG_DEVICE_PARAMETER_FEATURE_FLAGS + 1 ) ,
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_GPU_SLOWDOWN_PERFORMANCE_FACTOR = ( D3D12_DEBUG_DEVICE_PARAMETER_GPU_BASED_VALIDATION_SETTINGS + 1 )
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_GPU_BASED_VALIDATION_SETTINGS = ( D3D12_DEBUG_DEVICE_PARAMETER_FEATURE_FLAGS + 1 )
|
||||
} D3D12_DEBUG_DEVICE_PARAMETER_TYPE;
|
||||
|
||||
typedef
|
||||
@@ -456,15 +353,10 @@ typedef struct D3D12_DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS PipelineStateCreateFlags;
|
||||
} D3D12_DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS;
|
||||
|
||||
typedef struct D3D12_DEBUG_DEVICE_GPU_SLOWDOWN_PERFORMANCE_FACTOR
|
||||
{
|
||||
FLOAT SlowdownFactor;
|
||||
} D3D12_DEBUG_DEVICE_GPU_SLOWDOWN_PERFORMANCE_FACTOR;
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0003_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0003_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12DebugDevice1_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugDevice1_INTERFACE_DEFINED__
|
||||
@@ -670,14 +562,14 @@ EXTERN_C const IID IID_ID3D12DebugDevice;
|
||||
#endif /* __ID3D12DebugDevice_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0005 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0004 */
|
||||
/* [local] */
|
||||
|
||||
DEFINE_GUID(DXGI_DEBUG_D3D12, 0xcf59a98c, 0xa950, 0x4326, 0x91, 0xef, 0x9b, 0xba, 0xa1, 0x7b, 0xfd, 0x95);
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0004_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0004_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12DebugCommandQueue_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugCommandQueue_INTERFACE_DEFINED__
|
||||
@@ -762,7 +654,7 @@ EXTERN_C const IID IID_ID3D12DebugCommandQueue;
|
||||
#endif /* __ID3D12DebugCommandQueue_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0006 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0005 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
@@ -778,8 +670,8 @@ typedef struct D3D12_DEBUG_COMMAND_LIST_GPU_BASED_VALIDATION_SETTINGS
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0006_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0006_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12DebugCommandList1_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugCommandList1_INTERFACE_DEFINED__
|
||||
@@ -993,7 +885,7 @@ EXTERN_C const IID IID_ID3D12DebugCommandList;
|
||||
#endif /* __ID3D12DebugCommandList_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0008 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0007 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
@@ -1429,10 +1321,10 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_CREATERASTERIZERSTATE_INVALIDFORCEDSAMPLECOUNT = ( D3D12_MESSAGE_ID_ENQUEUESETEVENT_ACCESSDENIED_RETURN + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_DRAW_INVALID_USE_OF_FORCED_SAMPLE_COUNT = ( D3D12_MESSAGE_ID_CREATERASTERIZERSTATE_INVALIDFORCEDSAMPLECOUNT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEBLENDSTATE_INVALIDLOGICOPS = ( D3D12_MESSAGE_ID_DEVICE_DRAW_INVALID_USE_OF_FORCED_SAMPLE_COUNT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATEBLENDSTATE_INVALIDLOGICOPS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEUNORDEREDACCESSVIEW_INVALIDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERENDERTARGETVIEW_INVALIDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATEUNORDEREDACCESSVIEW_INVALIDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_LOCKEDOUT_INTERFACE = ( D3D12_MESSAGE_ID_CREATERENDERTARGETVIEW_INVALIDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATEBLENDSTATE_INVALIDLOGICOPS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEUNORDEREDACCESSVIEW_INVALIDDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERENDERTARGETVIEW_INVALIDDARRAYWITHDECODER = ( D3D12_MESSAGE_ID_CREATEUNORDEREDACCESSVIEW_INVALIDDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_LOCKEDOUT_INTERFACE = ( D3D12_MESSAGE_ID_CREATERENDERTARGETVIEW_INVALIDDARRAYWITHDECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_OFFERRESOURCES_INVALIDPRIORITY = ( D3D12_MESSAGE_ID_DEVICE_LOCKEDOUT_INTERFACE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_CLEARVIEW_INVALIDVIEW = ( D3D12_MESSAGE_ID_OFFERRESOURCES_INVALIDPRIORITY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_CREATEVERTEXSHADER_DOUBLEEXTENSIONSNOTSUPPORTED = ( D3D12_MESSAGE_ID_DEVICE_CLEARVIEW_INVALIDVIEW + 1 ) ,
|
||||
@@ -1771,7 +1663,10 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_CREATECOMMANDSIGNATURE_INVALID = ( D3D12_MESSAGE_ID_CREATE_SAMPLER_INVALID + 1 ) ,
|
||||
D3D12_MESSAGE_ID_EXECUTE_INDIRECT_INVALID_PARAMETERS = ( D3D12_MESSAGE_ID_CREATECOMMANDSIGNATURE_INVALID + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GETGPUVIRTUALADDRESS_INVALID_RESOURCE_DIMENSION = ( D3D12_MESSAGE_ID_EXECUTE_INDIRECT_INVALID_PARAMETERS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDPLANEINDEX = ( D3D12_MESSAGE_ID_GETGPUVIRTUALADDRESS_INVALID_RESOURCE_DIMENSION + 4 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_INVALIDCONTEXTTYPE = ( D3D12_MESSAGE_ID_GETGPUVIRTUALADDRESS_INVALID_RESOURCE_DIMENSION + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_DECODENOTSUPPORTED = ( D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_INVALIDCONTEXTTYPE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_ENCODENOTSUPPORTED = ( D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_DECODENOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDPLANEINDEX = ( D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_ENCODENOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDVIDEOPLANEINDEX = ( D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDPLANEINDEX + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_AMBIGUOUSVIDEOPLANEINDEX = ( D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_INVALIDVIDEOPLANEINDEX + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERENDERTARGETVIEW_INVALIDPLANEINDEX = ( D3D12_MESSAGE_ID_CREATESHADERRESOURCEVIEW_AMBIGUOUSVIDEOPLANEINDEX + 1 ) ,
|
||||
@@ -1816,8 +1711,8 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDSRCBUFFERMISCFLAGS = ( D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDSRCBUFFERUSAGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDDSTTEXTUREUSAGE = ( D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDSRCBUFFERMISCFLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGDECODE_BACKBUFFERNOTSUPPORTED = ( D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDDSTTEXTUREUSAGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDCOPYFLAGS = ( D3D12_MESSAGE_ID_JPEGDECODE_BACKBUFFERNOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_NOTSUPPORTED = ( D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPORTEDCOPYFLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPRTEDCOPYFLAGS = ( D3D12_MESSAGE_ID_JPEGDECODE_BACKBUFFERNOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_NOTSUPPORTED = ( D3D12_MESSAGE_ID_JPEGDECODE_UNSUPPRTEDCOPYFLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_INVALIDSCANDATAOFFSET = ( D3D12_MESSAGE_ID_JPEGENCODE_NOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_INVALIDCOMPONENTS = ( D3D12_MESSAGE_ID_JPEGENCODE_INVALIDSCANDATAOFFSET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_SOURCENOT2D = ( D3D12_MESSAGE_ID_JPEGENCODE_INVALIDCOMPONENTS + 1 ) ,
|
||||
@@ -1835,8 +1730,8 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_UNSUPPORTEDDSTBUFFERMISCFLAGS = ( D3D12_MESSAGE_ID_JPEGENCODE_UNSUPPORTEDDSTBUFFERUSAGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_UNSUPPORTEDSRCTEXTUREUSAGE = ( D3D12_MESSAGE_ID_JPEGENCODE_UNSUPPORTEDDSTBUFFERMISCFLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_JPEGENCODE_BACKBUFFERNOTSUPPORTED = ( D3D12_MESSAGE_ID_JPEGENCODE_UNSUPPORTEDSRCTEXTUREUSAGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_UNSUPPORTEDCONTEXTTYPEFORQUERY = ( D3D12_MESSAGE_ID_JPEGENCODE_BACKBUFFERNOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_FLUSH1_INVALIDCONTEXTTYPE = ( D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_UNSUPPORTEDCONTEXTTYPEFORQUERY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_UNSUPPORTEDCONTEXTTTYPEFORQUERY = ( D3D12_MESSAGE_ID_JPEGENCODE_BACKBUFFERNOTSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_FLUSH1_INVALIDCONTEXTTYPE = ( D3D12_MESSAGE_ID_CREATEQUERYORPREDICATE_UNSUPPORTEDCONTEXTTTYPEFORQUERY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDCLEARVALUE = ( D3D12_MESSAGE_ID_FLUSH1_INVALIDCONTEXTTYPE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERESOURCE_UNRECOGNIZEDCLEARVALUEFORMAT = ( D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDCLEARVALUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATERESOURCE_INVALIDCLEARVALUEFORMAT = ( D3D12_MESSAGE_ID_CREATERESOURCE_UNRECOGNIZEDCLEARVALUEFORMAT + 1 ) ,
|
||||
@@ -2001,14 +1896,14 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_CREATE_QUEUE_VIDEO_NOT_SUPPORTED = ( D3D12_MESSAGE_ID_SETEVENTONMULTIPLEFENCECOMPLETION_INVALIDFLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_COMMAND_ALLOCATOR_VIDEO_NOT_SUPPORTED = ( D3D12_MESSAGE_ID_CREATE_QUEUE_VIDEO_NOT_SUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEQUERY_HEAP_VIDEO_DECODE_STATISTICS_NOT_SUPPORTED = ( D3D12_MESSAGE_ID_CREATE_COMMAND_ALLOCATOR_VIDEO_NOT_SUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEODECODECOMMANDLIST = ( D3D12_MESSAGE_ID_CREATEQUERY_HEAP_VIDEO_DECODE_STATISTICS_NOT_SUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEODECODER = ( D3D12_MESSAGE_ID_CREATE_VIDEODECODECOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEOCOMMANDLIST = ( D3D12_MESSAGE_ID_CREATEQUERY_HEAP_VIDEO_DECODE_STATISTICS_NOT_SUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEODECODER = ( D3D12_MESSAGE_ID_CREATE_VIDEOCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEODECODESTREAM = ( D3D12_MESSAGE_ID_CREATE_VIDEODECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEODECODECOMMANDLIST = ( D3D12_MESSAGE_ID_CREATE_VIDEODECODESTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEODECODER = ( D3D12_MESSAGE_ID_LIVE_VIDEODECODECOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEOCOMMANDLIST = ( D3D12_MESSAGE_ID_CREATE_VIDEODECODESTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEODECODER = ( D3D12_MESSAGE_ID_LIVE_VIDEOCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEODECODESTREAM = ( D3D12_MESSAGE_ID_LIVE_VIDEODECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEODECODECOMMANDLIST = ( D3D12_MESSAGE_ID_LIVE_VIDEODECODESTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEODECODER = ( D3D12_MESSAGE_ID_DESTROY_VIDEODECODECOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEOCOMMANDLIST = ( D3D12_MESSAGE_ID_LIVE_VIDEODECODESTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEODECODER = ( D3D12_MESSAGE_ID_DESTROY_VIDEOCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEODECODESTREAM = ( D3D12_MESSAGE_ID_DESTROY_VIDEODECODER + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DECODE_FRAME_INVALID_PARAMETERS = ( D3D12_MESSAGE_ID_DESTROY_VIDEODECODESTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEPRECATED_API = ( D3D12_MESSAGE_ID_DECODE_FRAME_INVALID_PARAMETERS + 1 ) ,
|
||||
@@ -2023,78 +1918,9 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_COPY_ON_SAME_SUBRESOURCE = ( D3D12_MESSAGE_ID_DISCARD_NO_RECTS_FOR_NON_TEXTURE2D + 1 ) ,
|
||||
D3D12_MESSAGE_ID_SETRESIDENCYPRIORITY_INVALID_PAGEABLE = ( D3D12_MESSAGE_ID_COPY_ON_SAME_SUBRESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UNSUPPORTED = ( D3D12_MESSAGE_ID_SETRESIDENCYPRIORITY_INVALID_PAGEABLE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_STATIC_DESCRIPTOR_INVALID_DESCRIPTOR_CHANGE = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UNSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DATA_STATIC_DESCRIPTOR_INVALID_DATA_CHANGE = ( D3D12_MESSAGE_ID_STATIC_DESCRIPTOR_INVALID_DESCRIPTOR_CHANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DATA_STATIC_WHILE_SET_AT_EXECUTE_DESCRIPTOR_INVALID_DATA_CHANGE = ( D3D12_MESSAGE_ID_DATA_STATIC_DESCRIPTOR_INVALID_DATA_CHANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_EXECUTE_BUNDLE_STATIC_DESCRIPTOR_DATA_STATIC_NOT_SET = ( D3D12_MESSAGE_ID_DATA_STATIC_WHILE_SET_AT_EXECUTE_DESCRIPTOR_INVALID_DATA_CHANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_RESOURCE_ACCESS_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_EXECUTE_BUNDLE_STATIC_DESCRIPTOR_DATA_STATIC_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_SAMPLER_MODE_MISMATCH = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_RESOURCE_ACCESS_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_FENCE_INVALID_FLAGS = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_SAMPLER_MODE_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOURCE_BARRIER_DUPLICATE_SUBRESOURCE_TRANSITIONS = ( D3D12_MESSAGE_ID_CREATE_FENCE_INVALID_FLAGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_SETRESIDENCYPRIORITY_INVALID_PRIORITY = ( D3D12_MESSAGE_ID_RESOURCE_BARRIER_DUPLICATE_SUBRESOURCE_TRANSITIONS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_PASS = ( D3D12_MESSAGE_ID_SETRESIDENCYPRIORITY_INVALID_PRIORITY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_PASS = ( D3D12_MESSAGE_ID_CREATE_PASS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_PASS = ( D3D12_MESSAGE_ID_DESTROY_PASS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_DESCRIPTOR_HEAP_LARGE_NUM_DESCRIPTORS = ( D3D12_MESSAGE_ID_LIVE_PASS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_BEGIN_EVENT = ( D3D12_MESSAGE_ID_CREATE_DESCRIPTOR_HEAP_LARGE_NUM_DESCRIPTORS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_END_EVENT = ( D3D12_MESSAGE_ID_BEGIN_EVENT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEDEVICE_DEBUG_LAYER_STARTUP_OPTIONS = ( D3D12_MESSAGE_ID_END_EVENT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEDEPTHSTENCILSTATE_DEPTHBOUNDSTEST_UNSUPPORTED = ( D3D12_MESSAGE_ID_CREATEDEVICE_DEBUG_LAYER_STARTUP_OPTIONS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINESTATE_DUPLICATE_SUBOBJECT = ( D3D12_MESSAGE_ID_CREATEDEPTHSTENCILSTATE_DEPTHBOUNDSTEST_UNSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINESTATE_UNKNOWN_SUBOBJECT = ( D3D12_MESSAGE_ID_CREATEPIPELINESTATE_DUPLICATE_SUBOBJECT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINESTATE_ZERO_SIZE_STREAM = ( D3D12_MESSAGE_ID_CREATEPIPELINESTATE_UNKNOWN_SUBOBJECT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINESTATE_INVALID_STREAM = ( D3D12_MESSAGE_ID_CREATEPIPELINESTATE_ZERO_SIZE_STREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINESTATE_CANNOT_DEDUCE_TYPE = ( D3D12_MESSAGE_ID_CREATEPIPELINESTATE_INVALID_STREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_STATIC_DESCRIPTOR_RESOURCE_DIMENSION_MISMATCH = ( D3D12_MESSAGE_ID_CREATEPIPELINESTATE_CANNOT_DEDUCE_TYPE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_COMMAND_QUEUE_INSUFFICIENT_PRIVILEGE_FOR_GLOBAL_REALTIME = ( D3D12_MESSAGE_ID_COMMAND_LIST_STATIC_DESCRIPTOR_RESOURCE_DIMENSION_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_COMMAND_QUEUE_INSUFFICIENT_HARDWARE_SUPPORT_FOR_GLOBAL_REALTIME = ( D3D12_MESSAGE_ID_CREATE_COMMAND_QUEUE_INSUFFICIENT_PRIVILEGE_FOR_GLOBAL_REALTIME + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_ARCHITECTURE = ( D3D12_MESSAGE_ID_CREATE_COMMAND_QUEUE_INSUFFICIENT_HARDWARE_SUPPORT_FOR_GLOBAL_REALTIME + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DST = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_ARCHITECTURE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DST_RESOURCE_DIMENSION = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DST_RANGE_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DST_RESOURCE_DIMENSION + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_SRC = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DST_RANGE_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_SRC_RESOURCE_DIMENSION = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_SRC + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_SRC_RANGE_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_SRC_RESOURCE_DIMENSION + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_OFFSET_ALIGNMENT = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_SRC_RANGE_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DEPENDENT_RESOURCES = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_OFFSET_ALIGNMENT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DEPENDENT_SUBRESOURCE_RANGES = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DEPENDENT_RESOURCES + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DEPENDENT_RESOURCE = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_NULL_DEPENDENT_SUBRESOURCE_RANGES + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DEPENDENT_SUBRESOURCE_RANGE = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DEPENDENT_RESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DEPENDENT_SUBRESOURCE_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_INVALID_DEPENDENT_SUBRESOURCE_RANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DEPENDENT_RANGE_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DEPENDENT_SUBRESOURCE_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_ZERO_DEPENDENCIES = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_DEPENDENT_RANGE_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DEVICE_CREATE_SHARED_HANDLE_INVALIDARG = ( D3D12_MESSAGE_ID_ATOMICCOPYBUFFER_ZERO_DEPENDENCIES + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESCRIPTOR_HANDLE_WITH_INVALID_RESOURCE = ( D3D12_MESSAGE_ID_DEVICE_CREATE_SHARED_HANDLE_INVALIDARG + 1 ) ,
|
||||
D3D12_MESSAGE_ID_SETDEPTHBOUNDS_INVALIDARGS = ( D3D12_MESSAGE_ID_DESCRIPTOR_HANDLE_WITH_INVALID_RESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_RESOURCE_STATE_IMPRECISE = ( D3D12_MESSAGE_ID_SETDEPTHBOUNDS_INVALIDARGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_PIPELINE_STATE_NOT_SET = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_RESOURCE_STATE_IMPRECISE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_SHADER_MODEL_MISMATCH = ( D3D12_MESSAGE_ID_COMMAND_LIST_PIPELINE_STATE_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_OBJECT_ACCESSED_WHILE_STILL_IN_USE = ( D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_SHADER_MODEL_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_PROGRAMMABLE_MSAA_UNSUPPORTED = ( D3D12_MESSAGE_ID_OBJECT_ACCESSED_WHILE_STILL_IN_USE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_SETSAMPLEPOSITIONS_INVALIDARGS = ( D3D12_MESSAGE_ID_PROGRAMMABLE_MSAA_UNSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCEREGION_INVALID_RECT = ( D3D12_MESSAGE_ID_SETSAMPLEPOSITIONS_INVALIDARGS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEODECODECOMMANDQUEUE = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCEREGION_INVALID_RECT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSCOMMANDLIST = ( D3D12_MESSAGE_ID_CREATE_VIDEODECODECOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSCOMMANDQUEUE = ( D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEODECODECOMMANDQUEUE = ( D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSCOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSCOMMANDLIST = ( D3D12_MESSAGE_ID_LIVE_VIDEODECODECOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSCOMMANDQUEUE = ( D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEODECODECOMMANDQUEUE = ( D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSCOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSCOMMANDLIST = ( D3D12_MESSAGE_ID_DESTROY_VIDEODECODECOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSCOMMANDQUEUE = ( D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSCOMMANDLIST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSOR = ( D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSCOMMANDQUEUE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSSTREAM = ( D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSOR + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSOR = ( D3D12_MESSAGE_ID_CREATE_VIDEOPROCESSSTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSSTREAM = ( D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSOR + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSOR = ( D3D12_MESSAGE_ID_LIVE_VIDEOPROCESSSTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSSTREAM = ( D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSOR + 1 ) ,
|
||||
D3D12_MESSAGE_ID_PROCESS_FRAME_INVALID_PARAMETERS = ( D3D12_MESSAGE_ID_DESTROY_VIDEOPROCESSSTREAM + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COPY_INVALIDLAYOUT = ( D3D12_MESSAGE_ID_PROCESS_FRAME_INVALID_PARAMETERS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_COPY_INVALIDLAYOUT + 1 )
|
||||
D3D12_MESSAGE_ID_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UNSUPPORTED + 1 )
|
||||
} D3D12_MESSAGE_ID;
|
||||
|
||||
static_assert(D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UNSUPPORTED == 1000, "Publicly released SDK D3D12_MESSAGE_ID enum values must not be changed. New enum values must be added to the end of the list.");
|
||||
static_assert(D3D12_MESSAGE_ID_COPY_INVALIDLAYOUT == 1067, "Publicly released SDK D3D12_MESSAGE_ID enum values must not be changed. New enum values must be added to the end of the list.");
|
||||
typedef struct D3D12_MESSAGE
|
||||
{
|
||||
D3D12_MESSAGE_CATEGORY Category;
|
||||
@@ -2123,8 +1949,8 @@ typedef struct D3D12_INFO_QUEUE_FILTER
|
||||
#define D3D12_INFO_QUEUE_DEFAULT_MESSAGE_COUNT_LIMIT 1024
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0007_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0007_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12InfoQueue_INTERFACE_DEFINED__
|
||||
#define __ID3D12InfoQueue_INTERFACE_DEFINED__
|
||||
@@ -2531,14 +2357,13 @@ EXTERN_C const IID IID_ID3D12InfoQueue;
|
||||
#endif /* __ID3D12InfoQueue_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0009 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0008 */
|
||||
/* [local] */
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
DEFINE_GUID(IID_ID3D12Debug,0x344488b7,0x6846,0x474b,0xb9,0x89,0xf0,0x27,0x44,0x82,0x45,0xe0);
|
||||
DEFINE_GUID(IID_ID3D12Debug1,0xaffaa4ca,0x63fe,0x4d8e,0xb8,0xad,0x15,0x90,0x00,0xaf,0x43,0x04);
|
||||
DEFINE_GUID(IID_ID3D12Debug2,0x93a665c4,0xa3b2,0x4e5d,0xb6,0x92,0xa2,0x6a,0xe1,0x4e,0x33,0x74);
|
||||
DEFINE_GUID(IID_ID3D12DebugDevice1,0xa9b71770,0xd099,0x4a65,0xa6,0x98,0x3d,0xee,0x10,0x02,0x0f,0x88);
|
||||
DEFINE_GUID(IID_ID3D12DebugDevice,0x3febd6dd,0x4973,0x4787,0x81,0x94,0xe4,0x5f,0x9e,0x28,0x92,0x3e);
|
||||
DEFINE_GUID(IID_ID3D12DebugCommandQueue,0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0xae,0xea,0xb6,0x05,0x3a);
|
||||
@@ -2547,8 +2372,8 @@ DEFINE_GUID(IID_ID3D12DebugCommandList,0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0
|
||||
DEFINE_GUID(IID_ID3D12InfoQueue,0x0742a90b,0xc387,0x483f,0xb9,0x46,0x30,0xa7,0xe4,0xe6,0x14,0x58);
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0009_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0009_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
-10
@@ -4375,16 +4375,6 @@ interface DWRITE_DECLARE_INTERFACE("53737037-6d14-410b-9bfe-0b182bb70961") IDWri
|
||||
UINT32 maxHitTestMetricsCount,
|
||||
_Out_ UINT32* actualHitTestMetricsCount
|
||||
) PURE;
|
||||
|
||||
using IDWriteTextFormat::GetFontCollection;
|
||||
using IDWriteTextFormat::GetFontFamilyNameLength;
|
||||
using IDWriteTextFormat::GetFontFamilyName;
|
||||
using IDWriteTextFormat::GetFontWeight;
|
||||
using IDWriteTextFormat::GetFontStyle;
|
||||
using IDWriteTextFormat::GetFontStretch;
|
||||
using IDWriteTextFormat::GetFontSize;
|
||||
using IDWriteTextFormat::GetLocaleNameLength;
|
||||
using IDWriteTextFormat::GetLocaleName;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -10,7 +10,9 @@
|
||||
#ifndef DWRITE_1_H_INCLUDED
|
||||
#define DWRITE_1_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <DWrite.h>
|
||||
|
||||
@@ -1099,6 +1101,8 @@ interface DWRITE_DECLARE_INTERFACE("a71efdb4-9fdb-4838-ad90-cfc3be8c3daf") IDWri
|
||||
_Out_ DWRITE_FONT_METRICS1* fontMetrics
|
||||
) PURE;
|
||||
|
||||
using IDWriteFontFace::GetMetrics;
|
||||
|
||||
/// <summary>
|
||||
/// Gets common metrics for the font in design units.
|
||||
/// These metrics are applicable to all the glyphs within a font,
|
||||
@@ -1335,10 +1339,6 @@ interface DWRITE_DECLARE_INTERFACE("a71efdb4-9fdb-4838-ad90-cfc3be8c3daf") IDWri
|
||||
/// True if the font contains vertical glyph variants.
|
||||
/// </returns>
|
||||
STDMETHOD_(BOOL, HasVerticalGlyphVariants)() PURE;
|
||||
|
||||
using IDWriteFontFace::GetMetrics;
|
||||
using IDWriteFontFace::GetGdiCompatibleMetrics;
|
||||
using IDWriteFontFace::GetRecommendedRenderingMode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Vendored
+3
-10
@@ -10,7 +10,9 @@
|
||||
#ifndef DWRITE_2_H_INCLUDED
|
||||
#define DWRITE_2_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <DWrite_1.h>
|
||||
|
||||
@@ -236,11 +238,6 @@ interface DWRITE_DECLARE_INTERFACE("D3E0E934-22A0-427E-AAE4-7D9574B59DB1") IDWri
|
||||
BOOL isRightToLeft,
|
||||
_In_opt_ IUnknown* clientDrawingEffect
|
||||
) PURE;
|
||||
|
||||
using IDWriteTextRenderer::DrawGlyphRun;
|
||||
using IDWriteTextRenderer::DrawUnderline;
|
||||
using IDWriteTextRenderer::DrawStrikethrough;
|
||||
using IDWriteTextRenderer::DrawInlineObject;
|
||||
};
|
||||
|
||||
|
||||
@@ -513,8 +510,6 @@ interface DWRITE_DECLARE_INTERFACE("553A9FF3-5693-4DF7-B52B-74806F7F2EB9") IDWri
|
||||
_In_reads_(glyphCount) UINT16 const* glyphIndices,
|
||||
_Out_writes_(glyphCount) UINT8* featureApplies
|
||||
) PURE;
|
||||
|
||||
using IDWriteTextAnalyzer1::GetGlyphOrientationTransform;
|
||||
};
|
||||
|
||||
|
||||
@@ -648,7 +643,7 @@ typedef struct _D3DCOLORVALUE {
|
||||
} D3DCOLORVALUE;
|
||||
|
||||
#define D3DCOLORVALUE_DEFINED
|
||||
#endif // D3DCOLORVALUE_DEFINED
|
||||
#endif D3DCOLORVALUE_DEFINED
|
||||
|
||||
typedef D3DCOLORVALUE DWRITE_COLOR_F;
|
||||
|
||||
@@ -756,8 +751,6 @@ interface DWRITE_DECLARE_INTERFACE("d8b768ff-64bc-4e66-982b-ec8e87f693f7") IDWri
|
||||
_Out_ DWRITE_RENDERING_MODE* renderingMode,
|
||||
_Out_ DWRITE_GRID_FIT_MODE* gridFitMode
|
||||
) PURE;
|
||||
|
||||
using IDWriteFontFace1::GetRecommendedRenderingMode;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Vendored
-365
@@ -1578,8 +1578,6 @@ interface DWRITE_DECLARE_INTERFACE("4556BE70-3ABD-4F70-90BE-421780A6F515") IDWri
|
||||
_In_ IDWriteFontSet* fontSet,
|
||||
_COM_Outptr_ IDWriteFontSet** filteredSet
|
||||
) PURE;
|
||||
|
||||
using IDWriteGdiInterop::CreateFontFromLOGFONT;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -1686,9 +1684,6 @@ interface DWRITE_DECLARE_INTERFACE("F67E0EDD-9E3D-4ECC-8C32-4183253DFE70") IDWri
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(GetLineSpacing)(_Out_ DWRITE_LINE_SPACING* lineSpacingOptions) PURE;
|
||||
|
||||
using IDWriteTextFormat1::SetLineSpacing;
|
||||
using IDWriteTextFormat1::GetLineSpacing;
|
||||
};
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("07DDCD52-020E-4DE8-AC33-6C953D83F92D") IDWriteTextLayout3 : public IDWriteTextLayout2
|
||||
@@ -1743,10 +1738,6 @@ interface DWRITE_DECLARE_INTERFACE("07DDCD52-020E-4DE8-AC33-6C953D83F92D") IDWri
|
||||
UINT32 maxLineCount,
|
||||
_Out_ UINT32* actualLineCount
|
||||
) PURE;
|
||||
|
||||
using IDWriteTextLayout2::SetLineSpacing;
|
||||
using IDWriteTextLayout2::GetLineSpacing;
|
||||
using IDWriteTextLayout2::GetLineMetrics;
|
||||
};
|
||||
|
||||
|
||||
@@ -2065,360 +2056,4 @@ interface DWRITE_DECLARE_INTERFACE("4B0B5BD3-0797-4549-8AC5-FE915CC53856") IDWri
|
||||
|
||||
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS2
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("3FF7715F-3CDC-4DC6-9B72-EC5621DCCAFD") IDWriteFontSetBuilder1 : public IDWriteFontSetBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds references to all the fonts in the specified font file. The method
|
||||
/// parses the font file to determine the fonts and their properties.
|
||||
/// </summary>
|
||||
/// <param name="fontFile">Font file reference object to add to the set.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(AddFontFile)(
|
||||
_In_ IDWriteFontFile* fontFile
|
||||
) throw();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The IDWriteAsyncResult interface represents the result of an asynchronous
|
||||
/// operation. A client can use the interface to wait for the operation to
|
||||
/// complete and to get the result.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("CE25F8FD-863B-4D13-9651-C1F88DC73FE2") IDWriteAsyncResult : public IUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// The GetWaitHandleMethod method returns a handle that can be used to wait
|
||||
/// for the asynchronous operation to complete. The handle remains valid
|
||||
/// until the interface is released.
|
||||
/// </summary>
|
||||
STDMETHOD_(HANDLE, GetWaitHandle)() PURE;
|
||||
|
||||
/// <summary>
|
||||
/// The GetResult method returns the result of the asynchronous operation.
|
||||
/// The return value is E_PENDING if the operation has not yet completed.
|
||||
/// </summary>
|
||||
STDMETHOD(GetResult)() PURE;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DWRITE_FILE_FRAGMENT represents a range of bytes in a font file.
|
||||
/// </summary>
|
||||
struct DWRITE_FILE_FRAGMENT
|
||||
{
|
||||
/// <summary>
|
||||
/// Starting offset of the fragment from the beginning of the file.
|
||||
/// </summary>
|
||||
UINT64 fileOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the file fragment, in bytes.
|
||||
/// </summary>
|
||||
UINT64 fragmentSize;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// IDWriteRemoteFontFileStream represents a font file stream parts of which may be
|
||||
/// non-local. Non-local data must be downloaded before it can be accessed using
|
||||
/// ReadFragment. The interface exposes methods to download font data and query the
|
||||
/// locality of font data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For more information, see the description of IDWriteRemoteFontFileLoader.
|
||||
/// </remarks>
|
||||
interface DWRITE_DECLARE_INTERFACE("4DB3757A-2C72-4ED9-B2B6-1ABABE1AFF9C") IDWriteRemoteFontFileStream : public IDWriteFontFileStream
|
||||
{
|
||||
/// <summary>
|
||||
/// GetLocalFileSize returns the number of bytes of the font file that are
|
||||
/// currently local, which should always be less than or equal to the full
|
||||
/// file size returned by GetFileSize. If the locality is remote, the return
|
||||
/// value is zero. If the file is fully local, the return value must be the
|
||||
/// same as GetFileSize.
|
||||
/// </summary>
|
||||
/// <param name="localFileSize">Receives the local size of the file.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(GetLocalFileSize)(
|
||||
_Out_ UINT64* localFileSize
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// GetFileFragmentLocality returns information about the locality of a byte range (i.e.,
|
||||
/// font fragment) within the font file stream.
|
||||
/// </summary>
|
||||
/// <param name="fileOffset">Offset of the fragment from the beginning of the font file.</param>
|
||||
/// <param name="fragmentSize">Size of the fragment in bytes.</param>
|
||||
/// <param name="isLocal">Receives TRUE if the first byte of the fragment is local, FALSE if not.</param>
|
||||
/// <param name="partialSize">Receives the number of contiguous bytes from the start of the
|
||||
/// fragment that have the same locality as the first byte.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(GetFileFragmentLocality)(
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
_Out_ BOOL* isLocal,
|
||||
_Out_range_(0, fragmentSize) UINT64* partialSize
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current locality of the file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns the locality enumeration (i.e., remote, partial, or local).
|
||||
/// </returns>
|
||||
STDMETHOD_(DWRITE_LOCALITY, GetLocality)() PURE;
|
||||
|
||||
/// <summary>
|
||||
/// BeginDownload begins downloading all or part of the font file.
|
||||
/// </summary>
|
||||
/// <param name="fileFragments">Array of structures, each specifying a byte
|
||||
/// range to download.</param>
|
||||
/// <param name="fragmentCount">Number of elements in the fileFragments array.
|
||||
/// This can be zero to just download file information, such as the size.</param>
|
||||
/// <param name="asyncResult">Receives an object that can be used to wait for
|
||||
/// the asynchronous download to complete and to get the download result upon
|
||||
/// completion. The result may be NULL if the download completes synchronously.
|
||||
/// For example, this can happen if method determines that the requested data
|
||||
/// is already local.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(BeginDownload)(
|
||||
_In_ UUID const* downloadOperationID,
|
||||
_In_reads_(fragmentCount) DWRITE_FILE_FRAGMENT const* fileFragments,
|
||||
UINT32 fragmentCount,
|
||||
_COM_Outptr_result_maybenull_ IDWriteAsyncResult** asyncResult
|
||||
) PURE;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the container format of a font resource. A container format is distinct from
|
||||
/// a font file format (DWRITE_FONT_FILE_TYPE) because the container describes the container
|
||||
/// in which the underlying font file is packaged.
|
||||
/// </summary>
|
||||
enum DWRITE_CONTAINER_TYPE
|
||||
{
|
||||
DWRITE_CONTAINER_TYPE_UNKNOWN,
|
||||
DWRITE_CONTAINER_TYPE_WOFF,
|
||||
DWRITE_CONTAINER_TYPE_WOFF2
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The IDWriteRemoteFontFileLoader interface represents a font file loader that can access
|
||||
/// remote (i.e., downloadable) fonts. The IDWriteFactory5::CreateHttpFontFileLoader method
|
||||
/// returns an instance of this interface, or a client can create its own implementation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Calls to a remote file loader or stream should never block waiting for network operations.
|
||||
/// Any call that cannot succeeded immediately using local (e.g., cached) must should return
|
||||
/// DWRITE_E_REMOTEFONT. This error signifies to DWrite that it should add requests to the
|
||||
/// font download queue.
|
||||
/// </remarks>
|
||||
interface DWRITE_DECLARE_INTERFACE("68648C83-6EDE-46C0-AB46-20083A887FDE") IDWriteRemoteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a remote font file stream object that encapsulates an open file resource
|
||||
/// and can be used to download remote file data.
|
||||
/// </summary>
|
||||
/// <param name="fontFileReferenceKey">Font file reference key that uniquely identifies the font file resource
|
||||
/// within the scope of the font loader being used.</param>
|
||||
/// <param name="fontFileReferenceKeySize">Size of font file reference key in bytes.</param>
|
||||
/// <param name="fontFileStream">Pointer to the newly created font file stream.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Unlike CreateStreamFromKey, this method can be used to create a stream for a remote file.
|
||||
/// If the file is remote, the client must call IDWriteRemoteFontFileStream::DownloadFileInformation
|
||||
/// before the stream can be used to get the file size or access data.
|
||||
/// </remarks>
|
||||
STDMETHOD(CreateRemoteStreamFromKey)(
|
||||
_In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
_COM_Outptr_ IDWriteRemoteFontFileStream** fontFileStream
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the locality of the file resource identified by the unique key.
|
||||
/// </summary>
|
||||
/// <param name="fontFileReferenceKey">Font file reference key that uniquely identifies the font file resource
|
||||
/// within the scope of the font loader being used.</param>
|
||||
/// <param name="fontFileReferenceKeySize">Size of font file reference key in bytes.</param>
|
||||
/// <param name="locality">Locality of the file.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(GetLocalityFromKey)(
|
||||
_In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
_Out_ DWRITE_LOCALITY* locality
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a font file reference from a URL if the loader supports this capability.
|
||||
/// </summary>
|
||||
/// <param name="factory">Factory used to create the font file reference.</param>
|
||||
/// <param name="baseUrl">Optional base URL. The base URL is used to resolve the fontFileUrl
|
||||
/// if it is relative. For example, the baseUrl might be the URL of the referring document
|
||||
/// that contained the fontFileUrl.</param>
|
||||
/// <param name="fontFileUrl">URL of the font resource.</param>
|
||||
/// <param name="fontFile">Receives a pointer to the newly created font file reference.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code, or E_NOTIMPL if the loader does not implement this method.
|
||||
/// </returns>
|
||||
STDMETHOD(CreateFontFileReferenceFromUrl)(
|
||||
IDWriteFactory* factory,
|
||||
_In_opt_z_ WCHAR const* baseUrl,
|
||||
_In_z_ WCHAR const* fontFileUrl,
|
||||
_COM_Outptr_ IDWriteFontFile** fontFile
|
||||
) PURE;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The IDWriteInMemoryFontFileLoader interface enables clients to reference
|
||||
/// in-memory fonts without having to implement a custom loader. The
|
||||
/// IDWriteFactory5::CreateInMemoryFontFileLoader method returns an instance
|
||||
/// of this interface, which the client is responsible for registering and
|
||||
/// unregistering using IDWriteFactory::RegisterFontFileLoader and
|
||||
/// IDWriteFactory::UnregisterFontFileLoader.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("DC102F47-A12D-4B1C-822D-9E117E33043F") IDWriteInMemoryFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// The CreateInMemoryFontFileReference method creates a font file reference
|
||||
/// (IDWriteFontFile object) from an array of bytes. The font file reference
|
||||
/// is bound to the IDWRiteInMemoryFontFileLoader instance with which it was
|
||||
/// created and remains valid for as long as that loader is registered with
|
||||
/// the factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">Factory object used to create the font file reference.</param>
|
||||
/// <param name="fontData">Pointer to a memory block containing the font data.</param>
|
||||
/// <param name="fontDataSize">Size of the font data.</param>
|
||||
/// <param name="ownerObject">Optional object that owns the memory specified by
|
||||
/// the fontData parameter. If this parameter is not NULL, the method stores a
|
||||
/// pointer to the font data and adds a reference to the owner object. The
|
||||
/// fontData pointer must remain valid until the owner object is released. If
|
||||
/// this parameter is NULL, the method makes a copy of the font data.</param>
|
||||
/// <param name="fontFile">Receives a pointer to the newly-created font file
|
||||
/// reference.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(CreateInMemoryFontFileReference)(
|
||||
IDWriteFactory* factory,
|
||||
_In_reads_bytes_(fontDataSize) void const* fontData,
|
||||
UINT32 fontDataSize,
|
||||
_In_opt_ IUnknown* ownerObject,
|
||||
_COM_Outptr_ IDWriteFontFile** fontFile
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// The GetFileCount method returns the number of font file references that
|
||||
/// have been created using this loader instance.
|
||||
/// </summary>
|
||||
STDMETHOD_(UINT32, GetFileCount)() PURE;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The root factory interface for all DWrite objects.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("958DB99A-BE2A-4F09-AF7D-65189803D1D3") IDWriteFactory5 : public IDWriteFactory4
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an empty font set builder to add font face references
|
||||
/// and create a custom font set.
|
||||
/// </summary>
|
||||
/// <param name="fontSetBuilder">Holds the newly created font set builder object, or NULL in case of failure.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(CreateFontSetBuilder)(
|
||||
_COM_Outptr_ IDWriteFontSetBuilder1** fontSetBuilder
|
||||
) PURE;
|
||||
|
||||
using IDWriteFactory3::CreateFontSetBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// The CreateInMemoryFontFileLoader method creates a loader object that can
|
||||
/// be used to create font file references to in-memory fonts. The caller is
|
||||
/// responsible for registering and unregistering the loader.
|
||||
/// </summary>
|
||||
/// <param name="newLoader">Receives a pointer to the newly-created loader object.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(CreateInMemoryFontFileLoader)(
|
||||
_COM_Outptr_ IDWriteInMemoryFontFileLoader** newLoader
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// The CreateHttpFontFileLoader function creates a remote font file loader
|
||||
/// that can create font file references from HTTP or HTTPS URLs. The caller
|
||||
/// is responsible for registering and unregistering the loader.
|
||||
/// </summary>
|
||||
/// <param name="referrerUrl">Optional referrer URL for HTTP requests.</param>
|
||||
/// <param name="extraHeaders">Optional additional header fields to include
|
||||
/// in HTTP requests. Each header field consists of a name followed by a colon
|
||||
/// (":") and the field value, as specified by RFC 2616. Multiple header fields
|
||||
/// may be separated by newlines.</param>
|
||||
/// <param name="newLoader">Receives a pointer to the newly-created loader object.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
STDMETHOD(CreateHttpFontFileLoader)(
|
||||
_In_opt_z_ wchar_t const* referrerUrl,
|
||||
_In_opt_z_ wchar_t const* extraHeaders,
|
||||
_COM_Outptr_ IDWriteRemoteFontFileLoader** newLoader
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// The AnalyzeContainerType method analyzes the specified file data to determine
|
||||
/// whether it is a known font container format (e.g., WOFF or WOFF2).
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns the container type if recognized. DWRITE_CONTAINER_TYPE_UNKOWNN is
|
||||
/// returned for all other files, including uncompressed font files.
|
||||
/// </returns>
|
||||
STDMETHOD_(DWRITE_CONTAINER_TYPE, AnalyzeContainerType)(
|
||||
_In_reads_bytes_(fileDataSize) void const* fileData,
|
||||
UINT32 fileDataSize
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// The UnpackFontFile method unpacks font data from a container file (WOFF or
|
||||
/// WOFF2) and returns the unpacked font data in the form of a font file stream.
|
||||
/// </summary>
|
||||
/// <param name="containerType">Container type returned by AnalyzeContainerType.</param>
|
||||
/// <param name="fileData">Pointer to the compressed data.</param>
|
||||
/// <param name="fileDataSize">Size of the compressed data, in bytes.</param>
|
||||
/// <param name="unpackedFontStream">Receives a pointer to a newly created font
|
||||
/// file stream containing the uncompressed data.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code. The return value is E_INVALIDARG if the container
|
||||
/// type is DWRITE_CONTAINER_TYPE_UNKNOWN.
|
||||
/// </returns>
|
||||
STDMETHOD(UnpackFontFile)(
|
||||
DWRITE_CONTAINER_TYPE containerType,
|
||||
_In_reads_bytes_(fileDataSize) void const* fileData,
|
||||
UINT32 fileDataSize,
|
||||
_COM_Outptr_ IDWriteFontFileStream** unpackedFontStream
|
||||
) PURE;
|
||||
};
|
||||
|
||||
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS2
|
||||
|
||||
#endif // DWRITE_3_H_INCLUDED
|
||||
|
||||
Vendored
+18
-23
@@ -1,9 +1,9 @@
|
||||
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -140,7 +140,6 @@ typedef interface IDXGIDevice1 IDXGIDevice1;
|
||||
/* header files for imported files */
|
||||
#include "oaidl.h"
|
||||
#include "ocidl.h"
|
||||
#include "dxgicommon.h"
|
||||
#include "dxgitype.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -182,8 +181,6 @@ typedef struct DXGI_MAPPED_RECT
|
||||
} DXGI_MAPPED_RECT;
|
||||
|
||||
#ifdef __midl
|
||||
#ifndef LUID_DEFINED
|
||||
#define LUID_DEFINED 1
|
||||
typedef struct _LUID
|
||||
{
|
||||
DWORD LowPart;
|
||||
@@ -192,7 +189,6 @@ typedef struct _LUID
|
||||
|
||||
typedef struct _LUID *PLUID;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
typedef struct DXGI_ADAPTER_DESC
|
||||
{
|
||||
@@ -278,8 +274,7 @@ enum DXGI_SWAP_CHAIN_FLAG
|
||||
DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO = 256,
|
||||
DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO = 512,
|
||||
DXGI_SWAP_CHAIN_FLAG_HW_PROTECTED = 1024,
|
||||
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING = 2048,
|
||||
DXGI_SWAP_CHAIN_FLAG_RESTRICTED_TO_ALL_HOLOGRAPHIC_DISPLAYS = 4096
|
||||
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING = 2048
|
||||
} DXGI_SWAP_CHAIN_FLAG;
|
||||
|
||||
typedef struct DXGI_SWAP_CHAIN_DESC
|
||||
@@ -325,7 +320,7 @@ EXTERN_C const IID IID_IDXGIObject;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown) = 0;
|
||||
_In_ const IUnknown *pUnknown) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPrivateData(
|
||||
/* [annotation][in] */
|
||||
@@ -375,7 +370,7 @@ EXTERN_C const IID IID_IDXGIObject;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIObject * This,
|
||||
@@ -494,7 +489,7 @@ EXTERN_C const IID IID_IDXGIDeviceSubObject;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDeviceSubObject * This,
|
||||
@@ -632,7 +627,7 @@ EXTERN_C const IID IID_IDXGIResource;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIResource * This,
|
||||
@@ -794,7 +789,7 @@ EXTERN_C const IID IID_IDXGIKeyedMutex;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIKeyedMutex * This,
|
||||
@@ -959,7 +954,7 @@ EXTERN_C const IID IID_IDXGISurface;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISurface * This,
|
||||
@@ -1116,7 +1111,7 @@ EXTERN_C const IID IID_IDXGISurface1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISurface1 * This,
|
||||
@@ -1306,7 +1301,7 @@ EXTERN_C const IID IID_IDXGIAdapter;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIAdapter * This,
|
||||
@@ -1512,7 +1507,7 @@ EXTERN_C const IID IID_IDXGIOutput;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput * This,
|
||||
@@ -1794,7 +1789,7 @@ EXTERN_C const IID IID_IDXGISwapChain;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISwapChain * This,
|
||||
@@ -2046,7 +2041,7 @@ EXTERN_C const IID IID_IDXGIFactory;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory * This,
|
||||
@@ -2248,7 +2243,7 @@ EXTERN_C const IID IID_IDXGIDevice;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDevice * This,
|
||||
@@ -2455,7 +2450,7 @@ EXTERN_C const IID IID_IDXGIFactory1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory1 * This,
|
||||
@@ -2635,7 +2630,7 @@ EXTERN_C const IID IID_IDXGIAdapter1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIAdapter1 * This,
|
||||
@@ -2792,7 +2787,7 @@ EXTERN_C const IID IID_IDXGIDevice1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDevice1 * This,
|
||||
|
||||
Vendored
+10
-11
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ EXTERN_C const IID IID_IDXGIOutputDuplication;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutputDuplication * This,
|
||||
@@ -582,7 +582,7 @@ EXTERN_C const IID IID_IDXGISurface2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISurface2 * This,
|
||||
@@ -776,7 +776,7 @@ EXTERN_C const IID IID_IDXGIResource1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIResource1 * This,
|
||||
@@ -991,7 +991,7 @@ EXTERN_C const IID IID_IDXGIDevice2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDevice2 * This,
|
||||
@@ -1209,8 +1209,7 @@ typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC
|
||||
typedef struct DXGI_PRESENT_PARAMETERS
|
||||
{
|
||||
UINT DirtyRectsCount;
|
||||
/* [annotation] */
|
||||
_Field_size_full_opt_(DirtyRectsCount) RECT *pDirtyRects;
|
||||
RECT *pDirtyRects;
|
||||
RECT *pScrollRect;
|
||||
POINT *pScrollOffset;
|
||||
} DXGI_PRESENT_PARAMETERS;
|
||||
@@ -1315,7 +1314,7 @@ EXTERN_C const IID IID_IDXGISwapChain1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISwapChain1 * This,
|
||||
@@ -1700,7 +1699,7 @@ EXTERN_C const IID IID_IDXGIFactory2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory2 * This,
|
||||
@@ -2049,7 +2048,7 @@ EXTERN_C const IID IID_IDXGIAdapter2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIAdapter2 * This,
|
||||
@@ -2234,7 +2233,7 @@ EXTERN_C const IID IID_IDXGIOutput1;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput1 * This,
|
||||
|
||||
Vendored
+6
-6
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ EXTERN_C const IID IID_IDXGIDevice3;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDevice3 * This,
|
||||
@@ -430,7 +430,7 @@ EXTERN_C const IID IID_IDXGISwapChain2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISwapChain2 * This,
|
||||
@@ -792,7 +792,7 @@ EXTERN_C const IID IID_IDXGIOutput2;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput2 * This,
|
||||
@@ -1059,7 +1059,7 @@ EXTERN_C const IID IID_IDXGIFactory3;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory3 * This,
|
||||
@@ -1861,7 +1861,7 @@ EXTERN_C const IID IID_IDXGIOutput3;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput3 * This,
|
||||
|
||||
Vendored
+5
-5
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ EXTERN_C const IID IID_IDXGISwapChain3;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISwapChain3 * This,
|
||||
@@ -599,7 +599,7 @@ EXTERN_C const IID IID_IDXGIOutput4;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput4 * This,
|
||||
@@ -906,7 +906,7 @@ EXTERN_C const IID IID_IDXGIFactory4;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory4 * This,
|
||||
@@ -1296,7 +1296,7 @@ EXTERN_C const IID IID_IDXGIAdapter3;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIAdapter3 * This,
|
||||
|
||||
Vendored
+5
-11
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -81,12 +81,6 @@ extern "C"{
|
||||
#include <winapifamily.h>
|
||||
#pragma region App Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
typedef
|
||||
enum DXGI_OUTDUPL_FLAG
|
||||
{
|
||||
DXGI_OUTDUPL_COMPOSITED_UI_CAPTURE_ONLY = 1
|
||||
} DXGI_OUTDUPL_FLAG;
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_5_0000_0000_v0_0_c_ifspec;
|
||||
@@ -152,7 +146,7 @@ EXTERN_C const IID IID_IDXGIOutput5;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput5 * This,
|
||||
@@ -496,7 +490,7 @@ EXTERN_C const IID IID_IDXGISwapChain4;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGISwapChain4 * This,
|
||||
@@ -954,7 +948,7 @@ EXTERN_C const IID IID_IDXGIDevice4;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIDevice4 * This,
|
||||
@@ -1219,7 +1213,7 @@ EXTERN_C const IID IID_IDXGIFactory5;
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
_In_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIFactory5 * This,
|
||||
|
||||
Vendored
-727
@@ -1,727 +0,0 @@
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0622 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||
#define __REQUIRED_RPCNDR_H_VERSION__ 500
|
||||
#endif
|
||||
|
||||
/* verify that the <rpcsal.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCSAL_H_VERSION__
|
||||
#define __REQUIRED_RPCSAL_H_VERSION__ 100
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcndr.h"
|
||||
|
||||
#ifndef __RPCNDR_H_VERSION__
|
||||
#error this stub requires an updated version of <rpcndr.h>
|
||||
#endif /* __RPCNDR_H_VERSION__ */
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include "windows.h"
|
||||
#include "ole2.h"
|
||||
#endif /*COM_NO_WINDOWS_H*/
|
||||
|
||||
#ifndef __dxgi1_6_h__
|
||||
#define __dxgi1_6_h__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
|
||||
#ifndef __IDXGIAdapter4_FWD_DEFINED__
|
||||
#define __IDXGIAdapter4_FWD_DEFINED__
|
||||
typedef interface IDXGIAdapter4 IDXGIAdapter4;
|
||||
|
||||
#endif /* __IDXGIAdapter4_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __IDXGIOutput6_FWD_DEFINED__
|
||||
#define __IDXGIOutput6_FWD_DEFINED__
|
||||
typedef interface IDXGIOutput6 IDXGIOutput6;
|
||||
|
||||
#endif /* __IDXGIOutput6_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "dxgi1_5.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
|
||||
/* interface __MIDL_itf_dxgi1_6_0000_0000 */
|
||||
/* [local] */
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All Rights Reserved
|
||||
#include <winapifamily.h>
|
||||
#pragma region App Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
typedef
|
||||
enum DXGI_ADAPTER_FLAG3
|
||||
{
|
||||
DXGI_ADAPTER_FLAG3_NONE = 0,
|
||||
DXGI_ADAPTER_FLAG3_REMOTE = 1,
|
||||
DXGI_ADAPTER_FLAG3_SOFTWARE = 2,
|
||||
DXGI_ADAPTER_FLAG3_ACG_COMPATIBLE = 4,
|
||||
DXGI_ADAPTER_FLAG3_FORCE_DWORD = 0xffffffff
|
||||
} DXGI_ADAPTER_FLAG3;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS( DXGI_ADAPTER_FLAG3 );
|
||||
typedef struct DXGI_ADAPTER_DESC3
|
||||
{
|
||||
WCHAR Description[ 128 ];
|
||||
UINT VendorId;
|
||||
UINT DeviceId;
|
||||
UINT SubSysId;
|
||||
UINT Revision;
|
||||
SIZE_T DedicatedVideoMemory;
|
||||
SIZE_T DedicatedSystemMemory;
|
||||
SIZE_T SharedSystemMemory;
|
||||
LUID AdapterLuid;
|
||||
DXGI_ADAPTER_FLAG3 Flags;
|
||||
DXGI_GRAPHICS_PREEMPTION_GRANULARITY GraphicsPreemptionGranularity;
|
||||
DXGI_COMPUTE_PREEMPTION_GRANULARITY ComputePreemptionGranularity;
|
||||
} DXGI_ADAPTER_DESC3;
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0000_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0000_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __IDXGIAdapter4_INTERFACE_DEFINED__
|
||||
#define __IDXGIAdapter4_INTERFACE_DEFINED__
|
||||
|
||||
/* interface IDXGIAdapter4 */
|
||||
/* [unique][local][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_IDXGIAdapter4;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("3c8d99d1-4fbf-4181-a82c-af66bf7bd24e")
|
||||
IDXGIAdapter4 : public IDXGIAdapter3
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDesc3(
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_ADAPTER_DESC3 *pDesc) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct IDXGIAdapter4Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
IDXGIAdapter4 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
IDXGIAdapter4 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [in] */ UINT DataSize,
|
||||
/* [annotation][in] */
|
||||
_In_reads_bytes_(DataSize) const void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][out][in] */
|
||||
_Inout_ UINT *pDataSize,
|
||||
/* [annotation][out] */
|
||||
_Out_writes_bytes_(*pDataSize) void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetParent )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFIID riid,
|
||||
/* [annotation][retval][out] */
|
||||
_COM_Outptr_ void **ppParent);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *EnumOutputs )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [in] */ UINT Output,
|
||||
/* [annotation][out][in] */
|
||||
_COM_Outptr_ IDXGIOutput **ppOutput);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_ADAPTER_DESC *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckInterfaceSupport )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID InterfaceName,
|
||||
/* [annotation][out] */
|
||||
_Out_ LARGE_INTEGER *pUMDVersion);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc1 )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_ADAPTER_DESC1 *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc2 )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_ADAPTER_DESC2 *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *RegisterHardwareContentProtectionTeardownStatusEvent )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ HANDLE hEvent,
|
||||
/* [annotation][out] */
|
||||
_Out_ DWORD *pdwCookie);
|
||||
|
||||
void ( STDMETHODCALLTYPE *UnregisterHardwareContentProtectionTeardownStatus )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ DWORD dwCookie);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryVideoMemoryInfo )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ UINT NodeIndex,
|
||||
/* [annotation][in] */
|
||||
_In_ DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetVideoMemoryReservation )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ UINT NodeIndex,
|
||||
/* [annotation][in] */
|
||||
_In_ DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup,
|
||||
/* [annotation][in] */
|
||||
_In_ UINT64 Reservation);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *RegisterVideoMemoryBudgetChangeNotificationEvent )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ HANDLE hEvent,
|
||||
/* [annotation][out] */
|
||||
_Out_ DWORD *pdwCookie);
|
||||
|
||||
void ( STDMETHODCALLTYPE *UnregisterVideoMemoryBudgetChangeNotification )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ DWORD dwCookie);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc3 )(
|
||||
IDXGIAdapter4 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_ADAPTER_DESC3 *pDesc);
|
||||
|
||||
END_INTERFACE
|
||||
} IDXGIAdapter4Vtbl;
|
||||
|
||||
interface IDXGIAdapter4
|
||||
{
|
||||
CONST_VTBL struct IDXGIAdapter4Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define IDXGIAdapter4_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define IDXGIAdapter4_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define IDXGIAdapter4_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_SetPrivateData(This,Name,DataSize,pData) \
|
||||
( (This)->lpVtbl -> SetPrivateData(This,Name,DataSize,pData) )
|
||||
|
||||
#define IDXGIAdapter4_SetPrivateDataInterface(This,Name,pUnknown) \
|
||||
( (This)->lpVtbl -> SetPrivateDataInterface(This,Name,pUnknown) )
|
||||
|
||||
#define IDXGIAdapter4_GetPrivateData(This,Name,pDataSize,pData) \
|
||||
( (This)->lpVtbl -> GetPrivateData(This,Name,pDataSize,pData) )
|
||||
|
||||
#define IDXGIAdapter4_GetParent(This,riid,ppParent) \
|
||||
( (This)->lpVtbl -> GetParent(This,riid,ppParent) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_EnumOutputs(This,Output,ppOutput) \
|
||||
( (This)->lpVtbl -> EnumOutputs(This,Output,ppOutput) )
|
||||
|
||||
#define IDXGIAdapter4_GetDesc(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc(This,pDesc) )
|
||||
|
||||
#define IDXGIAdapter4_CheckInterfaceSupport(This,InterfaceName,pUMDVersion) \
|
||||
( (This)->lpVtbl -> CheckInterfaceSupport(This,InterfaceName,pUMDVersion) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_GetDesc1(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc1(This,pDesc) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_GetDesc2(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc2(This,pDesc) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_RegisterHardwareContentProtectionTeardownStatusEvent(This,hEvent,pdwCookie) \
|
||||
( (This)->lpVtbl -> RegisterHardwareContentProtectionTeardownStatusEvent(This,hEvent,pdwCookie) )
|
||||
|
||||
#define IDXGIAdapter4_UnregisterHardwareContentProtectionTeardownStatus(This,dwCookie) \
|
||||
( (This)->lpVtbl -> UnregisterHardwareContentProtectionTeardownStatus(This,dwCookie) )
|
||||
|
||||
#define IDXGIAdapter4_QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) \
|
||||
( (This)->lpVtbl -> QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) )
|
||||
|
||||
#define IDXGIAdapter4_SetVideoMemoryReservation(This,NodeIndex,MemorySegmentGroup,Reservation) \
|
||||
( (This)->lpVtbl -> SetVideoMemoryReservation(This,NodeIndex,MemorySegmentGroup,Reservation) )
|
||||
|
||||
#define IDXGIAdapter4_RegisterVideoMemoryBudgetChangeNotificationEvent(This,hEvent,pdwCookie) \
|
||||
( (This)->lpVtbl -> RegisterVideoMemoryBudgetChangeNotificationEvent(This,hEvent,pdwCookie) )
|
||||
|
||||
#define IDXGIAdapter4_UnregisterVideoMemoryBudgetChangeNotification(This,dwCookie) \
|
||||
( (This)->lpVtbl -> UnregisterVideoMemoryBudgetChangeNotification(This,dwCookie) )
|
||||
|
||||
|
||||
#define IDXGIAdapter4_GetDesc3(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc3(This,pDesc) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __IDXGIAdapter4_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_dxgi1_6_0000_0001 */
|
||||
/* [local] */
|
||||
|
||||
typedef struct DXGI_OUTPUT_DESC1
|
||||
{
|
||||
WCHAR DeviceName[ 32 ];
|
||||
RECT DesktopCoordinates;
|
||||
BOOL AttachedToDesktop;
|
||||
DXGI_MODE_ROTATION Rotation;
|
||||
HMONITOR Monitor;
|
||||
UINT BitsPerColor;
|
||||
DXGI_COLOR_SPACE_TYPE ColorSpace;
|
||||
FLOAT RedPrimary[ 2 ];
|
||||
FLOAT GreenPrimary[ 2 ];
|
||||
FLOAT BluePrimary[ 2 ];
|
||||
FLOAT WhitePoint[ 2 ];
|
||||
FLOAT MinLuminance;
|
||||
FLOAT MaxLuminance;
|
||||
FLOAT MaxFullFrameLuminance;
|
||||
} DXGI_OUTPUT_DESC1;
|
||||
|
||||
typedef
|
||||
enum DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAGS
|
||||
{
|
||||
DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN = 1,
|
||||
DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_WINDOWED = 2,
|
||||
DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED = 4
|
||||
} DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAGS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS( DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAGS );
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0001_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0001_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __IDXGIOutput6_INTERFACE_DEFINED__
|
||||
#define __IDXGIOutput6_INTERFACE_DEFINED__
|
||||
|
||||
/* interface IDXGIOutput6 */
|
||||
/* [unique][local][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_IDXGIOutput6;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("068346e8-aaec-4b84-add7-137f513f77a1")
|
||||
IDXGIOutput6 : public IDXGIOutput5
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDesc1(
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_OUTPUT_DESC1 *pDesc) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE CheckHardwareCompositionSupport(
|
||||
/* [annotation][out] */
|
||||
_Out_ UINT *pFlags) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct IDXGIOutput6Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
IDXGIOutput6 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
IDXGIOutput6 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [in] */ UINT DataSize,
|
||||
/* [annotation][in] */
|
||||
_In_reads_bytes_(DataSize) const void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ const IUnknown *pUnknown);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFGUID Name,
|
||||
/* [annotation][out][in] */
|
||||
_Inout_ UINT *pDataSize,
|
||||
/* [annotation][out] */
|
||||
_Out_writes_bytes_(*pDataSize) void *pData);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetParent )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ REFIID riid,
|
||||
/* [annotation][retval][out] */
|
||||
_COM_Outptr_ void **ppParent);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_OUTPUT_DESC *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDisplayModeList )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [in] */ DXGI_FORMAT EnumFormat,
|
||||
/* [in] */ UINT Flags,
|
||||
/* [annotation][out][in] */
|
||||
_Inout_ UINT *pNumModes,
|
||||
/* [annotation][out] */
|
||||
_Out_writes_to_opt_(*pNumModes,*pNumModes) DXGI_MODE_DESC *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *FindClosestMatchingMode )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ const DXGI_MODE_DESC *pModeToMatch,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_MODE_DESC *pClosestMatch,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ IUnknown *pConcernedDevice);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *WaitForVBlank )(
|
||||
IDXGIOutput6 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *TakeOwnership )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IUnknown *pDevice,
|
||||
BOOL Exclusive);
|
||||
|
||||
void ( STDMETHODCALLTYPE *ReleaseOwnership )(
|
||||
IDXGIOutput6 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetGammaControlCapabilities )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetGammaControl )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ const DXGI_GAMMA_CONTROL *pArray);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetGammaControl )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_GAMMA_CONTROL *pArray);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetDisplaySurface )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IDXGISurface *pScanoutSurface);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDisplaySurfaceData )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IDXGISurface *pDestination);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetFrameStatistics )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_FRAME_STATISTICS *pStats);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDisplayModeList1 )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [in] */ DXGI_FORMAT EnumFormat,
|
||||
/* [in] */ UINT Flags,
|
||||
/* [annotation][out][in] */
|
||||
_Inout_ UINT *pNumModes,
|
||||
/* [annotation][out] */
|
||||
_Out_writes_to_opt_(*pNumModes,*pNumModes) DXGI_MODE_DESC1 *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *FindClosestMatchingMode1 )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ const DXGI_MODE_DESC1 *pModeToMatch,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_MODE_DESC1 *pClosestMatch,
|
||||
/* [annotation][in] */
|
||||
_In_opt_ IUnknown *pConcernedDevice);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDisplaySurfaceData1 )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IDXGIResource *pDestination);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *DuplicateOutput )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IUnknown *pDevice,
|
||||
/* [annotation][out] */
|
||||
_COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication);
|
||||
|
||||
BOOL ( STDMETHODCALLTYPE *SupportsOverlays )(
|
||||
IDXGIOutput6 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckOverlaySupport )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ DXGI_FORMAT EnumFormat,
|
||||
/* [annotation][out] */
|
||||
_In_ IUnknown *pConcernedDevice,
|
||||
/* [annotation][out] */
|
||||
_Out_ UINT *pFlags);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckOverlayColorSpaceSupport )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ DXGI_FORMAT Format,
|
||||
/* [annotation][in] */
|
||||
_In_ DXGI_COLOR_SPACE_TYPE ColorSpace,
|
||||
/* [annotation][in] */
|
||||
_In_ IUnknown *pConcernedDevice,
|
||||
/* [annotation][out] */
|
||||
_Out_ UINT *pFlags);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *DuplicateOutput1 )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][in] */
|
||||
_In_ IUnknown *pDevice,
|
||||
/* [in] */ UINT Flags,
|
||||
/* [annotation][in] */
|
||||
_In_ UINT SupportedFormatsCount,
|
||||
/* [annotation][in] */
|
||||
_In_reads_(SupportedFormatsCount) const DXGI_FORMAT *pSupportedFormats,
|
||||
/* [annotation][out] */
|
||||
_COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDesc1 )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ DXGI_OUTPUT_DESC1 *pDesc);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *CheckHardwareCompositionSupport )(
|
||||
IDXGIOutput6 * This,
|
||||
/* [annotation][out] */
|
||||
_Out_ UINT *pFlags);
|
||||
|
||||
END_INTERFACE
|
||||
} IDXGIOutput6Vtbl;
|
||||
|
||||
interface IDXGIOutput6
|
||||
{
|
||||
CONST_VTBL struct IDXGIOutput6Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define IDXGIOutput6_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define IDXGIOutput6_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define IDXGIOutput6_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_SetPrivateData(This,Name,DataSize,pData) \
|
||||
( (This)->lpVtbl -> SetPrivateData(This,Name,DataSize,pData) )
|
||||
|
||||
#define IDXGIOutput6_SetPrivateDataInterface(This,Name,pUnknown) \
|
||||
( (This)->lpVtbl -> SetPrivateDataInterface(This,Name,pUnknown) )
|
||||
|
||||
#define IDXGIOutput6_GetPrivateData(This,Name,pDataSize,pData) \
|
||||
( (This)->lpVtbl -> GetPrivateData(This,Name,pDataSize,pData) )
|
||||
|
||||
#define IDXGIOutput6_GetParent(This,riid,ppParent) \
|
||||
( (This)->lpVtbl -> GetParent(This,riid,ppParent) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_GetDesc(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc(This,pDesc) )
|
||||
|
||||
#define IDXGIOutput6_GetDisplayModeList(This,EnumFormat,Flags,pNumModes,pDesc) \
|
||||
( (This)->lpVtbl -> GetDisplayModeList(This,EnumFormat,Flags,pNumModes,pDesc) )
|
||||
|
||||
#define IDXGIOutput6_FindClosestMatchingMode(This,pModeToMatch,pClosestMatch,pConcernedDevice) \
|
||||
( (This)->lpVtbl -> FindClosestMatchingMode(This,pModeToMatch,pClosestMatch,pConcernedDevice) )
|
||||
|
||||
#define IDXGIOutput6_WaitForVBlank(This) \
|
||||
( (This)->lpVtbl -> WaitForVBlank(This) )
|
||||
|
||||
#define IDXGIOutput6_TakeOwnership(This,pDevice,Exclusive) \
|
||||
( (This)->lpVtbl -> TakeOwnership(This,pDevice,Exclusive) )
|
||||
|
||||
#define IDXGIOutput6_ReleaseOwnership(This) \
|
||||
( (This)->lpVtbl -> ReleaseOwnership(This) )
|
||||
|
||||
#define IDXGIOutput6_GetGammaControlCapabilities(This,pGammaCaps) \
|
||||
( (This)->lpVtbl -> GetGammaControlCapabilities(This,pGammaCaps) )
|
||||
|
||||
#define IDXGIOutput6_SetGammaControl(This,pArray) \
|
||||
( (This)->lpVtbl -> SetGammaControl(This,pArray) )
|
||||
|
||||
#define IDXGIOutput6_GetGammaControl(This,pArray) \
|
||||
( (This)->lpVtbl -> GetGammaControl(This,pArray) )
|
||||
|
||||
#define IDXGIOutput6_SetDisplaySurface(This,pScanoutSurface) \
|
||||
( (This)->lpVtbl -> SetDisplaySurface(This,pScanoutSurface) )
|
||||
|
||||
#define IDXGIOutput6_GetDisplaySurfaceData(This,pDestination) \
|
||||
( (This)->lpVtbl -> GetDisplaySurfaceData(This,pDestination) )
|
||||
|
||||
#define IDXGIOutput6_GetFrameStatistics(This,pStats) \
|
||||
( (This)->lpVtbl -> GetFrameStatistics(This,pStats) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_GetDisplayModeList1(This,EnumFormat,Flags,pNumModes,pDesc) \
|
||||
( (This)->lpVtbl -> GetDisplayModeList1(This,EnumFormat,Flags,pNumModes,pDesc) )
|
||||
|
||||
#define IDXGIOutput6_FindClosestMatchingMode1(This,pModeToMatch,pClosestMatch,pConcernedDevice) \
|
||||
( (This)->lpVtbl -> FindClosestMatchingMode1(This,pModeToMatch,pClosestMatch,pConcernedDevice) )
|
||||
|
||||
#define IDXGIOutput6_GetDisplaySurfaceData1(This,pDestination) \
|
||||
( (This)->lpVtbl -> GetDisplaySurfaceData1(This,pDestination) )
|
||||
|
||||
#define IDXGIOutput6_DuplicateOutput(This,pDevice,ppOutputDuplication) \
|
||||
( (This)->lpVtbl -> DuplicateOutput(This,pDevice,ppOutputDuplication) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_SupportsOverlays(This) \
|
||||
( (This)->lpVtbl -> SupportsOverlays(This) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_CheckOverlaySupport(This,EnumFormat,pConcernedDevice,pFlags) \
|
||||
( (This)->lpVtbl -> CheckOverlaySupport(This,EnumFormat,pConcernedDevice,pFlags) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_CheckOverlayColorSpaceSupport(This,Format,ColorSpace,pConcernedDevice,pFlags) \
|
||||
( (This)->lpVtbl -> CheckOverlayColorSpaceSupport(This,Format,ColorSpace,pConcernedDevice,pFlags) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_DuplicateOutput1(This,pDevice,Flags,SupportedFormatsCount,pSupportedFormats,ppOutputDuplication) \
|
||||
( (This)->lpVtbl -> DuplicateOutput1(This,pDevice,Flags,SupportedFormatsCount,pSupportedFormats,ppOutputDuplication) )
|
||||
|
||||
|
||||
#define IDXGIOutput6_GetDesc1(This,pDesc) \
|
||||
( (This)->lpVtbl -> GetDesc1(This,pDesc) )
|
||||
|
||||
#define IDXGIOutput6_CheckHardwareCompositionSupport(This,pFlags) \
|
||||
( (This)->lpVtbl -> CheckHardwareCompositionSupport(This,pFlags) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __IDXGIOutput6_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_dxgi1_6_0000_0002 */
|
||||
/* [local] */
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
DEFINE_GUID(IID_IDXGIAdapter4,0x3c8d99d1,0x4fbf,0x4181,0xa8,0x2c,0xaf,0x66,0xbf,0x7b,0xd2,0x4e);
|
||||
DEFINE_GUID(IID_IDXGIOutput6,0x068346e8,0xaaec,0x4b84,0xad,0xd7,0x13,0x7f,0x51,0x3f,0x77,0xa1);
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi1_6_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __dxgicommon_h__
|
||||
#define __dxgicommon_h__
|
||||
|
||||
|
||||
typedef struct DXGI_RATIONAL
|
||||
{
|
||||
UINT Numerator;
|
||||
UINT Denominator;
|
||||
} DXGI_RATIONAL;
|
||||
|
||||
// The following values are used with DXGI_SAMPLE_DESC::Quality:
|
||||
#define DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN 0xffffffff
|
||||
#define DXGI_CENTER_MULTISAMPLE_QUALITY_PATTERN 0xfffffffe
|
||||
|
||||
typedef struct DXGI_SAMPLE_DESC
|
||||
{
|
||||
UINT Count;
|
||||
UINT Quality;
|
||||
} DXGI_SAMPLE_DESC;
|
||||
|
||||
typedef enum DXGI_COLOR_SPACE_TYPE
|
||||
{
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3,
|
||||
DXGI_COLOR_SPACE_RESERVED = 4,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19,
|
||||
DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF
|
||||
} DXGI_COLOR_SPACE_TYPE;
|
||||
|
||||
#endif // __dxgicommon_h__
|
||||
|
||||
Vendored
+40
-2
@@ -1,10 +1,9 @@
|
||||
//
|
||||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#ifndef __dxgitype_h__
|
||||
#define __dxgitype_h__
|
||||
|
||||
#include "dxgicommon.h"
|
||||
#include "dxgiformat.h"
|
||||
|
||||
#define _FACDXGI 0x87a
|
||||
@@ -56,6 +55,12 @@ typedef struct DXGI_GAMMA_CONTROL_CAPABILITIES
|
||||
float ControlPointPositions[1025];
|
||||
} DXGI_GAMMA_CONTROL_CAPABILITIES;
|
||||
|
||||
typedef struct DXGI_RATIONAL
|
||||
{
|
||||
UINT Numerator;
|
||||
UINT Denominator;
|
||||
} DXGI_RATIONAL;
|
||||
|
||||
typedef enum DXGI_MODE_SCANLINE_ORDER
|
||||
{
|
||||
DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0,
|
||||
@@ -90,6 +95,39 @@ typedef struct DXGI_MODE_DESC
|
||||
DXGI_MODE_SCALING Scaling;
|
||||
} DXGI_MODE_DESC;
|
||||
|
||||
// The following values are used with DXGI_SAMPLE_DESC::Quality:
|
||||
#define DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN 0xffffffff
|
||||
#define DXGI_CENTER_MULTISAMPLE_QUALITY_PATTERN 0xfffffffe
|
||||
|
||||
typedef struct DXGI_SAMPLE_DESC
|
||||
{
|
||||
UINT Count;
|
||||
UINT Quality;
|
||||
} DXGI_SAMPLE_DESC;
|
||||
|
||||
typedef enum DXGI_COLOR_SPACE_TYPE
|
||||
{
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3,
|
||||
DXGI_COLOR_SPACE_RESERVED = 4,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10,
|
||||
DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13,
|
||||
DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15,
|
||||
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16,
|
||||
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17,
|
||||
DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF
|
||||
} DXGI_COLOR_SPACE_TYPE;
|
||||
|
||||
typedef struct DXGI_JPEG_DC_HUFFMAN_TABLE
|
||||
{
|
||||
BYTE CodeCounts[12];
|
||||
|
||||
+3
-13
@@ -146,10 +146,6 @@ Abstract:
|
||||
#define NTDDI_WIN10 0x0A000000 /* ABRACADABRA_THRESHOLD */
|
||||
#define NTDDI_WIN10_TH2 0x0A000001 /* ABRACADABRA_WIN10_TH2 */
|
||||
#define NTDDI_WIN10_RS1 0x0A000002 /* ABRACADABRA_WIN10_RS1 */
|
||||
#define NTDDI_WIN10_RS2 0x0A000003 /* ABRACADABRA_WIN10_RS2 */
|
||||
|
||||
|
||||
#define WDK_NTDDI_VERSION NTDDI_WIN10_RS2
|
||||
|
||||
//
|
||||
// masks for version macros
|
||||
@@ -215,18 +211,12 @@ Abstract:
|
||||
|
||||
#ifndef NTDDI_VERSION
|
||||
#ifdef _WIN32_WINNT
|
||||
#if (_WIN32_WINNT <= _WIN32_WINNT_WINBLUE)
|
||||
// set NTDDI_VERSION based on _WIN32_WINNT
|
||||
#define NTDDI_VERSION NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
|
||||
#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN10)
|
||||
// set NTDDI_VERSION to default to WDK_NTDDI_VERSION
|
||||
#define NTDDI_VERSION WDK_NTDDI_VERSION
|
||||
#endif // (_WIN32_WINNT <= _WIN32_WINNT_WINBLUE)
|
||||
#else
|
||||
// set NTDDI_VERSION to default to latest if _WIN32_WINNT isn't set
|
||||
#define NTDDI_VERSION 0x0A000003
|
||||
#endif // _WIN32_WINNT
|
||||
#endif // NTDDI_VERSION
|
||||
#define NTDDI_VERSION 0x0A000002
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
#ifdef _WIN32_WINNT
|
||||
|
||||
-240
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
winapifamily.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Master include file for API family partitioning.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_WINAPIFAMILY
|
||||
#define _INC_WINAPIFAMILY
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4001) /* nonstandard extension 'single line comment' was used */
|
||||
#endif
|
||||
#pragma once
|
||||
#endif // defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
|
||||
#include <winpackagefamily.h>
|
||||
|
||||
/*
|
||||
* When compiling C and C++ code using SDK header files, the development
|
||||
* environment can specify a target platform by #define-ing the
|
||||
* pre-processor symbol WINAPI_FAMILY to one of the following values.
|
||||
* Each FAMILY value denotes an application family for which a different
|
||||
* subset of the total set of header-file-defined APIs are available.
|
||||
* Setting the WINAPI_FAMILY value will effectively hide from the
|
||||
* editing and compilation environments the existence of APIs that
|
||||
* are not applicable to the family of applications targeting a
|
||||
* specific platform.
|
||||
*/
|
||||
|
||||
/* In Windows 10, WINAPI_PARTITIONs will be used to add additional
|
||||
* device specific APIs to a particular WINAPI_FAMILY.
|
||||
* For example, when writing Windows Universal apps, specifying
|
||||
* WINAPI_FAMILY_APP will hide phone APIs from compilation.
|
||||
* However, specifying WINAPI_PARTITION_PHONE_APP=1 additionally, will
|
||||
* unhide any API hidden behind the partition, to the compiler.
|
||||
|
||||
* The following partitions are currently defined:
|
||||
* WINAPI_PARTITION_DESKTOP // usable for Desktop Win32 apps (but not store apps)
|
||||
* WINAPI_PARTITION_APP // usable for Windows Universal store apps
|
||||
* WINAPI_PARTITION_PC_APP // specific to Desktop-only store apps
|
||||
* WINAPI_PARTITION_PHONE_APP // specific to Phone-only store apps
|
||||
* WINAPI_PARTITION_SYSTEM // specific to System applications
|
||||
|
||||
* The following partitions are indirect partitions and defined in
|
||||
* winpackagefamily.h. These partitions are related to package based
|
||||
* partitions. For example, specifying WINAPI_PARTITION_SERVER=1 will light up
|
||||
* any API hidden behind the package based partitions that are bound to
|
||||
* WINAPI_PARTITION_SERVER, to the compiler.
|
||||
* WINAPI_PARTITION_SERVER // specific to Server applications
|
||||
*/
|
||||
|
||||
/*
|
||||
* The WINAPI_FAMILY values of 0 and 1 are reserved to ensure that
|
||||
* an error will occur if WINAPI_FAMILY is set to any
|
||||
* WINAPI_PARTITION value (which must be 0 or 1, see below).
|
||||
*/
|
||||
#define WINAPI_FAMILY_PC_APP 2 /* Windows Store Applications */
|
||||
#define WINAPI_FAMILY_PHONE_APP 3 /* Windows Phone Applications */
|
||||
#define WINAPI_FAMILY_SYSTEM 4 /* Windows Drivers and Tools */
|
||||
#define WINAPI_FAMILY_SERVER 5 /* Windows Server Applications */
|
||||
#define WINAPI_FAMILY_DESKTOP_APP 100 /* Windows Desktop Applications */
|
||||
/* The value of WINAPI_FAMILY_DESKTOP_APP may change in future SDKs. */
|
||||
/* Additional WINAPI_FAMILY values may be defined in future SDKs. */
|
||||
|
||||
/*
|
||||
* For compatibility with Windows 8 header files, the following
|
||||
* synonym for WINAPI_FAMILY_PC_APP is temporarily #define'd.
|
||||
* Use of this symbol should be considered deprecated.
|
||||
*/
|
||||
#define WINAPI_FAMILY_APP WINAPI_FAMILY_PC_APP
|
||||
|
||||
/*
|
||||
* If no WINAPI_FAMILY value is specified, then all APIs available to
|
||||
* Windows desktop applications are exposed.
|
||||
*/
|
||||
#ifndef WINAPI_FAMILY
|
||||
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* API PARTITONs are part of an indirection mechanism for mapping between
|
||||
* individual APIs and the FAMILYs to which they apply.
|
||||
* Each PARTITION is a category or subset of named APIs. PARTITIONs
|
||||
* are permitted to have overlapping membership -- some single API
|
||||
* might be part of more than one PARTITION. PARTITIONS are each #define-ed
|
||||
* to be either 1 or 0 or depending on the platform at which the app is targeted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The mapping between families and partitions is summarized here.
|
||||
* An X indicates that the given partition is active for the given
|
||||
* platform/family.
|
||||
*
|
||||
* +-------------------+---+
|
||||
* | *Partition* | |
|
||||
* +---+---+---+---+---+---+
|
||||
* | | | | | | |
|
||||
* | | | | | | |
|
||||
* | | | | P | | |
|
||||
* | | | | H | | |
|
||||
* | D | | | O | | |
|
||||
* | E | | P | N | S | S |
|
||||
* | S | | C | E | Y | E |
|
||||
* | K | | _ | _ | S | R |
|
||||
* | T | A | A | A | T | V |
|
||||
* +-------------------------+----+ O | P | P | P | E | E |
|
||||
* | *Platform/Family* \| P | P | P | P | M | R |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_DESKTOP_APP | X | X | X | | | |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_PC_APP | | X | X | | | |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_PHONE_APP | | X | | X | | |
|
||||
* +----------------------------- +---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_SYSTEM | | | | | X | |
|
||||
* +----------------------------- +---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_SERVER | | | | | X | X |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
*
|
||||
* The table above is encoded in the following expressions,
|
||||
* each of which evaluates to 1 or 0.
|
||||
*
|
||||
* Whenever a new family is added, all of these expressions
|
||||
* need to be reconsidered.
|
||||
*/
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_PC_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_SYSTEM && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_SERVER
|
||||
#error Unknown WINAPI_FAMILY value. Was it defined in terms of a WINAPI_PARTITION_* value?
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_DESKTOP
|
||||
#define WINAPI_PARTITION_DESKTOP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_APP
|
||||
#define WINAPI_PARTITION_APP \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_PC_APP
|
||||
#define WINAPI_PARTITION_PC_APP \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_PHONE_APP
|
||||
#define WINAPI_PARTITION_PHONE_APP (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SYSTEM is the only partition defined here.
|
||||
* All other System based editions are defined as packages
|
||||
* on top of the System partition.
|
||||
* See winpackagefamily.h for packages level partitions
|
||||
*/
|
||||
#ifndef WINAPI_PARTITION_SYSTEM
|
||||
#define WINAPI_PARTITION_SYSTEM \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_SYSTEM || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_SERVER)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For compatibility with Windows Phone 8 header files, the following
|
||||
* synonym for WINAPI_PARTITION_PHONE_APP is temporarily #define'd.
|
||||
* Use of this symbol should be regarded as deprecated.
|
||||
*/
|
||||
#define WINAPI_PARTITION_PHONE WINAPI_PARTITION_PHONE_APP
|
||||
|
||||
/*
|
||||
* Header files use the WINAPI_FAMILY_PARTITION macro to assign one or
|
||||
* more declarations to some group of partitions. The macro chooses
|
||||
* whether the preprocessor will emit or omit a sequence of declarations
|
||||
* bracketed by an #if/#endif pair. All header file references to the
|
||||
* WINAPI_PARTITION_* values should be in the form of occurrences of
|
||||
* WINAPI_FAMILY_PARTITION(...).
|
||||
*
|
||||
* For example, the following usage of WINAPI_FAMILY_PARTITION identifies
|
||||
* a sequence of declarations that are part of both the Windows Desktop
|
||||
* Partition and the Windows-Phone-Specific Store Partition:
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
|
||||
* ...
|
||||
* #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
|
||||
*
|
||||
* The comment on the closing #endif allow tools as well as people to find the
|
||||
* matching #ifdef properly.
|
||||
*
|
||||
* Usages of WINAPI_FAMILY_PARTITION may be combined, when the partitition definitions are
|
||||
* related. In particular one might use declarations like
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
*
|
||||
* or
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
*
|
||||
* Direct references to WINAPI_PARTITION_ values (eg #if !WINAPI_FAMILY_PARTITION_...)
|
||||
* should not be used.
|
||||
*/
|
||||
#define WINAPI_FAMILY_PARTITION(Partitions) (Partitions)
|
||||
|
||||
/*
|
||||
* Macro used to #define or typedef a symbol used for selective deprecation
|
||||
* of individual methods of a COM interfaces that are otherwise available
|
||||
* for a given set of partitions.
|
||||
*/
|
||||
#define _WINAPI_DEPRECATED_DECLARATION __declspec(deprecated("This API cannot be used in the context of the caller's application type."))
|
||||
|
||||
/*
|
||||
* For compatibility with Windows 8 header files, the following
|
||||
* symbol is temporarily conditionally #define'd. Additional symbols
|
||||
* like this should be not defined in winapifamily.h, but rather should be
|
||||
* introduced locally to the header files of the component that needs them.
|
||||
*/
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# define APP_DEPRECATED_HRESULT HRESULT _WINAPI_DEPRECATED_DECLARATION
|
||||
#endif // WINAPIFAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_WINAPIFAMILY */
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
winpackagefamily.h
|
||||
|
||||
Abstract:
|
||||
|
||||
API family partitioning based on packages.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_WINPACKAGEFAMILY
|
||||
#define _INC_WINPACKAGEFAMILY
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4001) /* nonstandard extension 'single line comment' was used */
|
||||
#endif
|
||||
#pragma once
|
||||
#endif // defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
|
||||
#ifndef WINAPI_PARTITION_SERVER
|
||||
#define WINAPI_PARTITION_SERVER (WINAPI_FAMILY == WINAPI_FAMILY_SERVER)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PARTITIONS based on packages are each #undef'ed below, and then will be #define-ed
|
||||
* to be either 1 or 0 or depending on the active WINAPI_FAMILY.
|
||||
*/
|
||||
#undef WINAPI_PARTITION_PKG_WINTRUST
|
||||
#undef WINAPI_PARTITION_PKG_WEBSERVICES
|
||||
#undef WINAPI_PARTITION_PKG_EVENTLOGSERVICE
|
||||
#undef WINAPI_PARTITION_PKG_VHD
|
||||
#undef WINAPI_PARTITION_PKG_PERFCOUNTER
|
||||
#undef WINAPI_PARTITION_PKG_SECURESTARTUP
|
||||
#undef WINAPI_PARTITION_PKG_REMOTEFS
|
||||
#undef WINAPI_PARTITION_PKG_BOOTABLESKU
|
||||
#undef WINAPI_PARTITION_PKG_CMDTOOLS
|
||||
#undef WINAPI_PARTITION_PKG_DISM
|
||||
#undef WINAPI_PARTITION_PKG_CORESETUP
|
||||
#undef WINAPI_PARTITION_PKG_APPRUNTIME
|
||||
#undef WINAPI_PARTITION_PKG_ESENT
|
||||
#undef WINAPI_PARTITION_PKG_WINMGMT
|
||||
#undef WINAPI_PARTITION_PKG_WNV
|
||||
#undef WINAPI_PARTITION_PKG_CLUSTER
|
||||
#undef WINAPI_PARTITION_PKG_VSS
|
||||
#undef WINAPI_PARTITION_PKG_TRAFFIC
|
||||
#undef WINAPI_PARTITION_PKG_ISCSI
|
||||
#undef WINAPI_PARTITION_PKG_STORAGE
|
||||
#undef WINAPI_PARTITION_PKG_MPSSVC
|
||||
#undef WINAPI_PARTITION_PKG_APPXDEPLOYMENT
|
||||
#undef WINAPI_PARTITION_PKG_WER
|
||||
|
||||
/*
|
||||
* PARTITIONS for feature packages. Each package might be active for one or more editions
|
||||
*/
|
||||
#define WINAPI_PARTITION_PKG_WINTRUST (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WEBSERVICES (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_EVENTLOGSERVICE (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_VHD (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_PERFCOUNTER (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_SECURESTARTUP (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_REMOTEFS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_BOOTABLESKU (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CMDTOOLS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_DISM (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CORESETUP (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_APPRUNTIME (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_ESENT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WINMGMT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WNV (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CLUSTER (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_VSS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_TRAFFIC (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_ISCSI (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_STORAGE (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_MPSSVC (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_APPXDEPLOYMENT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WER (WINAPI_PARTITION_SERVER == 1)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_WINPACKAGEFAMILY */
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
-1
Submodule 3rdparty/zlib deleted from cacf7f1d4e
+8
-27
@@ -1,11 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
option(WITH_GDB "WITH_GDB" OFF)
|
||||
option(WITHOUT_LLVM "WITHOUT_LLVM" OFF)
|
||||
|
||||
if (WITH_GDB)
|
||||
add_definitions(-DWITH_GDB_DEBUGGER)
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
set(ASMJIT_STATIC TRUE)
|
||||
|
||||
@@ -18,10 +11,12 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
|
||||
endif()
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if (CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
|
||||
message( FATAL_ERROR "RPCS3 requires at least gcc-5.1." )
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 6.1)
|
||||
message( FATAL_ERROR "RPCS3 can't be compiled with gcc-6.1, see #1691." )
|
||||
endif()
|
||||
|
||||
add_definitions(-DCMAKE_BUILD)
|
||||
@@ -40,20 +35,6 @@ option(VULKAN_PREBUILT "" OFF)
|
||||
# TODO: do real installation, including copying directory structure
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PROJECT_BINARY_DIR}/bin")
|
||||
|
||||
add_subdirectory( Vulkan )
|
||||
add_subdirectory( rpcs3 )
|
||||
|
||||
include_directories(3rdparty/hidapi/hidapi)
|
||||
if(APPLE)
|
||||
add_subdirectory(3rdparty/hidapi/mac)
|
||||
#list(APPEND LIBS hidapi)
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
add_subdirectory(3rdparty/hidapi/linux)
|
||||
elseif(MSVC)
|
||||
add_subdirectory(3rdparty/hidapi/windows)
|
||||
else()
|
||||
add_subdirectory(3rdparty/hidapi/libusb)
|
||||
#list(APPEND LIBS hidapi-libusb)
|
||||
endif()
|
||||
add_subdirectory( rsx_program_decompiler )
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
Before getting started using the emulator, read the [Quickstart Guide](https://rpcs3.net/quickstart) and the [FAQ](https://rpcs3.net/faq). After reading those, if you need support, visit our [Forums](https://forums.rpcs3.net).
|
||||
|
||||
# Issue Reporting
|
||||
|
||||
**The GitHub Issue Tracker is not the place to ask for support or to submit [Game Compatibility](https://rpcs3.net/compatibility) reports.** Requests for support or incorrect reports will be closed. If you are not sure whether the issue you want to report is an actual issue that is not yet known, please use the forums to submit such report.
|
||||
|
||||
**Before reporting an issue:**
|
||||
- Check if your system matches all the minimum requirements listed in the [Quickstart Guide](https://rpcs3.net/quickstart);
|
||||
- Check if the issue is meaningful for the team (e.g. The Last of Us doesn't work is obvious and therefore useless);
|
||||
- Search older issues/forum threads to see if your issue was already submitted.
|
||||
- Use understandable English. It doesn't need to be perfect, but clear enough to understand your message.
|
||||
- While reporting issues, don't forget to include details about your system (OS, CPU, GPU, etc.), as well as the RPCS3.log file.
|
||||
|
||||
Submitting your test results for Commercial Games must be done on our forums. Please read the [Game Compatibility](https://github.com/RPCS3/rpcs3/wiki/Game-Compatibility) wiki page before doing so.
|
||||
|
||||
# Contributing
|
||||
|
||||
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style), [Roadmap](https://github.com/RPCS3/rpcs3/wiki/Roadmap) 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.
|
||||
@@ -3,94 +3,68 @@ RPCS3
|
||||
|
||||
[](https://travis-ci.org/RPCS3/rpcs3)
|
||||
[](https://ci.appveyor.com/project/rpcs3/rpcs3/branch/master)
|
||||
[](https://scan.coverity.com/projects/3960)
|
||||
[](https://coveralls.io/r/RPCS3/rpcs3)
|
||||
|
||||
The world's first open-source PlayStation 3 emulator/debugger written in C++ for Windows and Linux.
|
||||
An open-source PlayStation 3 emulator/debugger written in C++.
|
||||
|
||||
You can find some basic information in our [**website**](https://rpcs3.net/).
|
||||
For discussion about this emulator and PS3 emulation please visit our [**forums**](https://forums.rpcs3.net) and our [**Discord server**](https://discord.me/RPCS3).
|
||||
You can find some basic information in the [FAQ](https://github.com/RPCS3/rpcs3/wiki/FAQ). For discussion about this emulator and PS3 emulation please visit the [official forums](http://www.emunewz.net/forum/forumdisplay.php?fid=162).
|
||||
|
||||
[**Support Lead Developers Nekotekina and kd-11 on Patreon**](https://www.patreon.com/Nekotekina)
|
||||
Official Discord server: https://discord.me/RPCS3
|
||||
|
||||
Support Nekotekina on Patreon: https://www.patreon.com/Nekotekina
|
||||
|
||||
### Development
|
||||
|
||||
If you want to contribute please take a look at the [Coding Style](https://github.com/RPCS3/rpcs3/wiki/Coding-Style), [Roadmap](https://github.com/RPCS3/rpcs3/wiki/Roadmap) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information) pages. You should as well contact any of the developers in the forum in order to know about the current situation of the emulator.
|
||||
|
||||
|
||||
## Development
|
||||
### Dependencies
|
||||
|
||||
If you want to contribute please take a look at the [Coding Style](https://github.com/RPCS3/rpcs3/wiki/Coding-Style), [Roadmap](https://github.com/RPCS3/rpcs3/wiki/Roadmap) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information) pages. You should as well contact any of the developers in the forums or in Discord in order to know more about the current situation of the emulator.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Windows
|
||||
* [Visual Studio 2017](https://www.visualstudio.com/en/downloads/)
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2017](https://go.microsoft.com/fwlink/?LinkId=746572)
|
||||
* [Cmake 3.1.0+](https://www.cmake.org/download/) (required; add to PATH)
|
||||
__Windows__
|
||||
* [Visual Studio 2015](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx)
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
||||
* [Cmake 3.1.0+](http://www.cmake.org/download/) (required; add to PATH)
|
||||
* [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
|
||||
* [Qt 5.9+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.9.1\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
|
||||
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
|
||||
|
||||
### Linux
|
||||
* [Qt 5.9+](https://www.qt.io/download-open-source/)
|
||||
__Linux__
|
||||
* GCC 5.1+ or Clang 3.5.0+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691))
|
||||
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git qt5-default`
|
||||
* Arch: `sudo pacman -S glew openal cmake llvm qt5-base`
|
||||
* Fedora: `sudo dnf install cmake qt5-devel vulkan-devel glew glew-devel`
|
||||
**If you have a NVIDIA GPU, you may need to install the libglvnd package.**
|
||||
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libopenal-dev libwxgtk3.0-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev git`
|
||||
* Arch: `sudo pacman -S glew openal wxgtk cmake llvm`
|
||||
|
||||
### MacOS
|
||||
MacOS is not supported at this moment because it doesn't meet system requirements (OpenGL 4.3)
|
||||
__Mac OSX__
|
||||
Mac OSX is not supported at this moment because it doesn't meet system requirements (OpenGL 4.3)
|
||||
* Xcode 6+ (tested with Xcode 6.4)
|
||||
* Install with Homebrew: `brew install glew llvm qt cmake`
|
||||
* Install with Homebrew: `brew install glew wxwidgets`
|
||||
* Remove '-framework QuickTime' from '_ldflags' in /usr/local/bin/wx-config
|
||||
|
||||
### Building
|
||||
|
||||
## Building on Windows:
|
||||
To initialize the repository don't forget to execute `git submodule update --init` to pull the submodules.
|
||||
|
||||
### Configuring Qt
|
||||
|
||||
*If you're using Visual Studio 2017 without Qt plugin support (or simply dont want to use it):*
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.9.1\msvc2017_64\` </br>
|
||||
|
||||
*If you wish to use the Visual Studio plugin for Qt:* </br>
|
||||
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.9.1\msvc2015_64`. </br>
|
||||
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
### Building the projects
|
||||
1) Build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*. </br>
|
||||
2) Press *BUILD* > *Build Solution* or *Rebuild Solution*. </br>
|
||||
|
||||
|
||||
## Building on Linux & Mac OS:
|
||||
- __Windows__: </br>
|
||||
1) To initialize the repository don't forget to execute `git submodule update --init` to pull the submodules. </br>
|
||||
2) Open the *.SLN* file. </br>
|
||||
3) Build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*. </br>
|
||||
4) Press *BUILD* > *Build Solution* or *Rebuild Solution*. </br>
|
||||
|
||||
- __Linux & Mac OSX__: </br>
|
||||
1) `git clone https://github.com/RPCS3/rpcs3.git` </br>
|
||||
2) `cd rpcs3/` </br>
|
||||
3) `git submodule update --init` </br>
|
||||
4) `cmake CMakeLists.txt && make GitVersion && make` </br>
|
||||
5) Run RPCS3 with `./bin/rpcs3` </br>
|
||||
|
||||
If you are on MacOS and want to build with brew llvm and qt don't forget to add the following environment variables
|
||||
|
||||
* `LLVM_DIR=/usr/local/opt/llvm/` (or wherever llvm was installed).
|
||||
* `Qt5_DIR=/usr/local/opt/qt/lib/cmake/Qt5` (or wherever qt was installed).
|
||||
If you are on OSX and want to build with llvm don't forget to add `-DLLVM_DIR=...` (or wherever llvm brew was installed) to cmake invocation.
|
||||
|
||||
When using GDB, configure it to ignore SIGSEGV signal (`handle SIGSEGV nostop noprint`).
|
||||
|
||||
##### CMake Build Options (Linux & Mac OSX)
|
||||
|
||||
## CMake Build Options (Linux & Mac OS)
|
||||
|
||||
- ```-DUSE_SYSTEM_LIBPNG=ON/OFF``` (default = *OFF*)
|
||||
- ```-DUSE_SYSTEM_LIBPNG=ON/OFF``` (default = *OFF*) </br>
|
||||
Build against the shared libpng instead of using the builtin one. libpng 1.6+ highly recommended. Try this option if you get version conflict errors or only see black game icons.
|
||||
|
||||
- ```-DUSE_SYSTEM_FFMPEG=ON/OFF``` (default = *OFF*)
|
||||
- ```-DUSE_SYSTEM_FFMPEG=ON/OFF``` (default = *OFF*) </br>
|
||||
Build against the shared ffmpeg libraries instead of using the builtin patched version. Try this if the builtin version breaks the OpenGL renderer for you.
|
||||
|
||||
- ```-DWITHOUT_LLVM=ON/OFF``` (default = *OFF*)
|
||||
This forces RPCS3 to build without LLVM, not recommended.
|
||||
|
||||
- ```-DWITH_GDB=ON/OFF``` (default = *OFF*)
|
||||
This Builds RPCS3 with support for debugging PS3 games using gdb.
|
||||
|
||||
- ```-DUSE_VULKAN=ON/OFF``` (default = *ON*)
|
||||
This builds RPCS3 with Vulkan support.
|
||||
|
||||
## License
|
||||
### License
|
||||
|
||||
Most files are licensed under the terms of GNU GPLv2 License, see LICENSE file for details. Some files may be licensed differently, check appropriate file headers for details.
|
||||
|
||||
+7
-13
@@ -300,24 +300,21 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
|
||||
static inline bool bts(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ushort _bit = (ushort)bit;
|
||||
__asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btsw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool btr(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ushort _bit = (ushort)bit;
|
||||
__asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btrw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool btc(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ushort _bit = (ushort)bit;
|
||||
__asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@@ -501,24 +498,21 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
|
||||
static inline bool bts(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ullong _bit = bit;
|
||||
__asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btsq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool btr(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ullong _bit = bit;
|
||||
__asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btrq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool btc(T& dest, uint bit)
|
||||
{
|
||||
bool result;
|
||||
ullong _bit = bit;
|
||||
__asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (_bit) : "cc");
|
||||
__asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@@ -536,7 +530,7 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
||||
|
||||
static inline T load(const T& dest)
|
||||
{
|
||||
llong result[2]{0, 0};
|
||||
llong result[2];
|
||||
_InterlockedCompareExchange128((volatile llong*)&dest, 0, 0, result);
|
||||
return *(T*)+result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "AutoPause.h"
|
||||
|
||||
cfg::bool_entry g_cfg_debug_autopause_syscall(cfg::root.misc, "Automatically pause at system call");
|
||||
cfg::bool_entry g_cfg_debug_autopause_func_call(cfg::root.misc, "Automatically pause at function call");
|
||||
|
||||
debug::autopause& debug::autopause::get_instance()
|
||||
{
|
||||
// Use magic static
|
||||
static autopause instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Load Auto Pause Configuration from file "pause.bin"
|
||||
void debug::autopause::reload(void)
|
||||
{
|
||||
auto& instance = get_instance();
|
||||
|
||||
instance.m_pause_function.clear();
|
||||
instance.m_pause_syscall.clear();
|
||||
|
||||
// TODO: better format, possibly a config entry
|
||||
if (fs::file list{ fs::get_config_dir() + "pause.bin" })
|
||||
{
|
||||
u32 num;
|
||||
size_t fmax = list.size();
|
||||
size_t fcur = 0;
|
||||
list.seek(0);
|
||||
while (fcur <= fmax - sizeof(u32))
|
||||
{
|
||||
list.read(&num, sizeof(u32));
|
||||
fcur += sizeof(u32);
|
||||
if (num == 0xFFFFFFFF) break;
|
||||
|
||||
if (num < 1024)
|
||||
{
|
||||
instance.m_pause_syscall.emplace(num);
|
||||
LOG_WARNING(HLE, "Set autopause at syscall %lld", num);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance.m_pause_function.emplace(num);
|
||||
LOG_WARNING(HLE, "Set autopause at function 0x%08x", num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool debug::autopause::pause_syscall(u64 code)
|
||||
{
|
||||
if (g_cfg_debug_autopause_syscall && get_instance().m_pause_syscall.count(code) != 0)
|
||||
{
|
||||
Emu.Pause();
|
||||
LOG_SUCCESS(HLE, "Autopause triggered at syscall %lld", code);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool debug::autopause::pause_function(u32 code)
|
||||
{
|
||||
if (g_cfg_debug_autopause_func_call && get_instance().m_pause_function.count(code) != 0)
|
||||
{
|
||||
Emu.Pause();
|
||||
LOG_SUCCESS(HLE, "Autopause triggered at function 0x%08x", code);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
// Regarded as a Debugger Enchantment
|
||||
namespace debug
|
||||
{
|
||||
// To store the pause function/call id, and let those pause there.
|
||||
// Would be with a GUI to configure those.
|
||||
class autopause
|
||||
{
|
||||
std::unordered_set<u64> m_pause_syscall;
|
||||
std::unordered_set<u32> m_pause_function;
|
||||
|
||||
static autopause& get_instance();
|
||||
public:
|
||||
|
||||
static void reload();
|
||||
static bool pause_syscall(u64 code);
|
||||
static bool pause_function(u32 code);
|
||||
};
|
||||
}
|
||||
@@ -301,16 +301,6 @@ union alignas(16) v128
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N, std::size_t M>
|
||||
struct offset32_array<v128::masked_array_t<T, N, M>>
|
||||
{
|
||||
template <typename Arg>
|
||||
static inline u32 index32(const Arg& arg)
|
||||
{
|
||||
return SIZE_32(T) * (static_cast<u32>(arg) ^ static_cast<u32>(M));
|
||||
}
|
||||
};
|
||||
|
||||
inline v128 operator|(const v128& left, const v128& right)
|
||||
{
|
||||
return v128::fromV(_mm_or_si128(left.vi, right.vi));
|
||||
|
||||
+18
-24
@@ -7,7 +7,6 @@ struct bf_base
|
||||
{
|
||||
using type = T;
|
||||
using vtype = simple_t<type>;
|
||||
using utype = typename std::make_unsigned<vtype>::type;
|
||||
|
||||
// Datatype bitsize
|
||||
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
|
||||
@@ -16,10 +15,7 @@ struct bf_base
|
||||
static constexpr uint bitsize = N;
|
||||
|
||||
// Value mask
|
||||
static constexpr utype vmask = static_cast<utype>(~utype{} >> (bitmax - bitsize));
|
||||
|
||||
// All ones mask
|
||||
static constexpr utype mask1 = static_cast<utype>(~utype{});
|
||||
static constexpr vtype vmask = static_cast<vtype>(~std::make_unsigned_t<vtype>{} >> (bitmax - bitsize));
|
||||
|
||||
protected:
|
||||
type m_data;
|
||||
@@ -31,15 +27,14 @@ struct bf_t : bf_base<T, N>
|
||||
{
|
||||
using type = typename bf_t::type;
|
||||
using vtype = typename bf_t::vtype;
|
||||
using utype = typename bf_t::utype;
|
||||
|
||||
// Field offset
|
||||
static constexpr uint bitpos = I; static_assert(bitpos + N <= bf_t::bitmax, "bf_t<> error: I out of bounds");
|
||||
|
||||
// Get bitmask of size N, at I pos
|
||||
static constexpr utype data_mask()
|
||||
static constexpr vtype data_mask()
|
||||
{
|
||||
return static_cast<utype>(static_cast<utype>(bf_t::mask1 >> (bf_t::bitmax - bf_t::bitsize)) << bitpos);
|
||||
return bf_t::vmask << bitpos;
|
||||
}
|
||||
|
||||
// Bitfield extraction helper
|
||||
@@ -55,7 +50,7 @@ struct bf_t : bf_base<T, N>
|
||||
// Load unsigned value
|
||||
static constexpr T2 extract(const T& data)
|
||||
{
|
||||
return static_cast<T2>((static_cast<utype>(data) >> bitpos) & bf_t::vmask);
|
||||
return (data >> bitpos) & bf_t::vmask;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,7 +60,7 @@ struct bf_t : bf_base<T, N>
|
||||
// Load signed value (sign-extended)
|
||||
static constexpr T2 extract(const T& data)
|
||||
{
|
||||
return static_cast<T2>(static_cast<vtype>(static_cast<utype>(data) << (bf_t::bitmax - bitpos - N)) >> (bf_t::bitmax - N));
|
||||
return data << (bf_t::bitmax - bitpos - N) >> (bf_t::bitmax - N);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,7 +73,7 @@ struct bf_t : bf_base<T, N>
|
||||
// Bitfield insertion
|
||||
static constexpr vtype insert(vtype value)
|
||||
{
|
||||
return static_cast<vtype>((value & bf_t::vmask) << bitpos);
|
||||
return (value & bf_t::vmask) << bitpos;
|
||||
}
|
||||
|
||||
// Load bitfield value
|
||||
@@ -90,7 +85,7 @@ struct bf_t : bf_base<T, N>
|
||||
// Load raw data with mask applied
|
||||
constexpr T unshifted() const
|
||||
{
|
||||
return static_cast<T>(this->m_data & data_mask());
|
||||
return this->m_data & data_mask();
|
||||
}
|
||||
|
||||
// Optimized bool conversion (must be removed if inappropriate)
|
||||
@@ -102,14 +97,14 @@ struct bf_t : bf_base<T, N>
|
||||
// Store bitfield value
|
||||
bf_t& operator =(vtype value)
|
||||
{
|
||||
this->m_data = static_cast<vtype>((this->m_data & ~data_mask()) | insert(value));
|
||||
this->m_data = (this->m_data & ~data_mask()) | insert(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
vtype operator ++(int)
|
||||
{
|
||||
utype result = *this;
|
||||
*this = static_cast<vtype>(result + 1);
|
||||
vtype result = *this;
|
||||
*this = result + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -120,8 +115,8 @@ struct bf_t : bf_base<T, N>
|
||||
|
||||
vtype operator --(int)
|
||||
{
|
||||
utype result = *this;
|
||||
*this = static_cast<vtype>(result - 1);
|
||||
vtype result = *this;
|
||||
*this = result - 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -147,19 +142,19 @@ struct bf_t : bf_base<T, N>
|
||||
|
||||
bf_t& operator &=(vtype right)
|
||||
{
|
||||
this->m_data &= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
|
||||
this->m_data &= (right & bf_t::vmask) << bitpos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bf_t& operator |=(vtype right)
|
||||
{
|
||||
this->m_data |= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
|
||||
this->m_data |= (right & bf_t::vmask) << bitpos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bf_t& operator ^=(vtype right)
|
||||
{
|
||||
this->m_data ^= static_cast<vtype>((static_cast<utype>(right) & bf_t::vmask) << bitpos);
|
||||
this->m_data ^= (right & bf_t::vmask) << bitpos;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
@@ -170,24 +165,23 @@ struct cf_t : bf_base<typename F::type, F::bitsize + cf_t<Fields...>::bitsize>
|
||||
{
|
||||
using type = typename cf_t::type;
|
||||
using vtype = typename cf_t::vtype;
|
||||
using utype = typename cf_t::utype;
|
||||
|
||||
// Get disjunction of all "data" masks of concatenated values
|
||||
static constexpr vtype data_mask()
|
||||
{
|
||||
return static_cast<vtype>(F::data_mask() | cf_t<Fields...>::data_mask());
|
||||
return F::data_mask() | cf_t<Fields...>::data_mask();
|
||||
}
|
||||
|
||||
// Extract all bitfields and concatenate
|
||||
static constexpr vtype extract(const type& data)
|
||||
{
|
||||
return static_cast<vtype>(static_cast<utype>(F::extract(data)) << cf_t<Fields...>::bitsize | cf_t<Fields...>::extract(data));
|
||||
return F::extract(data) << cf_t<Fields...>::bitsize | cf_t<Fields...>::extract(data);
|
||||
}
|
||||
|
||||
// Split bitfields and insert them
|
||||
static constexpr vtype insert(vtype value)
|
||||
{
|
||||
return static_cast<vtype>(F::insert(value >> cf_t<Fields...>::bitsize) | cf_t<Fields...>::insert(value));
|
||||
return F::insert(value >> cf_t<Fields...>::bitsize) | cf_t<Fields...>::insert(value);
|
||||
}
|
||||
|
||||
// Load value
|
||||
|
||||
-1702
File diff suppressed because it is too large
Load Diff
+49
-120
@@ -3,13 +3,11 @@
|
||||
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace cfg
|
||||
{
|
||||
logs::channel cfg("CFG");
|
||||
logs::channel cfg("CFG", logs::level::notice);
|
||||
|
||||
_base::_base(type _type)
|
||||
entry_base::entry_base(type _type)
|
||||
: m_type(_type)
|
||||
{
|
||||
if (_type != type::node)
|
||||
@@ -18,41 +16,51 @@ namespace cfg
|
||||
}
|
||||
}
|
||||
|
||||
_base::_base(type _type, node* owner, const std::string& name)
|
||||
entry_base::entry_base(type _type, node& owner, const std::string& name)
|
||||
: m_type(_type)
|
||||
{
|
||||
for (const auto& pair : owner->m_nodes)
|
||||
if (!owner.m_nodes.emplace(name, this).second)
|
||||
{
|
||||
if (pair.first == name)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Node already exists: %s" HERE, name);
|
||||
}
|
||||
fmt::throw_exception<std::logic_error>("Node already exists: %s" HERE, name);
|
||||
}
|
||||
|
||||
owner->m_nodes.emplace_back(name, this);
|
||||
}
|
||||
|
||||
bool _base::from_string(const std::string&)
|
||||
entry_base& entry_base::operator[](const std::string& name) const
|
||||
{
|
||||
if (m_type == type::node)
|
||||
{
|
||||
return *static_cast<const node&>(*this).m_nodes.at(name);
|
||||
}
|
||||
|
||||
fmt::throw_exception<std::logic_error>("Invalid node type" HERE);
|
||||
}
|
||||
|
||||
entry_base& entry_base::operator[](const char* name) const
|
||||
{
|
||||
if (m_type == type::node)
|
||||
{
|
||||
return *static_cast<const node&>(*this).m_nodes.at(name);
|
||||
}
|
||||
|
||||
fmt::throw_exception<std::logic_error>("Invalid node type" HERE);
|
||||
}
|
||||
|
||||
bool entry_base::from_string(const std::string&)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("from_string() purecall" HERE);
|
||||
}
|
||||
|
||||
bool _base::from_list(std::vector<std::string>&&)
|
||||
bool entry_base::from_list(std::vector<std::string>&&)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("from_list() purecall" HERE);
|
||||
}
|
||||
|
||||
// Emit YAML
|
||||
static void encode(YAML::Emitter& out, const class _base& rhs);
|
||||
static void encode(YAML::Emitter& out, const class entry_base& rhs);
|
||||
|
||||
// Incrementally load config entries from YAML::Node.
|
||||
// The config value is preserved if the corresponding YAML node doesn't exist.
|
||||
static void decode(const YAML::Node& data, class _base& rhs);
|
||||
}
|
||||
|
||||
std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
|
||||
{
|
||||
return {std::to_string(min), std::to_string(max)};
|
||||
static void decode(const YAML::Node& data, class entry_base& rhs);
|
||||
}
|
||||
|
||||
bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
||||
@@ -89,8 +97,6 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
||||
|
||||
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string& value)
|
||||
{
|
||||
u64 max = -1;
|
||||
|
||||
for (u64 i = 0;; i++)
|
||||
{
|
||||
std::string var;
|
||||
@@ -108,33 +114,17 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
max = i;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::size_t pos;
|
||||
const auto val = std::stoull(value, &pos, 0);
|
||||
|
||||
if (pos != value.size())
|
||||
{
|
||||
if (out) cfg.error("cfg::try_to_enum_value('%s'): unexpected characters (pos=%zu)", value, pos);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (val > max)
|
||||
{
|
||||
if (out) cfg.error("cfg::try_to_enum_value('%s'): out of bounds(0..%u)", value, max);
|
||||
return false;
|
||||
}
|
||||
const auto val = std::stoull(value, nullptr, 0);
|
||||
|
||||
if (out) *out = val;
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
catch (...)
|
||||
{
|
||||
if (out) cfg.error("cfg::try_to_enum_value('%s'): invalid enum value: %s", value, e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -161,7 +151,7 @@ std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::
|
||||
return result;
|
||||
}
|
||||
|
||||
void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
||||
void cfg::encode(YAML::Emitter& out, const cfg::entry_base& rhs)
|
||||
{
|
||||
switch (rhs.get_type())
|
||||
{
|
||||
@@ -171,8 +161,7 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
||||
for (const auto& np : static_cast<const node&>(rhs).get_nodes())
|
||||
{
|
||||
out << YAML::Key << np.first;
|
||||
out << YAML::Value;
|
||||
encode(out, *np.second);
|
||||
out << YAML::Value; encode(out, *np.second);
|
||||
}
|
||||
|
||||
out << YAML::EndMap;
|
||||
@@ -189,25 +178,12 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
||||
out << YAML::EndSeq;
|
||||
return;
|
||||
}
|
||||
case type::log:
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
for (const auto& np : static_cast<const log_entry&>(rhs).get_map())
|
||||
{
|
||||
if (np.second == logs::level::notice) continue;
|
||||
out << YAML::Key << np.first;
|
||||
out << YAML::Value << fmt::format("%s", np.second);
|
||||
}
|
||||
|
||||
out << YAML::EndMap;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out << rhs.to_string();
|
||||
}
|
||||
|
||||
void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
|
||||
void cfg::decode(const YAML::Node& data, cfg::entry_base& rhs)
|
||||
{
|
||||
switch (rhs.get_type())
|
||||
{
|
||||
@@ -223,12 +199,16 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
|
||||
if (!pair.first.IsScalar()) continue;
|
||||
|
||||
// Find the key among existing nodes
|
||||
for (const auto& _pair : static_cast<node&>(rhs).get_nodes())
|
||||
const auto name = pair.first.Scalar();
|
||||
const auto found = static_cast<node&>(rhs).get_nodes().find(name);
|
||||
|
||||
if (found != static_cast<node&>(rhs).get_nodes().cend())
|
||||
{
|
||||
if (_pair.first == pair.first.Scalar())
|
||||
{
|
||||
decode(pair.second, *_pair.second);
|
||||
}
|
||||
decode(pair.second, *found->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,29 +225,6 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
|
||||
|
||||
break;
|
||||
}
|
||||
case type::log:
|
||||
{
|
||||
if (data.IsScalar() || data.IsSequence())
|
||||
{
|
||||
return; // ???
|
||||
}
|
||||
|
||||
std::map<std::string, logs::level> values;
|
||||
|
||||
for (const auto& pair : data)
|
||||
{
|
||||
if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue;
|
||||
|
||||
u64 value;
|
||||
if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar()))
|
||||
{
|
||||
values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value)));
|
||||
}
|
||||
}
|
||||
|
||||
static_cast<log_entry&>(rhs).set_map(std::move(values));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
std::string value;
|
||||
@@ -287,19 +244,14 @@ std::string cfg::node::to_string() const
|
||||
YAML::Emitter out;
|
||||
cfg::encode(out, *this);
|
||||
|
||||
return {out.c_str(), out.size()};
|
||||
return{ out.c_str(), out.size() };
|
||||
}
|
||||
|
||||
bool cfg::node::from_string(const std::string& value) try
|
||||
bool cfg::node::from_string(const std::string& value)
|
||||
{
|
||||
cfg::decode(YAML::Load(value), *this);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
cfg.fatal("%s thrown: %s", typeid(e).name(), e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
void cfg::node::from_default()
|
||||
{
|
||||
@@ -309,32 +261,9 @@ void cfg::node::from_default()
|
||||
}
|
||||
}
|
||||
|
||||
void cfg::_bool::from_default()
|
||||
cfg::root_node& cfg::get_root()
|
||||
{
|
||||
m_value = def;
|
||||
}
|
||||
|
||||
void cfg::string::from_default()
|
||||
{
|
||||
m_value = def;
|
||||
}
|
||||
|
||||
void cfg::set_entry::from_default()
|
||||
{
|
||||
m_set = {};
|
||||
}
|
||||
|
||||
void cfg::log_entry::set_map(std::map<std::string, logs::level>&& map)
|
||||
{
|
||||
logs::reset();
|
||||
|
||||
for (auto&& pair : (m_map = std::move(map)))
|
||||
{
|
||||
logs::set_level(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
void cfg::log_entry::from_default()
|
||||
{
|
||||
set_map({});
|
||||
// Magic static
|
||||
static root_node root;
|
||||
return root;
|
||||
}
|
||||
|
||||
+233
-81
@@ -1,20 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/Atomic.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Utilities/Log.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace cfg
|
||||
{
|
||||
// Format min and max values
|
||||
std::vector<std::string> make_int_range(s64 min, s64 max);
|
||||
|
||||
// Convert string to signed integer
|
||||
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max);
|
||||
|
||||
@@ -28,33 +29,36 @@ namespace cfg
|
||||
enum class type : uint
|
||||
{
|
||||
node = 0, // cfg::node type
|
||||
_bool, // cfg::_bool type
|
||||
_enum, // cfg::_enum type
|
||||
_int, // cfg::_int type
|
||||
string, // cfg::string type
|
||||
boolean, // cfg::bool_entry type
|
||||
fixed_map, // cfg::map_entry type
|
||||
enumeration, // cfg::enum_entry type
|
||||
integer, // cfg::int_entry type
|
||||
string, // cfg::string_entry type
|
||||
set, // cfg::set_entry type
|
||||
log,
|
||||
};
|
||||
|
||||
// Config tree entry abstract base class
|
||||
class _base
|
||||
class entry_base
|
||||
{
|
||||
const type m_type;
|
||||
|
||||
protected:
|
||||
// Ownerless entry constructor
|
||||
_base(type _type);
|
||||
entry_base(type _type);
|
||||
|
||||
// Owned entry constructor
|
||||
_base(type _type, class node* owner, const std::string& name);
|
||||
entry_base(type _type, class node& owner, const std::string& name);
|
||||
|
||||
public:
|
||||
// Disallow copy/move constructors and assignments
|
||||
_base(const _base&) = delete;
|
||||
entry_base(const entry_base&) = delete;
|
||||
|
||||
// Get type
|
||||
type get_type() const { return m_type; }
|
||||
|
||||
// Access child node (must exist)
|
||||
entry_base& operator [](const std::string& name) const; entry_base& operator [](const char* name) const;
|
||||
|
||||
// Reset defaults
|
||||
virtual void from_default() = 0;
|
||||
|
||||
@@ -78,27 +82,27 @@ namespace cfg
|
||||
};
|
||||
|
||||
// Config tree node which contains another nodes
|
||||
class node : public _base
|
||||
class node : public entry_base
|
||||
{
|
||||
std::vector<std::pair<std::string, _base*>> m_nodes;
|
||||
std::map<std::string, entry_base*> m_nodes;
|
||||
|
||||
friend class _base;
|
||||
friend class entry_base;
|
||||
|
||||
public:
|
||||
// Root node constructor
|
||||
node()
|
||||
: _base(type::node)
|
||||
: entry_base(type::node)
|
||||
{
|
||||
}
|
||||
|
||||
// Registered node constructor
|
||||
node(node* owner, const std::string& name)
|
||||
: _base(type::node, owner, name)
|
||||
node(node& owner, const std::string& name)
|
||||
: entry_base(type::node, owner, name)
|
||||
{
|
||||
}
|
||||
|
||||
// Get child nodes
|
||||
const auto& get_nodes() const
|
||||
const std::map<std::string, entry_base*>& get_nodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
@@ -113,38 +117,46 @@ namespace cfg
|
||||
void from_default() override;
|
||||
};
|
||||
|
||||
class _bool final : public _base
|
||||
struct bool_entry final : public entry_base
|
||||
{
|
||||
bool m_value;
|
||||
atomic_t<bool> value;
|
||||
|
||||
public:
|
||||
const bool def;
|
||||
|
||||
_bool(node* owner, const std::string& name, bool def = false)
|
||||
: _base(type::_bool, owner, name)
|
||||
, m_value(def)
|
||||
bool_entry(node& owner, const std::string& name, bool def = false)
|
||||
: entry_base(type::boolean, owner, name)
|
||||
, value(def)
|
||||
, def(def)
|
||||
{
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return m_value;
|
||||
return value.load();
|
||||
}
|
||||
|
||||
void from_default() override;
|
||||
bool_entry& operator =(bool value)
|
||||
{
|
||||
value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void from_default() override
|
||||
{
|
||||
value = def;
|
||||
}
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
return m_value ? "true" : "false";
|
||||
return value.load() ? "true" : "false";
|
||||
}
|
||||
|
||||
bool from_string(const std::string& value) override
|
||||
{
|
||||
if (value == "false")
|
||||
m_value = false;
|
||||
this->value = false;
|
||||
else if (value == "true")
|
||||
m_value = true;
|
||||
this->value = true;
|
||||
else
|
||||
return false;
|
||||
|
||||
@@ -152,17 +164,116 @@ namespace cfg
|
||||
}
|
||||
};
|
||||
|
||||
// Value node with fixed set of possible values, each maps to an enum value of type T.
|
||||
template <typename T>
|
||||
class _enum final : public _base
|
||||
// Value node with fixed set of possible values, each maps to a value of type T.
|
||||
template<typename T>
|
||||
struct map_entry final : public entry_base
|
||||
{
|
||||
T m_value;
|
||||
using init_type = std::initializer_list<std::pair<std::string, T>>;
|
||||
using map_type = std::unordered_map<std::string, T>;
|
||||
using list_type = std::vector<std::string>;
|
||||
using value_type = typename map_type::value_type;
|
||||
|
||||
static map_type make_map(init_type init)
|
||||
{
|
||||
map_type map(init.size());
|
||||
|
||||
for (const auto& v : init)
|
||||
{
|
||||
// Ensure elements are unique
|
||||
verify(HERE), map.emplace(v.first, v.second).second;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static list_type make_list(init_type init)
|
||||
{
|
||||
list_type list; list.reserve(init.size());
|
||||
|
||||
for (const auto& v : init)
|
||||
{
|
||||
list.emplace_back(v.first);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public:
|
||||
const map_type map;
|
||||
const list_type list; // Element list sorted in original order
|
||||
const value_type& def; // Pointer to the default value
|
||||
|
||||
private:
|
||||
atomic_t<const value_type*> m_value;
|
||||
|
||||
public:
|
||||
map_entry(node& owner, const std::string& name, const std::string& def, init_type init)
|
||||
: entry_base(type::fixed_map, owner, name)
|
||||
, map(make_map(init))
|
||||
, list(make_list(init))
|
||||
, def(*map.find(def))
|
||||
, m_value(&this->def)
|
||||
{
|
||||
}
|
||||
|
||||
map_entry(node& owner, const std::string& name, std::size_t def_index, init_type init)
|
||||
: map_entry(owner, name, (init.begin() + (def_index < init.size() ? def_index : 0))->first, init)
|
||||
{
|
||||
}
|
||||
|
||||
map_entry(node& owner, const std::string& name, init_type init)
|
||||
: map_entry(owner, name, 0, init)
|
||||
{
|
||||
}
|
||||
|
||||
const T& get() const
|
||||
{
|
||||
return m_value.load()->second;
|
||||
}
|
||||
|
||||
void from_default() override
|
||||
{
|
||||
m_value = &def;
|
||||
}
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
return m_value.load()->first;
|
||||
}
|
||||
|
||||
bool from_string(const std::string& value) override
|
||||
{
|
||||
const auto found = map.find(value);
|
||||
|
||||
if (found == map.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value = &*found;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
// Value node with fixed set of possible values, each maps to an enum value of type T.
|
||||
template<typename T, bool External = false>
|
||||
class enum_entry final : public entry_base
|
||||
{
|
||||
// Value or reference
|
||||
std::conditional_t<External, atomic_t<T>&, atomic_t<T>> m_value;
|
||||
|
||||
public:
|
||||
const T def;
|
||||
|
||||
_enum(node* owner, const std::string& name, T value = {})
|
||||
: _base(type::_enum, owner, name)
|
||||
enum_entry(node& owner, const std::string& name, std::conditional_t<External, atomic_t<T>&, T> value)
|
||||
: entry_base(type::enumeration, owner, name)
|
||||
, m_value(value)
|
||||
, def(value)
|
||||
{
|
||||
@@ -170,7 +281,13 @@ namespace cfg
|
||||
|
||||
operator T() const
|
||||
{
|
||||
return m_value;
|
||||
return m_value.load();
|
||||
}
|
||||
|
||||
enum_entry& operator =(T value)
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void from_default() override
|
||||
@@ -206,21 +323,21 @@ namespace cfg
|
||||
};
|
||||
|
||||
// Signed 32/64-bit integer entry with custom Min/Max range.
|
||||
template <s64 Min, s64 Max>
|
||||
class _int final : public _base
|
||||
template<s64 Min, s64 Max>
|
||||
class int_entry final : public entry_base
|
||||
{
|
||||
static_assert(Min < Max, "Invalid cfg::_int range");
|
||||
static_assert(Min < Max, "Invalid cfg::int_entry range");
|
||||
|
||||
// Prefer 32 bit type if possible
|
||||
using int_type = std::conditional_t<Min >= INT32_MIN && Max <= INT32_MAX, s32, s64>;
|
||||
|
||||
int_type m_value;
|
||||
atomic_t<int_type> m_value;
|
||||
|
||||
public:
|
||||
const int_type def;
|
||||
|
||||
_int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)))
|
||||
: _base(type::_int, owner, name)
|
||||
int_entry(node& owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)))
|
||||
: entry_base(type::integer, owner, name)
|
||||
, m_value(def)
|
||||
, def(def)
|
||||
{
|
||||
@@ -228,7 +345,18 @@ namespace cfg
|
||||
|
||||
operator int_type() const
|
||||
{
|
||||
return m_value;
|
||||
return m_value.load();
|
||||
}
|
||||
|
||||
int_entry& operator =(int_type value)
|
||||
{
|
||||
if (value < Min || value > Max)
|
||||
{
|
||||
fmt::throw_exception("Value out of the valid range: %lld" HERE, s64{ value });
|
||||
}
|
||||
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void from_default() override
|
||||
@@ -238,7 +366,7 @@ namespace cfg
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
return std::to_string(m_value);
|
||||
return std::to_string(m_value.load());
|
||||
}
|
||||
|
||||
bool from_string(const std::string& value) override
|
||||
@@ -252,29 +380,25 @@ namespace cfg
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
return make_int_range(Min, Max);
|
||||
}
|
||||
};
|
||||
|
||||
// Alias for 32 bit int
|
||||
using int32 = _int<INT32_MIN, INT32_MAX>;
|
||||
using int32_entry = int_entry<INT32_MIN, INT32_MAX>;
|
||||
|
||||
// Alias for 64 bit int
|
||||
using int64 = _int<INT64_MIN, INT64_MAX>;
|
||||
using int64_entry = int_entry<INT64_MIN, INT64_MAX>;
|
||||
|
||||
// Simple string entry with mutex
|
||||
class string final : public _base
|
||||
class string_entry final : public entry_base
|
||||
{
|
||||
mutable std::mutex m_mutex;
|
||||
std::string m_value;
|
||||
|
||||
public:
|
||||
const std::string def;
|
||||
|
||||
string(node* owner, const std::string& name, const std::string& def = {})
|
||||
: _base(type::string, owner, name)
|
||||
string_entry(node& owner, const std::string& name, const std::string& def = {})
|
||||
: entry_base(type::string, owner, name)
|
||||
, m_value(def)
|
||||
, def(def)
|
||||
{
|
||||
@@ -282,87 +406,115 @@ namespace cfg
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const std::string& get() const
|
||||
std::string get() const
|
||||
{
|
||||
return m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string_entry& operator =(const std::string& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_value.size();
|
||||
}
|
||||
|
||||
void from_default() override;
|
||||
void from_default() override
|
||||
{
|
||||
*this = def;
|
||||
}
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool from_string(const std::string& value) override
|
||||
{
|
||||
m_value = value;
|
||||
*this = value;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Simple set entry with mutex (TODO: template for various types)
|
||||
class set_entry final : public _base
|
||||
class set_entry final : public entry_base
|
||||
{
|
||||
mutable std::mutex m_mutex;
|
||||
|
||||
std::set<std::string> m_set;
|
||||
|
||||
public:
|
||||
// Default value is empty list in current implementation
|
||||
set_entry(node* owner, const std::string& name)
|
||||
: _base(type::set, owner, name)
|
||||
set_entry(node& owner, const std::string& name)
|
||||
: entry_base(type::set, owner, name)
|
||||
{
|
||||
}
|
||||
|
||||
std::set<std::string> get_set() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
return m_set;
|
||||
}
|
||||
|
||||
void set_set(std::set<std::string>&& set)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_set = std::move(set);
|
||||
}
|
||||
|
||||
void from_default() override;
|
||||
void from_default() override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_set = {};
|
||||
}
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
return{ m_set.begin(), m_set.end() };
|
||||
}
|
||||
|
||||
bool from_list(std::vector<std::string>&& list) override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_set = { std::make_move_iterator(list.begin()), std::make_move_iterator(list.end()) };
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class log_entry final : public _base
|
||||
// Root type with some predefined nodes. Don't change it, this is not mandatory for adding nodes.
|
||||
struct root_node : node
|
||||
{
|
||||
std::map<std::string, logs::level> m_map;
|
||||
|
||||
public:
|
||||
log_entry(node* owner, const std::string& name)
|
||||
: _base(type::log, owner, name)
|
||||
{
|
||||
}
|
||||
|
||||
std::map<std::string, logs::level> get_map() const
|
||||
{
|
||||
return m_map;
|
||||
}
|
||||
|
||||
void set_map(std::map<std::string, logs::level>&& map);
|
||||
|
||||
void from_default() override;
|
||||
node core { *this, "Core" };
|
||||
node vfs { *this, "VFS" };
|
||||
node log { *this, "Log" };
|
||||
node video { *this, "Video" };
|
||||
node audio { *this, "Audio" };
|
||||
node io { *this, "Input/Output" };
|
||||
node sys { *this, "System" };
|
||||
node net { *this, "Net" };
|
||||
node misc { *this, "Miscellaneous" };
|
||||
};
|
||||
|
||||
// Get global configuration root instance
|
||||
extern root_node& get_root();
|
||||
|
||||
// Global configuration root instance (cached reference)
|
||||
static root_node& root = get_root();
|
||||
}
|
||||
|
||||
// Registered log channel
|
||||
#define LOG_CHANNEL(name) extern logs::channel name; namespace logs { static cfg::enum_entry<logs::level, true> name(cfg::root.log, #name, ::name.enabled); }
|
||||
|
||||
+111
-282
@@ -1,16 +1,12 @@
|
||||
#include "File.h"
|
||||
#include "mutex.h"
|
||||
#include "StrFmt.h"
|
||||
#include "SharedMutex.h"
|
||||
#include "BEType.h"
|
||||
#include "Crypto/sha1.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <typeinfo>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -73,29 +69,17 @@ static time_t to_time(const FILETIME& ft)
|
||||
return to_time(v);
|
||||
}
|
||||
|
||||
static FILETIME from_time(s64 _time)
|
||||
{
|
||||
const ullong wtime = (_time + 11644473600ULL) * 10000000ULL;
|
||||
FILETIME result;
|
||||
result.dwLowDateTime = static_cast<DWORD>(wtime);
|
||||
result.dwHighDateTime = static_cast<DWORD>(wtime >> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
static fs::error to_error(DWORD e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND: return fs::error::noent;
|
||||
case ERROR_PATH_NOT_FOUND: return fs::error::noent;
|
||||
case ERROR_ACCESS_DENIED: return fs::error::acces;
|
||||
case ERROR_ALREADY_EXISTS: return fs::error::exist;
|
||||
case ERROR_FILE_EXISTS: return fs::error::exist;
|
||||
case ERROR_NEGATIVE_SEEK: return fs::error::inval;
|
||||
case ERROR_DIRECTORY: return fs::error::inval;
|
||||
case ERROR_INVALID_NAME: return fs::error::inval;
|
||||
case ERROR_SHARING_VIOLATION: return fs::error::acces;
|
||||
case ERROR_DIR_NOT_EMPTY: return fs::error::notempty;
|
||||
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
@@ -105,20 +89,16 @@ static fs::error to_error(DWORD e)
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <copyfile.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
#include <sys/socket.h> // sendfile
|
||||
#elif defined(__linux__) || defined(__sun)
|
||||
#else
|
||||
#include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
@@ -129,8 +109,6 @@ static fs::error to_error(int e)
|
||||
case ENOENT: return fs::error::noent;
|
||||
case EEXIST: return fs::error::exist;
|
||||
case EINVAL: return fs::error::inval;
|
||||
case EACCES: return fs::error::acces;
|
||||
case ENOTEMPTY: return fs::error::notempty;
|
||||
default: fmt::throw_exception("Unknown system error: %d.", e);
|
||||
}
|
||||
}
|
||||
@@ -158,28 +136,6 @@ namespace fs
|
||||
static device_manager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
file_base::~file_base()
|
||||
{
|
||||
}
|
||||
|
||||
stat_t file_base::stat()
|
||||
{
|
||||
fmt::throw_exception("fs::file::stat() not supported for %s", typeid(*this).name());
|
||||
}
|
||||
|
||||
void file_base::sync()
|
||||
{
|
||||
// Do notning
|
||||
}
|
||||
|
||||
dir_base::~dir_base()
|
||||
{
|
||||
}
|
||||
|
||||
device_base::~device_base()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path)
|
||||
@@ -410,45 +366,6 @@ bool fs::is_dir(const std::string& path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::statfs(const std::string& path, fs::device_stat& info)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
return device->statfs(path, info);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
ULARGE_INTEGER avail_free;
|
||||
ULARGE_INTEGER total_size;
|
||||
ULARGE_INTEGER total_free;
|
||||
|
||||
if (!GetDiskFreeSpaceExW(to_wchar(path).get(), &avail_free, &total_size, &total_free))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
info.block_size = 4096; // TODO
|
||||
info.total_size = total_size.QuadPart;
|
||||
info.total_free = total_free.QuadPart;
|
||||
info.avail_free = avail_free.QuadPart;
|
||||
#else
|
||||
struct ::statvfs buf;
|
||||
if (::statvfs(path.c_str(), &buf) != 0)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
info.block_size = buf.f_frsize;
|
||||
info.total_size = info.block_size * buf.f_blocks;
|
||||
info.total_free = info.block_size * buf.f_bfree;
|
||||
info.avail_free = info.block_size * buf.f_bavail;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::create_dir(const std::string& path)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
@@ -513,7 +430,7 @@ bool fs::remove_dir(const std::string& path)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fs::rename(const std::string& from, const std::string& to, bool overwrite)
|
||||
bool fs::rename(const std::string& from, const std::string& to)
|
||||
{
|
||||
const auto device = get_virtual_device(from);
|
||||
|
||||
@@ -528,43 +445,14 @@ bool fs::rename(const std::string& from, const std::string& to, bool overwrite)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
const auto ws1 = to_wchar(from);
|
||||
const auto ws2 = to_wchar(to);
|
||||
|
||||
if (!MoveFileExW(ws1.get(), ws2.get(), overwrite ? MOVEFILE_REPLACE_EXISTING : 0))
|
||||
if (!MoveFileW(to_wchar(from).get(), to_wchar(to).get()))
|
||||
{
|
||||
DWORD error1 = GetLastError();
|
||||
|
||||
if (overwrite && error1 == ERROR_ACCESS_DENIED && is_dir(from) && is_dir(to))
|
||||
{
|
||||
if (RemoveDirectoryW(ws2.get()))
|
||||
{
|
||||
if (MoveFileW(ws1.get(), ws2.get()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
error1 = GetLastError();
|
||||
CreateDirectoryW(ws2.get(), NULL); // TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
error1 = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
g_tls_error = to_error(error1);
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
if (!overwrite && exists(to))
|
||||
{
|
||||
g_tls_error = fs::error::exist;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::rename(from.c_str(), to.c_str()) != 0)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
@@ -613,20 +501,14 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
}
|
||||
|
||||
// Here we use kernel-space copying for performance reasons
|
||||
#if defined(__APPLE__)
|
||||
// fcopyfile works on OS X 10.5+
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// fcopyfile works on FreeBSD and OS X 10.5+
|
||||
if (::fcopyfile(input, output, 0, COPYFILE_ALL))
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
if (::sendfile(input, output, 0, 0, NULL, NULL, 0))
|
||||
#elif defined(__linux__) || defined(__sun)
|
||||
#else
|
||||
// sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
|
||||
off_t bytes_copied = 0;
|
||||
struct ::stat fileinfo = { 0 };
|
||||
if (::fstat(input, &fileinfo) || ::sendfile(output, input, &bytes_copied, fileinfo.st_size))
|
||||
#else // NetBSD, OpenBSD, etc.
|
||||
fmt::throw_exception("fs::copy_file() isn't implemented for this platform.\nFrom: %s\nTo: %s", from, to);
|
||||
errno = 0;
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
const int err = errno;
|
||||
@@ -678,17 +560,18 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
|
||||
#ifdef _WIN32
|
||||
// Open the file
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE_END_OF_FILE_INFO _eof;
|
||||
_eof.EndOfFile.QuadPart = length;
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = length;
|
||||
|
||||
if (!SetFileInformationByHandle(handle, FileEndOfFileInfo, &_eof, sizeof(_eof)))
|
||||
// Seek and truncate
|
||||
if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN) || !SetEndOfFile(handle))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
CloseHandle(handle);
|
||||
@@ -708,48 +591,6 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fs::utime(const std::string& path, s64 atime, s64 mtime)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
return device->utime(path, atime, mtime);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Open the file
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
FILETIME _atime = from_time(atime);
|
||||
FILETIME _mtime = from_time(mtime);
|
||||
if (!SetFileTime(handle, nullptr, &_atime, &_mtime))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return true;
|
||||
#else
|
||||
::utimbuf buf;
|
||||
buf.actime = atime;
|
||||
buf.modtime = mtime;
|
||||
|
||||
if (::utime(path.c_str(), &buf) != 0)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::file::xnull() const
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("fs::file is null");
|
||||
@@ -760,17 +601,17 @@ void fs::file::xfail() const
|
||||
fmt::throw_exception("Unexpected fs::error %s", g_tls_error);
|
||||
}
|
||||
|
||||
fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
if (auto&& _file = device->open(path, mode))
|
||||
{
|
||||
m_file = std::move(_file);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -790,27 +631,21 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
if (test(mode & fs::excl))
|
||||
{
|
||||
g_tls_error = error::inval;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING;
|
||||
}
|
||||
|
||||
DWORD share = FILE_SHARE_READ;
|
||||
if (!test(mode & fs::unshare))
|
||||
{
|
||||
share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
}
|
||||
|
||||
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
class windows_file final : public file_base, public get_native_handle
|
||||
class windows_file final : public file_base
|
||||
{
|
||||
const HANDLE m_handle;
|
||||
|
||||
@@ -841,22 +676,25 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
return info;
|
||||
}
|
||||
|
||||
void sync() override
|
||||
{
|
||||
verify("file::sync" HERE), FlushFileBuffers(m_handle);
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
FILE_END_OF_FILE_INFO _eof;
|
||||
_eof.EndOfFile.QuadPart = length;
|
||||
LARGE_INTEGER old, pos;
|
||||
|
||||
if (!SetFileInformationByHandle(m_handle, FileEndOfFileInfo, &_eof, sizeof(_eof)))
|
||||
pos.QuadPart = 0;
|
||||
if (!SetFilePointerEx(m_handle, pos, &old, FILE_CURRENT)) // get old position
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
pos.QuadPart = length;
|
||||
if (!SetFilePointerEx(m_handle, pos, NULL, FILE_BEGIN)) // set new position
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
verify("file::trunc" HERE), SetEndOfFile(m_handle), SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -893,11 +731,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
whence == seek_end ? FILE_END :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
|
||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
verify("file::seek" HERE), SetFilePointerEx(m_handle, pos, &pos, mode);
|
||||
|
||||
return pos.QuadPart;
|
||||
}
|
||||
@@ -909,11 +743,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
native_handle get() override
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
};
|
||||
|
||||
m_file = std::make_unique<windows_file>(handle);
|
||||
@@ -934,10 +763,10 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
if (fd == -1)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
class unix_file final : public file_base, public get_native_handle
|
||||
class unix_file final : public file_base
|
||||
{
|
||||
const int m_fd;
|
||||
|
||||
@@ -968,11 +797,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
return info;
|
||||
}
|
||||
|
||||
void sync() override
|
||||
{
|
||||
verify("file::sync" HERE), ::fsync(m_fd) == 0;
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
if (::ftruncate(m_fd, length) != 0)
|
||||
@@ -1009,12 +833,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
|
||||
const auto result = ::lseek(m_fd, offset, mode);
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
return -1;
|
||||
}
|
||||
verify("file::seek" HERE), result != -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1026,15 +845,12 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
return file_info.st_size;
|
||||
}
|
||||
|
||||
native_handle get() override
|
||||
{
|
||||
return m_fd;
|
||||
}
|
||||
};
|
||||
|
||||
m_file = std::make_unique<unix_file>(fd);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fs::file::file(const void* ptr, std::size_t size)
|
||||
@@ -1053,48 +869,38 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
fs::stat_t stat() override
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Not supported" HERE);
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
return false;
|
||||
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
|
||||
}
|
||||
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
if (m_pos < m_size)
|
||||
{
|
||||
// Get readable size
|
||||
if (const u64 result = std::min<u64>(count, m_size - m_pos))
|
||||
{
|
||||
std::memcpy(buffer, m_ptr + m_pos, result);
|
||||
m_pos += result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
const u64 start = m_pos;
|
||||
const u64 end = seek(count, fs::seek_cur);
|
||||
if (end < start) fmt::throw_exception<std::logic_error>("Stream overflow" HERE);
|
||||
const u64 read_size = end - start;
|
||||
std::memcpy(buffer, m_ptr + start, read_size);
|
||||
return read_size;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
return 0;
|
||||
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, fs::seek_mode whence) override
|
||||
{
|
||||
const s64 new_pos =
|
||||
whence == fs::seek_set ? offset :
|
||||
whence == fs::seek_cur ? offset + m_pos :
|
||||
whence == fs::seek_end ? offset + size() :
|
||||
(fmt::raw_error("fs::file::memory_stream::seek(): invalid whence"), 0);
|
||||
|
||||
if (new_pos < 0)
|
||||
{
|
||||
fs::g_tls_error = fs::error::inval;
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_pos = new_pos;
|
||||
return m_pos;
|
||||
return
|
||||
whence == fs::seek_set ? m_pos = std::min<u64>(offset, m_size) :
|
||||
whence == fs::seek_cur ? m_pos = std::min<u64>(offset + m_pos, m_size) :
|
||||
whence == fs::seek_end ? m_pos = std::min<u64>(offset + m_size, m_size) :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
@@ -1106,20 +912,6 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
m_file = std::make_unique<memory_stream>(ptr, size);
|
||||
}
|
||||
|
||||
fs::native_handle fs::file::get_handle() const
|
||||
{
|
||||
if (auto getter = dynamic_cast<get_native_handle*>(m_file.get()))
|
||||
{
|
||||
return getter->get();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
return INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::dir::xnull() const
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("fs::dir is null");
|
||||
@@ -1263,22 +1055,11 @@ const std::string& fs::get_config_dir()
|
||||
// Use magic static
|
||||
static const std::string s_dir = []
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return get_executable_dir(); // ?
|
||||
#else
|
||||
std::string dir;
|
||||
|
||||
#ifdef _WIN32
|
||||
wchar_t buf[2048];
|
||||
if (GetModuleFileName(NULL, buf, ::size32(buf)) - 1 >= ::size32(buf) - 1)
|
||||
{
|
||||
MessageBoxA(0, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_config_dir()", MB_ICONERROR);
|
||||
return dir; // empty
|
||||
}
|
||||
|
||||
to_utf8(dir, buf); // Convert to UTF-8
|
||||
|
||||
std::replace(dir.begin(), dir.end(), '\\', '/');
|
||||
|
||||
dir.resize(dir.rfind('/') + 1);
|
||||
#else
|
||||
if (const char* home = ::getenv("XDG_CONFIG_HOME"))
|
||||
dir = home;
|
||||
else if (const char* home = ::getenv("HOME"))
|
||||
@@ -1291,9 +1072,59 @@ const std::string& fs::get_config_dir()
|
||||
if (!is_dir(dir) && !create_path(dir))
|
||||
{
|
||||
std::printf("Failed to create configuration directory '%s' (%d).\n", dir.c_str(), errno);
|
||||
return get_executable_dir();
|
||||
}
|
||||
#endif
|
||||
|
||||
return dir;
|
||||
#endif
|
||||
}();
|
||||
|
||||
return s_dir;
|
||||
}
|
||||
|
||||
const std::string& fs::get_executable_dir()
|
||||
{
|
||||
// Use magic static
|
||||
static const std::string s_dir = []
|
||||
{
|
||||
std::string dir;
|
||||
|
||||
#ifdef _WIN32
|
||||
wchar_t buf[2048];
|
||||
if (GetModuleFileName(NULL, buf, ::size32(buf)) - 1 >= ::size32(buf) - 1)
|
||||
{
|
||||
MessageBoxA(0, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_executable_dir()", MB_ICONERROR);
|
||||
return dir; // empty
|
||||
}
|
||||
|
||||
to_utf8(dir, buf); // Convert to UTF-8
|
||||
|
||||
std::replace(dir.begin(), dir.end(), '\\', '/');
|
||||
|
||||
#elif __APPLE__
|
||||
char buf[4096];
|
||||
u32 size = sizeof(buf);
|
||||
if (_NSGetExecutablePath(buf, &size))
|
||||
{
|
||||
std::printf("_NSGetExecutablePath() failed (size=0x%x).\n", size);
|
||||
return dir; // empty
|
||||
}
|
||||
|
||||
dir = buf;
|
||||
#else
|
||||
char buf[4096];
|
||||
const auto size = ::readlink("/proc/self/exe", buf, sizeof(buf));
|
||||
if (size <= 0 || size >= sizeof(buf))
|
||||
{
|
||||
std::printf("readlink(/proc/self/exe) failed (%d).\n", errno);
|
||||
return dir; // empty
|
||||
}
|
||||
|
||||
dir.assign(buf, size);
|
||||
#endif
|
||||
|
||||
// Leave only path
|
||||
dir.resize(dir.rfind('/') + 1);
|
||||
return dir;
|
||||
}();
|
||||
|
||||
@@ -1304,7 +1135,7 @@ std::string fs::get_data_dir(const std::string& prefix, const std::string& locat
|
||||
{
|
||||
static const std::string s_dir = []
|
||||
{
|
||||
const std::string& dir = get_config_dir() + "data/";
|
||||
const std::string& dir = get_config_dir() + "/data/";
|
||||
|
||||
if (!is_dir(dir) && !create_path(dir))
|
||||
{
|
||||
@@ -1451,8 +1282,6 @@ void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
|
||||
case fs::error::inval: return "Invalid arguments";
|
||||
case fs::error::noent: return "Not found";
|
||||
case fs::error::exist: return "Already exists";
|
||||
case fs::error::acces: return "Access violation";
|
||||
case fs::error::notempty: return "Not empty";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
|
||||
+15
-175
@@ -6,16 +6,9 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace fs
|
||||
{
|
||||
#ifdef _WIN32
|
||||
using native_handle = void*;
|
||||
#else
|
||||
using native_handle = int;
|
||||
#endif
|
||||
|
||||
// File open mode flags
|
||||
enum class open_mode : u32
|
||||
{
|
||||
@@ -25,7 +18,6 @@ namespace fs
|
||||
create,
|
||||
trunc,
|
||||
excl,
|
||||
unshare,
|
||||
|
||||
__bitset_enum_max
|
||||
};
|
||||
@@ -36,7 +28,6 @@ namespace fs
|
||||
constexpr auto create = +open_mode::create; // Create file if it doesn't exist
|
||||
constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty
|
||||
constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`)
|
||||
constexpr auto unshare = +open_mode::unshare; // Prevent opening the file twice
|
||||
|
||||
constexpr auto rewrite = open_mode::write + open_mode::create + open_mode::trunc;
|
||||
|
||||
@@ -63,19 +54,12 @@ namespace fs
|
||||
s64 ctime;
|
||||
};
|
||||
|
||||
// Native handle getter
|
||||
struct get_native_handle
|
||||
{
|
||||
virtual native_handle get() = 0;
|
||||
};
|
||||
|
||||
// File handle base
|
||||
struct file_base
|
||||
{
|
||||
virtual ~file_base();
|
||||
virtual ~file_base() = default;
|
||||
|
||||
virtual stat_t stat();
|
||||
virtual void sync();
|
||||
virtual stat_t stat() = 0;
|
||||
virtual bool trunc(u64 length) = 0;
|
||||
virtual u64 read(void* buffer, u64 size) = 0;
|
||||
virtual u64 write(const void* buffer, u64 size) = 0;
|
||||
@@ -92,34 +76,23 @@ namespace fs
|
||||
// Directory handle base
|
||||
struct dir_base
|
||||
{
|
||||
virtual ~dir_base();
|
||||
virtual ~dir_base() = default;
|
||||
|
||||
virtual bool read(dir_entry&) = 0;
|
||||
virtual void rewind() = 0;
|
||||
};
|
||||
|
||||
// Device information
|
||||
struct device_stat
|
||||
{
|
||||
u64 block_size;
|
||||
u64 total_size;
|
||||
u64 total_free; // Total size of free space
|
||||
u64 avail_free; // Free space available to unprivileged user
|
||||
};
|
||||
|
||||
// Virtual device
|
||||
struct device_base
|
||||
{
|
||||
virtual ~device_base();
|
||||
virtual ~device_base() = default;
|
||||
|
||||
virtual bool stat(const std::string& path, stat_t& info) = 0;
|
||||
virtual bool statfs(const std::string& path, device_stat& info) = 0;
|
||||
virtual bool remove_dir(const std::string& path) = 0;
|
||||
virtual bool create_dir(const std::string& path) = 0;
|
||||
virtual bool rename(const std::string& from, const std::string& to) = 0;
|
||||
virtual bool remove(const std::string& path) = 0;
|
||||
virtual bool trunc(const std::string& path, u64 length) = 0;
|
||||
virtual bool utime(const std::string& path, s64 atime, s64 mtime) = 0;
|
||||
|
||||
virtual std::unique_ptr<file_base> open(const std::string& path, bs_t<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
|
||||
@@ -146,9 +119,6 @@ namespace fs
|
||||
// Check whether the directory exists and is NOT a file
|
||||
bool is_dir(const std::string& path);
|
||||
|
||||
// Get filesystem information
|
||||
bool statfs(const std::string& path, device_stat& info);
|
||||
|
||||
// Delete empty directory
|
||||
bool remove_dir(const std::string& path);
|
||||
|
||||
@@ -159,7 +129,7 @@ namespace fs
|
||||
bool create_path(const std::string& path);
|
||||
|
||||
// Rename (move) file or directory
|
||||
bool rename(const std::string& from, const std::string& to, bool overwrite);
|
||||
bool rename(const std::string& from, const std::string& to);
|
||||
|
||||
// Copy file contents
|
||||
bool copy_file(const std::string& from, const std::string& to, bool overwrite);
|
||||
@@ -170,9 +140,6 @@ namespace fs
|
||||
// Change file size (possibly appending zeros)
|
||||
bool truncate_file(const std::string& path, u64 length);
|
||||
|
||||
// Set file access/modification time
|
||||
bool utime(const std::string& path, s64 atime, s64 mtime);
|
||||
|
||||
class file final
|
||||
{
|
||||
std::unique_ptr<file_base> m_file;
|
||||
@@ -185,19 +152,17 @@ namespace fs
|
||||
file() = default;
|
||||
|
||||
// Open file with specified mode
|
||||
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read);
|
||||
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read)
|
||||
{
|
||||
open(path, mode);
|
||||
}
|
||||
|
||||
// Open file with specified mode
|
||||
bool open(const std::string& path, bs_t<open_mode> mode = ::fs::read);
|
||||
|
||||
// Open memory for read
|
||||
explicit file(const void* ptr, std::size_t size);
|
||||
|
||||
// Open file with specified args (forward to constructor)
|
||||
template <typename... Args>
|
||||
bool open(Args&&... args)
|
||||
{
|
||||
*this = fs::file(std::forward<Args>(args)...);
|
||||
return m_file.operator bool();
|
||||
}
|
||||
|
||||
// Check whether the handle is valid (opened file)
|
||||
explicit operator bool() const
|
||||
{
|
||||
@@ -234,13 +199,6 @@ namespace fs
|
||||
return m_file->stat();
|
||||
}
|
||||
|
||||
// Sync file buffers
|
||||
void sync() const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
return m_file->sync();
|
||||
}
|
||||
|
||||
// Read the data from the file and return the amount of data written in buffer
|
||||
u64 read(void* buffer, u64 count) const
|
||||
{
|
||||
@@ -361,9 +319,6 @@ namespace fs
|
||||
if (seek(0), !read(result)) xfail();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get native handle if available
|
||||
native_handle get_handle() const;
|
||||
};
|
||||
|
||||
class dir final
|
||||
@@ -482,6 +437,9 @@ namespace fs
|
||||
// Get configuration directory
|
||||
const std::string& get_config_dir();
|
||||
|
||||
// Get executable directory
|
||||
const std::string& get_executable_dir();
|
||||
|
||||
// Get data/cache directory for specified prefix and suffix
|
||||
std::string get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix);
|
||||
|
||||
@@ -501,126 +459,8 @@ namespace fs
|
||||
inval,
|
||||
noent,
|
||||
exist,
|
||||
acces,
|
||||
notempty,
|
||||
};
|
||||
|
||||
// Error code returned
|
||||
extern thread_local error g_tls_error;
|
||||
|
||||
template <typename T>
|
||||
struct container_stream final : file_base
|
||||
{
|
||||
// T can be a reference, but this is not recommended
|
||||
using value_type = typename std::remove_reference_t<T>::value_type;
|
||||
|
||||
T obj;
|
||||
u64 pos;
|
||||
|
||||
container_stream(T&& obj)
|
||||
: obj(std::forward<T>(obj))
|
||||
, pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
~container_stream() override
|
||||
{
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
obj.resize(length);
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 read(void* buffer, u64 size) override
|
||||
{
|
||||
const u64 end = obj.size();
|
||||
|
||||
if (pos < end)
|
||||
{
|
||||
// Get readable size
|
||||
if (const u64 max = std::min<u64>(size, end - pos))
|
||||
{
|
||||
std::copy(obj.cbegin() + pos, obj.cbegin() + pos + max, static_cast<value_type*>(buffer));
|
||||
pos = pos + max;
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 size) override
|
||||
{
|
||||
const u64 old_size = obj.size();
|
||||
|
||||
if (old_size + size < old_size)
|
||||
{
|
||||
fmt::raw_error("fs::container_stream<>::write(): overflow");
|
||||
}
|
||||
|
||||
if (pos > old_size)
|
||||
{
|
||||
// Fill gap if necessary (default-initialized)
|
||||
obj.resize(pos);
|
||||
}
|
||||
|
||||
const auto src = static_cast<const value_type*>(buffer);
|
||||
|
||||
// Overwrite existing part
|
||||
const u64 overlap = std::min<u64>(obj.size() - pos, size);
|
||||
std::copy(src, src + overlap, obj.begin() + pos);
|
||||
|
||||
// Append new data
|
||||
obj.insert(obj.end(), src + overlap, src + size);
|
||||
pos += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, seek_mode whence) override
|
||||
{
|
||||
const s64 new_pos =
|
||||
whence == fs::seek_set ? offset :
|
||||
whence == fs::seek_cur ? offset + pos :
|
||||
whence == fs::seek_end ? offset + size() :
|
||||
(fmt::raw_error("fs::container_stream<>::seek(): invalid whence"), 0);
|
||||
|
||||
if (new_pos < 0)
|
||||
{
|
||||
fs::g_tls_error = fs::error::inval;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = new_pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
{
|
||||
return obj.size();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
file make_stream(T&& container = T{})
|
||||
{
|
||||
file result;
|
||||
result.reset(std::make_unique<container_stream<T>>(std::forward<T>(container)));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
|
||||
{
|
||||
if (fs::file f{path, mode})
|
||||
{
|
||||
// Write args sequentially
|
||||
int seq[]{ (f.write(args), 0)... };
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,817 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
|
||||
#include "GDBDebugServer.h"
|
||||
#include "Log.h"
|
||||
#include <algorithm>
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include"fcntl.h"
|
||||
#endif
|
||||
|
||||
extern void ppu_set_breakpoint(u32 addr);
|
||||
extern void ppu_remove_breakpoint(u32 addr);
|
||||
|
||||
logs::channel gdbDebugServer("gdbDebugServer");
|
||||
|
||||
int sock_init(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa_data;
|
||||
return WSAStartup(MAKEWORD(1, 1), &wsa_data);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_quit(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return WSACleanup();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
int closesocket(socket_t s) {
|
||||
return close(s);
|
||||
}
|
||||
const int SOCKET_ERROR = -1;
|
||||
const socket_t INVALID_SOCKET = -1;
|
||||
#define sscanf_s sscanf
|
||||
#define HEX_U32 "x"
|
||||
#define HEX_U64 "lx"
|
||||
#else
|
||||
#define HEX_U32 "lx"
|
||||
#define HEX_U64 "llx"
|
||||
#endif
|
||||
|
||||
bool check_errno_again() {
|
||||
#ifdef _WIN32
|
||||
int err = GetLastError();
|
||||
return (err == WSAEWOULDBLOCK);
|
||||
#else
|
||||
int err = errno;
|
||||
return (err == EAGAIN) || (err == EWOULDBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string u32_to_hex(u32 i) {
|
||||
return fmt::format("%" HEX_U32, i);
|
||||
}
|
||||
|
||||
std::string u64_to_padded_hex(u64 value) {
|
||||
return fmt::format("%.16" HEX_U64, value);
|
||||
}
|
||||
|
||||
std::string u32_to_padded_hex(u32 value) {
|
||||
return fmt::format("%.8" HEX_U32, value);
|
||||
}
|
||||
|
||||
u8 hex_to_u8(std::string val) {
|
||||
u8 result;
|
||||
sscanf_s(val.c_str(), "%02hhX", &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 hex_to_u32(std::string val) {
|
||||
u32 result;
|
||||
sscanf_s(val.c_str(), "%" HEX_U32, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 hex_to_u64(std::string val) {
|
||||
u64 result;
|
||||
sscanf_s(val.c_str(), "%" HEX_U64, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void GDBDebugServer::start_server()
|
||||
{
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (server_socket == INVALID_SOCKET) {
|
||||
gdbDebugServer.error("Error creating server socket");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
{
|
||||
int mode = 1;
|
||||
ioctlsocket(server_socket, FIONBIO, (u_long FAR *)&mode);
|
||||
}
|
||||
#else
|
||||
fcntl(server_socket, F_SETFL, fcntl(server_socket, F_GETFL) | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
int err;
|
||||
|
||||
sockaddr_in server_saddr;
|
||||
server_saddr.sin_family = AF_INET;
|
||||
int port = g_cfg.misc.gdb_server_port;
|
||||
server_saddr.sin_port = htons(port);
|
||||
server_saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
err = bind(server_socket, (struct sockaddr *) &server_saddr, sizeof(server_saddr));
|
||||
if (err == SOCKET_ERROR) {
|
||||
gdbDebugServer.error("Error binding to port %d", port);
|
||||
return;
|
||||
}
|
||||
|
||||
err = listen(server_socket, 1);
|
||||
if (err == SOCKET_ERROR) {
|
||||
gdbDebugServer.error("Error listening on port %d", port);
|
||||
return;
|
||||
}
|
||||
|
||||
gdbDebugServer.success("GDB Debug Server listening on port %d", port);
|
||||
}
|
||||
|
||||
int GDBDebugServer::read(void * buf, int cnt)
|
||||
{
|
||||
while (!stop) {
|
||||
int result = recv(client_socket, reinterpret_cast<char*>(buf), cnt, 0);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
gdbDebugServer.error("Error during socket read");
|
||||
fmt::throw_exception("Error during socket read" HERE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char GDBDebugServer::read_char()
|
||||
{
|
||||
char result;
|
||||
int cnt = read(&result, 1);
|
||||
if (!cnt) {
|
||||
fmt::throw_exception("Tried to read char, but no data was available" HERE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
u8 GDBDebugServer::read_hexbyte()
|
||||
{
|
||||
char buf[2];
|
||||
read(buf, 2);
|
||||
return static_cast<u8>(strtol(buf, nullptr, 16));
|
||||
}
|
||||
|
||||
void GDBDebugServer::try_read_cmd(gdb_cmd & out_cmd)
|
||||
{
|
||||
char c = read_char();
|
||||
//interrupt
|
||||
if (UNLIKELY(c == 0x03)) {
|
||||
out_cmd.cmd = "\0x03";
|
||||
out_cmd.data = "";
|
||||
out_cmd.checksum = 0;
|
||||
return;
|
||||
}
|
||||
if (UNLIKELY(c != '$')) {
|
||||
//gdb starts conversation with + for some reason
|
||||
if (c == '+') {
|
||||
c = read_char();
|
||||
}
|
||||
if (c != '$') {
|
||||
fmt::throw_exception("Expected start of packet character '$', got '%c' instead" HERE, c);
|
||||
}
|
||||
}
|
||||
//clear packet data
|
||||
out_cmd.cmd = "";
|
||||
out_cmd.data = "";
|
||||
out_cmd.checksum = 0;
|
||||
bool cmd_part = true;
|
||||
u8 checksum = 0;
|
||||
while(true) {
|
||||
c = read_char();
|
||||
if (c == '#') {
|
||||
break;
|
||||
}
|
||||
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
||||
//escaped char
|
||||
if (c == '}') {
|
||||
c = read_char() ^ 0x20;
|
||||
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
||||
}
|
||||
//cmd-data splitters
|
||||
if (cmd_part && ((c == ':') || (c == '.') || (c == ';'))) {
|
||||
cmd_part = false;
|
||||
}
|
||||
if (cmd_part) {
|
||||
out_cmd.cmd += c;
|
||||
//only q and v commands can have multi-char command
|
||||
if ((out_cmd.cmd.length() == 1) && (c != 'q') && (c != 'v')) {
|
||||
cmd_part = false;
|
||||
}
|
||||
} else {
|
||||
out_cmd.data += c;
|
||||
}
|
||||
}
|
||||
out_cmd.checksum = read_hexbyte();
|
||||
if (out_cmd.checksum != checksum) {
|
||||
throw new wrong_checksum_exception("Wrong checksum for packet" HERE);
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::read_cmd(gdb_cmd & out_cmd)
|
||||
{
|
||||
while (true) {
|
||||
try {
|
||||
try_read_cmd(out_cmd);
|
||||
ack(true);
|
||||
return true;
|
||||
}
|
||||
catch (wrong_checksum_exception) {
|
||||
ack(false);
|
||||
}
|
||||
catch (std::runtime_error e) {
|
||||
gdbDebugServer.error(e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GDBDebugServer::send(const char * buf, int cnt)
|
||||
{
|
||||
gdbDebugServer.trace("Sending %s (%d bytes)", buf, cnt);
|
||||
while (!stop) {
|
||||
int res = ::send(client_socket, buf, cnt, 0);
|
||||
if (res == SOCKET_ERROR) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
continue;
|
||||
}
|
||||
gdbDebugServer.error("Failed sending %d bytes", cnt);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GDBDebugServer::send_char(char c)
|
||||
{
|
||||
send(&c, 1);
|
||||
}
|
||||
|
||||
void GDBDebugServer::ack(bool accepted)
|
||||
{
|
||||
send_char(accepted ? '+' : '-');
|
||||
}
|
||||
|
||||
void GDBDebugServer::send_cmd(const std::string & cmd)
|
||||
{
|
||||
u8 checksum = 0;
|
||||
std::string buf;
|
||||
buf.reserve(cmd.length() + 4);
|
||||
buf += "$";
|
||||
for (int i = 0; i < cmd.length(); ++i) {
|
||||
checksum = (checksum + append_encoded_char(cmd[i], buf)) % 256;
|
||||
}
|
||||
buf += "#";
|
||||
buf += to_hexbyte(checksum);
|
||||
send(buf.c_str(), static_cast<int>(buf.length()));
|
||||
}
|
||||
|
||||
bool GDBDebugServer::send_cmd_ack(const std::string & cmd)
|
||||
{
|
||||
while (true) {
|
||||
send_cmd(cmd);
|
||||
char c = read_char();
|
||||
if (LIKELY(c == '+')) {
|
||||
return true;
|
||||
}
|
||||
if (UNLIKELY(c != '-')) {
|
||||
gdbDebugServer.error("Wrong acknowledge character received %c", c);
|
||||
return false;
|
||||
}
|
||||
gdbDebugServer.warning("Client rejected our cmd");
|
||||
}
|
||||
}
|
||||
|
||||
u8 GDBDebugServer::append_encoded_char(char c, std::string & str)
|
||||
{
|
||||
u8 checksum = 0;
|
||||
if (UNLIKELY((c == '#') || (c == '$') || (c == '}'))) {
|
||||
str += '}';
|
||||
c ^= 0x20;
|
||||
checksum = '}';
|
||||
}
|
||||
checksum = (checksum + reinterpret_cast<u8&>(c)) % 256;
|
||||
str += c;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::to_hexbyte(u8 i)
|
||||
{
|
||||
std::string result = "00";
|
||||
u8 i1 = i & 0xF;
|
||||
u8 i2 = i >> 4;
|
||||
result[0] = i2 > 9 ? 'a' + i2 - 10 : '0' + i2;
|
||||
result[1] = i1 > 9 ? 'a' + i1 - 10 : '0' + i1;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::select_thread(u64 id)
|
||||
{
|
||||
//in case we have none at all
|
||||
selected_thread.reset();
|
||||
const auto on_select = [&](u32, cpu_thread& cpu)
|
||||
{
|
||||
return (id == ALL_THREADS) || (id == ANY_THREAD) || (cpu.id == id);
|
||||
};
|
||||
if (auto ppu = idm::select<ppu_thread>(on_select)) {
|
||||
selected_thread = ppu.ptr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::get_reg(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
{
|
||||
std::string result;
|
||||
//ids from gdb/features/rs6000/powerpc-64.c
|
||||
//pc
|
||||
switch (rid) {
|
||||
case 64:
|
||||
return u64_to_padded_hex(thread->cia);
|
||||
//msr?
|
||||
case 65:
|
||||
return std::string(16, 'x');
|
||||
case 66:
|
||||
return u32_to_padded_hex(thread->cr_pack());
|
||||
case 67:
|
||||
return u64_to_padded_hex(thread->lr);
|
||||
case 68:
|
||||
return u64_to_padded_hex(thread->ctr);
|
||||
//xer
|
||||
case 69:
|
||||
return std::string(8, 'x');
|
||||
//fpscr
|
||||
case 70:
|
||||
return std::string(8, 'x');
|
||||
default:
|
||||
if (rid > 70) return "";
|
||||
return (rid > 31)
|
||||
? u64_to_padded_hex(reinterpret_cast<u64&>(thread->fpr[rid - 32])) //fpr
|
||||
: u64_to_padded_hex(thread->gpr[rid]); //gpr
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::set_reg(std::shared_ptr<ppu_thread> thread, u32 rid, std::string value)
|
||||
{
|
||||
switch (rid) {
|
||||
case 64:
|
||||
thread->cia = static_cast<u32>(hex_to_u64(value));
|
||||
return true;
|
||||
//msr?
|
||||
case 65:
|
||||
return true;
|
||||
case 66:
|
||||
thread->cr_unpack(hex_to_u32(value));
|
||||
return true;
|
||||
case 67:
|
||||
thread->lr = hex_to_u64(value);
|
||||
return true;
|
||||
case 68:
|
||||
thread->ctr = hex_to_u64(value);
|
||||
return true;
|
||||
//xer
|
||||
case 69:
|
||||
return true;
|
||||
//fpscr
|
||||
case 70:
|
||||
return true;
|
||||
default:
|
||||
if (rid > 70) return false;
|
||||
if (rid > 31) {
|
||||
u64 val = hex_to_u64(value);
|
||||
thread->fpr[rid - 32] = reinterpret_cast<f64&>(val);
|
||||
} else {
|
||||
thread->gpr[rid] = hex_to_u64(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GDBDebugServer::get_reg_size(std::shared_ptr<ppu_thread> thread, u32 rid)
|
||||
{
|
||||
switch (rid) {
|
||||
case 66:
|
||||
case 69:
|
||||
case 70:
|
||||
return 4;
|
||||
default:
|
||||
if (rid > 70) {
|
||||
return 0;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBDebugServer::send_reason()
|
||||
{
|
||||
return send_cmd_ack("S05");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_extended_mode(gdb_cmd & cmd)
|
||||
{
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_reason(gdb_cmd & cmd)
|
||||
{
|
||||
return send_reason();
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_supported(gdb_cmd & cmd)
|
||||
{
|
||||
return send_cmd_ack("PacketSize=1200");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_thread_info(gdb_cmd & cmd)
|
||||
{
|
||||
std::string result = "";
|
||||
const auto on_select = [&](u32, cpu_thread& cpu)
|
||||
{
|
||||
if (result.length()) {
|
||||
result += ",";
|
||||
}
|
||||
result += u64_to_padded_hex(static_cast<u64>(cpu.id));
|
||||
};
|
||||
idm::select<ppu_thread>(on_select);
|
||||
idm::select<ARMv7Thread>(on_select);
|
||||
idm::select<RawSPUThread>(on_select);
|
||||
idm::select<SPUThread>(on_select);
|
||||
|
||||
//todo: this may exceed max command length
|
||||
result = "m" + result + "l";
|
||||
|
||||
return send_cmd_ack(result);;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_current_thread(gdb_cmd & cmd)
|
||||
{
|
||||
return send_cmd_ack(selected_thread.expired() ? "" : u64_to_padded_hex(selected_thread.lock()->id));
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_register(gdb_cmd & cmd)
|
||||
{
|
||||
select_thread(general_ops_thread_id);
|
||||
auto th = selected_thread.lock();
|
||||
if (th->id_type() == 1) {
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(th);
|
||||
u32 rid = hex_to_u32(cmd.data);
|
||||
std::string result = get_reg(ppu, rid);
|
||||
if (!result.length()) {
|
||||
gdbDebugServer.warning("Wrong register id %d", rid);
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
return send_cmd_ack(result);
|
||||
}
|
||||
gdbDebugServer.warning("Unimplemented thread type %d", th->id_type());
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_register(gdb_cmd & cmd)
|
||||
{
|
||||
select_thread(general_ops_thread_id);
|
||||
auto th = selected_thread.lock();
|
||||
if (th->id_type() == 1) {
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(th);
|
||||
size_t eq_pos = cmd.data.find('=');
|
||||
if (eq_pos == std::string::npos) {
|
||||
gdbDebugServer.warning("Wrong write_register cmd data %s", cmd.data.c_str());
|
||||
return send_cmd_ack("E02");
|
||||
}
|
||||
u32 rid = hex_to_u32(cmd.data.substr(0, eq_pos));
|
||||
std::string value = cmd.data.substr(eq_pos + 1);
|
||||
if (!set_reg(ppu, rid, value)) {
|
||||
gdbDebugServer.warning("Wrong register id %d", rid);
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
gdbDebugServer.warning("Unimplemented thread type %d", th->id_type());
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_memory(gdb_cmd & cmd)
|
||||
{
|
||||
size_t s = cmd.data.find(',');
|
||||
u32 addr = hex_to_u32(cmd.data.substr(0, s));
|
||||
u32 len = hex_to_u32(cmd.data.substr(s + 1));
|
||||
std::string result;
|
||||
result.reserve(len * 2);
|
||||
for (u32 i = 0; i < len; ++i) {
|
||||
if (vm::check_addr(addr + i)) {
|
||||
result += to_hexbyte(vm::read8(addr + i));
|
||||
} else {
|
||||
break;
|
||||
//result += "xx";
|
||||
}
|
||||
}
|
||||
if (len && !result.length()) {
|
||||
//nothing read
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
return send_cmd_ack(result);
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_memory(gdb_cmd & cmd)
|
||||
{
|
||||
size_t s = cmd.data.find(',');
|
||||
size_t s2 = cmd.data.find(':');
|
||||
if ((s == std::string::npos) || (s2 == std::string::npos)) {
|
||||
gdbDebugServer.warning("Malformed write memory request received: %s", cmd.data.c_str());
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
u32 addr = hex_to_u32(cmd.data.substr(0, s));
|
||||
u32 len = hex_to_u32(cmd.data.substr(s + 1, s2 - s - 1));
|
||||
const char* data_ptr = (cmd.data.c_str()) + s2 + 1;
|
||||
for (u32 i = 0; i < len; ++i) {
|
||||
if (vm::check_addr(addr + i)) {
|
||||
u8 val;
|
||||
int res = sscanf_s(data_ptr, "%02hhX", &val);
|
||||
if (!res) {
|
||||
gdbDebugServer.warning("Couldn't read u8 from string %s", data_ptr);
|
||||
return send_cmd_ack("E02");
|
||||
}
|
||||
data_ptr += 2;
|
||||
vm::write8(addr + i, val);
|
||||
} else {
|
||||
return send_cmd_ack("E03");
|
||||
}
|
||||
}
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_read_all_registers(gdb_cmd & cmd)
|
||||
{
|
||||
std::string result;
|
||||
select_thread(general_ops_thread_id);
|
||||
|
||||
auto th = selected_thread.lock();
|
||||
if (th->id_type() == 1) {
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(th);
|
||||
//68 64-bit registers, and 3 32-bit
|
||||
result.reserve(68*16 + 3*8);
|
||||
for (int i = 0; i < 71; ++i) {
|
||||
result += get_reg(ppu, i);
|
||||
}
|
||||
return send_cmd_ack(result);
|
||||
}
|
||||
gdbDebugServer.warning("Unimplemented thread type %d", th->id_type());
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_write_all_registers(gdb_cmd & cmd)
|
||||
{
|
||||
select_thread(general_ops_thread_id);
|
||||
auto th = selected_thread.lock();
|
||||
if (th->id_type() == 1) {
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(th);
|
||||
int ptr = 0;
|
||||
for (int i = 0; i < 71; ++i) {
|
||||
int sz = get_reg_size(ppu, i);
|
||||
set_reg(ppu, i, cmd.data.substr(ptr, sz * 2));
|
||||
ptr += sz * 2;
|
||||
}
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
gdbDebugServer.warning("Unimplemented thread type %d", th->id_type());
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_set_thread_ops(gdb_cmd & cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
std::string thread = cmd.data.substr(1);
|
||||
u64 id = thread == "-1" ? ALL_THREADS : hex_to_u64(thread);
|
||||
if (type == 'c') {
|
||||
continue_ops_thread_id = id;
|
||||
} else {
|
||||
general_ops_thread_id = id;
|
||||
}
|
||||
if (select_thread(id)) {
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
gdbDebugServer.warning("Client asked to use thread %llx for %s, but no matching thread was found", id, type == 'c' ? "continue ops" : "general ops");
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_attached_to_what(gdb_cmd & cmd)
|
||||
{
|
||||
//creating processes from client is not available yet
|
||||
return send_cmd_ack("1");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_kill(gdb_cmd & cmd)
|
||||
{
|
||||
Emu.Stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_continue_support(gdb_cmd & cmd)
|
||||
{
|
||||
return send_cmd_ack("vCont;c;s;C;S");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_vcont(gdb_cmd & cmd)
|
||||
{
|
||||
//todo: handle multiple actions and thread ids
|
||||
this->from_breakpoint = false;
|
||||
if (cmd.data[1] == 'c') {
|
||||
select_thread(continue_ops_thread_id);
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(selected_thread.lock());
|
||||
ppu->state -= cpu_flag::dbg_pause;
|
||||
if (Emu.IsPaused()) {
|
||||
Emu.Resume();
|
||||
}
|
||||
thread_ctrl::wait();
|
||||
//we are in all-stop mode
|
||||
Emu.Pause();
|
||||
return send_reason();
|
||||
} else if (cmd.data[1] == 's') {
|
||||
select_thread(continue_ops_thread_id);
|
||||
auto ppu = std::static_pointer_cast<ppu_thread>(selected_thread.lock());
|
||||
ppu->state += cpu_flag::dbg_step;
|
||||
ppu->state -= cpu_flag::dbg_pause;
|
||||
if (Emu.IsPaused()) {
|
||||
Emu.Resume();
|
||||
} else {
|
||||
ppu->notify();
|
||||
}
|
||||
thread_ctrl::wait();
|
||||
//we are in all-stop mode
|
||||
Emu.Pause();
|
||||
return send_reason();
|
||||
}
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
static const u32 INVALID_PTR = 0xffffffff;
|
||||
|
||||
bool GDBDebugServer::cmd_set_breakpoint(gdb_cmd & cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
//software breakpoint
|
||||
if (type == '0') {
|
||||
u32 addr = INVALID_PTR;
|
||||
if (cmd.data.find(';') != std::string::npos) {
|
||||
gdbDebugServer.warning("Received request to set breakpoint with condition, but they are not supported");
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
||||
if (addr == INVALID_PTR) {
|
||||
gdbDebugServer.warning("Can't parse breakpoint request, data: %s", cmd.data.c_str());
|
||||
return send_cmd_ack("E02");
|
||||
}
|
||||
ppu_set_breakpoint(addr);
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
//other breakpoint types are not supported
|
||||
return send_cmd_ack("");
|
||||
}
|
||||
|
||||
bool GDBDebugServer::cmd_remove_breakpoint(gdb_cmd & cmd)
|
||||
{
|
||||
char type = cmd.data[0];
|
||||
//software breakpoint
|
||||
if (type == '0') {
|
||||
u32 addr = INVALID_PTR;
|
||||
sscanf_s(cmd.data.c_str(), "0,%x", &addr);
|
||||
if (addr == INVALID_PTR) {
|
||||
gdbDebugServer.warning("Can't parse breakpoint remove request, data: %s", cmd.data.c_str());
|
||||
return send_cmd_ack("E01");
|
||||
}
|
||||
ppu_remove_breakpoint(addr);
|
||||
return send_cmd_ack("OK");
|
||||
}
|
||||
//other breakpoint types are not supported
|
||||
return send_cmd_ack("");
|
||||
|
||||
}
|
||||
|
||||
#define PROCESS_CMD(cmds,handler) if (cmd.cmd == cmds) { if (!handler(cmd)) break; else continue; }
|
||||
|
||||
void GDBDebugServer::on_task()
|
||||
{
|
||||
sock_init();
|
||||
|
||||
start_server();
|
||||
|
||||
while (!stop) {
|
||||
sockaddr_in client;
|
||||
socklen_t client_len = sizeof(client);
|
||||
client_socket = accept(server_socket, (struct sockaddr *) &client, &client_len);
|
||||
|
||||
if (client_socket == INVALID_SOCKET) {
|
||||
if (check_errno_again()) {
|
||||
thread_ctrl::wait_for(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
gdbDebugServer.error("Could not establish new connection\n");
|
||||
return;
|
||||
}
|
||||
//stop immediately
|
||||
Emu.Pause();
|
||||
|
||||
try {
|
||||
char hostbuf[32];
|
||||
inet_ntop(client.sin_family, reinterpret_cast<void*>(&client.sin_addr), hostbuf, 32);
|
||||
gdbDebugServer.success("Got connection to GDB debug server from %s:%d", hostbuf, client.sin_port);
|
||||
|
||||
gdb_cmd cmd;
|
||||
|
||||
while (!stop) {
|
||||
if (!read_cmd(cmd)) {
|
||||
break;
|
||||
}
|
||||
gdbDebugServer.trace("Command %s with data %s received", cmd.cmd.c_str(), cmd.data.c_str());
|
||||
PROCESS_CMD("!", cmd_extended_mode);
|
||||
PROCESS_CMD("?", cmd_reason);
|
||||
PROCESS_CMD("qSupported", cmd_supported);
|
||||
PROCESS_CMD("qfThreadInfo", cmd_thread_info);
|
||||
PROCESS_CMD("qC", cmd_current_thread);
|
||||
PROCESS_CMD("p", cmd_read_register);
|
||||
PROCESS_CMD("P", cmd_write_register);
|
||||
PROCESS_CMD("m", cmd_read_memory);
|
||||
PROCESS_CMD("M", cmd_write_memory);
|
||||
PROCESS_CMD("g", cmd_read_all_registers);
|
||||
PROCESS_CMD("G", cmd_write_all_registers);
|
||||
PROCESS_CMD("H", cmd_set_thread_ops);
|
||||
PROCESS_CMD("qAttached", cmd_attached_to_what);
|
||||
PROCESS_CMD("k", cmd_kill);
|
||||
PROCESS_CMD("vCont?", cmd_continue_support);
|
||||
PROCESS_CMD("vCont", cmd_vcont);
|
||||
PROCESS_CMD("z", cmd_remove_breakpoint);
|
||||
PROCESS_CMD("Z", cmd_set_breakpoint);
|
||||
|
||||
gdbDebugServer.trace("Unsupported command received %s", cmd.cmd.c_str());
|
||||
if (!send_cmd_ack("")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
if (client_socket) {
|
||||
closesocket(client_socket);
|
||||
client_socket = 0;
|
||||
}
|
||||
gdbDebugServer.error(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef PROCESS_CMD
|
||||
|
||||
void GDBDebugServer::on_exit()
|
||||
{
|
||||
if (server_socket) {
|
||||
closesocket(server_socket);
|
||||
}
|
||||
if (client_socket) {
|
||||
closesocket(client_socket);
|
||||
}
|
||||
sock_quit();
|
||||
}
|
||||
|
||||
std::string GDBDebugServer::get_name() const
|
||||
{
|
||||
return "GDBDebugger";
|
||||
}
|
||||
|
||||
void GDBDebugServer::on_stop()
|
||||
{
|
||||
this->stop = true;
|
||||
//just in case we are waiting for breakpoint
|
||||
this->notify();
|
||||
named_thread::on_stop();
|
||||
}
|
||||
|
||||
u32 g_gdb_debugger_id = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef sscanf_s
|
||||
#endif
|
||||
|
||||
#undef HEX_U32
|
||||
#undef HEX_U64
|
||||
|
||||
#endif
|
||||
@@ -1,131 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_GDB_DEBUGGER
|
||||
|
||||
#include "Thread.h"
|
||||
#include <Emu/IdManager.h>
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
using socket_t = SOCKET;
|
||||
#else
|
||||
using socket_t = int;
|
||||
#endif
|
||||
|
||||
typedef struct gdb_cmd {
|
||||
std::string cmd;
|
||||
std::string data;
|
||||
u8 checksum;
|
||||
} gdb_cmd;
|
||||
|
||||
class wrong_checksum_exception : public std::runtime_error {
|
||||
public:
|
||||
wrong_checksum_exception(char const* const message) : runtime_error(message) {}
|
||||
};
|
||||
|
||||
const u64 ALL_THREADS = 0xffffffffffffffff;
|
||||
const u64 ANY_THREAD = 0;
|
||||
|
||||
class GDBDebugServer : public named_thread {
|
||||
|
||||
socket_t server_socket;
|
||||
socket_t client_socket;
|
||||
std::weak_ptr<cpu_thread> selected_thread;
|
||||
u64 continue_ops_thread_id = ANY_THREAD;
|
||||
u64 general_ops_thread_id = ANY_THREAD;
|
||||
|
||||
//initialize server socket and start listening
|
||||
void start_server();
|
||||
//read at most cnt bytes to buf, returns nubmer of bytes actually read
|
||||
int read(void* buf, int cnt);
|
||||
//reads one character
|
||||
char read_char();
|
||||
//reads pairs of hex characters and returns their integer value
|
||||
u8 read_hexbyte();
|
||||
//tries to read command, throws exceptions if anything goes wrong
|
||||
void try_read_cmd(gdb_cmd& out_cmd);
|
||||
//reads commands until receiveing one with valid checksum
|
||||
//in case of other exception (i.e. wrong first char of command)
|
||||
//it will log exception text and return false
|
||||
//in that case best for caller would be to stop reading, because
|
||||
//chance of getting correct command is low
|
||||
bool read_cmd(gdb_cmd& out_cmd);
|
||||
//send cnt bytes from buf to client
|
||||
void send(const char* buf, int cnt);
|
||||
//send character to client
|
||||
void send_char(char c);
|
||||
//acknowledge packet, either as accepted or declined
|
||||
void ack(bool accepted);
|
||||
//sends command body cmd to client
|
||||
void send_cmd(const std::string & cmd);
|
||||
//sends command to client until receives positive acknowledgement
|
||||
//returns false in case some error happened, and command wasn't sent
|
||||
bool send_cmd_ack(const std::string & cmd);
|
||||
//appends encoded char c to string str, and returns checksum. encoded byte can occupy 2 bytes
|
||||
static u8 append_encoded_char(char c, std::string& str);
|
||||
//convert u8 to 2 byte hexademical representation
|
||||
static std::string to_hexbyte(u8 i);
|
||||
//choose thread, support ALL_THREADS and ANY_THREAD values, returns true if some thread was selected
|
||||
bool select_thread(u64 id);
|
||||
//returns register value as hex string by register id (in gdb), in case of wrong id returns empty string
|
||||
static std::string get_reg(std::shared_ptr<ppu_thread> thread, u32 rid);
|
||||
//sets register value to hex string by register id (in gdb), in case of wrong id returns false
|
||||
static bool set_reg(std::shared_ptr<ppu_thread> thread, u32 rid, std::string value);
|
||||
//returns size of register with id rid in bytes, zero if invalid rid is provided
|
||||
static u32 get_reg_size(std::shared_ptr<ppu_thread> thread, u32 rid);
|
||||
//send reason of stop, returns false if sending response failed
|
||||
bool send_reason();
|
||||
|
||||
//commands
|
||||
bool cmd_extended_mode(gdb_cmd& cmd);
|
||||
bool cmd_reason(gdb_cmd& cmd);
|
||||
bool cmd_supported(gdb_cmd& cmd);
|
||||
bool cmd_thread_info(gdb_cmd& cmd);
|
||||
bool cmd_current_thread(gdb_cmd& cmd);
|
||||
bool cmd_read_register(gdb_cmd& cmd);
|
||||
bool cmd_write_register(gdb_cmd& cmd);
|
||||
bool cmd_read_memory(gdb_cmd& cmd);
|
||||
bool cmd_write_memory(gdb_cmd& cmd);
|
||||
bool cmd_read_all_registers(gdb_cmd& cmd);
|
||||
bool cmd_write_all_registers(gdb_cmd& cmd);
|
||||
bool cmd_set_thread_ops(gdb_cmd& cmd);
|
||||
bool cmd_attached_to_what(gdb_cmd& cmd);
|
||||
bool cmd_kill(gdb_cmd& cmd);
|
||||
bool cmd_continue_support(gdb_cmd& cmd);
|
||||
bool cmd_vcont(gdb_cmd& cmd);
|
||||
bool cmd_set_breakpoint(gdb_cmd& cmd);
|
||||
bool cmd_remove_breakpoint(gdb_cmd& cmd);
|
||||
|
||||
protected:
|
||||
void on_task() override final;
|
||||
void on_exit() override final;
|
||||
|
||||
public:
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 0x100000;
|
||||
|
||||
bool from_breakpoint = true;
|
||||
bool stop = false;
|
||||
|
||||
virtual std::string get_name() const;
|
||||
virtual void on_stop() override final;
|
||||
};
|
||||
|
||||
extern u32 g_gdb_debugger_id;
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma push_macro("new")
|
||||
#undef new
|
||||
#include <gsl/gsl>
|
||||
#include <gsl.h>
|
||||
#pragma pop_macro("new")
|
||||
#undef Expects
|
||||
#undef Ensures
|
||||
|
||||
+196
-351
@@ -5,15 +5,11 @@
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
#include <array>
|
||||
#include <deque>
|
||||
|
||||
#include "types.h"
|
||||
#include "StrFmt.h"
|
||||
#include "File.h"
|
||||
#include "Log.h"
|
||||
#include "mutex.h"
|
||||
#include "sysinfo.h"
|
||||
#include "VirtualMemory.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
@@ -23,19 +19,24 @@
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "JIT.h"
|
||||
|
||||
// Memory manager mutex
|
||||
shared_mutex s_mutex;
|
||||
// Global LLVM context (thread-unsafe)
|
||||
llvm::LLVMContext g_llvm_ctx;
|
||||
|
||||
// Size of virtual memory area reserved: 512 MB
|
||||
static const u64 s_memory_size = 0x20000000;
|
||||
@@ -43,61 +44,40 @@ static const u64 s_memory_size = 0x20000000;
|
||||
// Try to reserve a portion of virtual memory in the first 2 GB address space beforehand, if possible.
|
||||
static void* const s_memory = []() -> void*
|
||||
{
|
||||
llvm::InitializeNativeTarget();
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
LLVMLinkInMCJIT();
|
||||
|
||||
for (u64 addr = 0x10000000; addr <= 0x80000000 - s_memory_size; addr += 0x1000000)
|
||||
#ifdef _WIN32
|
||||
for (u64 addr = 0x10000000; addr <= 0x60000000; addr += 0x1000000)
|
||||
{
|
||||
if (auto ptr = utils::memory_reserve(s_memory_size, (void*)addr))
|
||||
if (VirtualAlloc((void*)addr, s_memory_size, MEM_RESERVE, PAGE_NOACCESS))
|
||||
{
|
||||
return ptr;
|
||||
return (void*)addr;
|
||||
}
|
||||
}
|
||||
|
||||
return utils::memory_reserve(s_memory_size);
|
||||
return VirtualAlloc(NULL, s_memory_size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
return ::mmap((void*)0x10000000, s_memory_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
#endif
|
||||
}();
|
||||
|
||||
static void* s_next = s_memory;
|
||||
// Code section
|
||||
static u8* s_code_addr;
|
||||
static u64 s_code_size;
|
||||
|
||||
// EH frames
|
||||
static u8* s_unwind_info;
|
||||
static u64 s_unwind_size;
|
||||
|
||||
#ifdef _WIN32
|
||||
static std::deque<std::vector<RUNTIME_FUNCTION>> s_unwater;
|
||||
static std::vector<std::vector<RUNTIME_FUNCTION>> s_unwind; // .pdata
|
||||
static std::vector<RUNTIME_FUNCTION> s_unwind; // Custom .pdata section replacement
|
||||
#endif
|
||||
|
||||
// Reset memory manager
|
||||
extern void jit_finalize()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (auto&& unwind : s_unwind)
|
||||
{
|
||||
if (!RtlDeleteFunctionTable(unwind.data()))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable() failed! Error %u", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
s_unwind.clear();
|
||||
#else
|
||||
// TODO: unregister EH frames if necessary
|
||||
#endif
|
||||
|
||||
utils::memory_decommit(s_memory, s_memory_size);
|
||||
|
||||
s_next = s_memory;
|
||||
}
|
||||
|
||||
// Helper class
|
||||
struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||
{
|
||||
std::unordered_map<std::string, u64>& m_link;
|
||||
std::unordered_map<std::string, std::uintptr_t> table;
|
||||
|
||||
std::array<u8, 16>* m_tramps{};
|
||||
|
||||
u8* m_code_addr{}; // TODO
|
||||
|
||||
MemoryManager(std::unordered_map<std::string, u64>& table)
|
||||
: m_link(table)
|
||||
MemoryManager(std::unordered_map<std::string, std::uintptr_t>&& table)
|
||||
: table(std::move(table))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -106,70 +86,31 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
fmt::throw_exception("Null function" HERE);
|
||||
}
|
||||
|
||||
llvm::JITSymbol findSymbol(const std::string& name) override
|
||||
virtual u64 getSymbolAddress(const std::string& name) override
|
||||
{
|
||||
auto& addr = m_link[name];
|
||||
|
||||
// Find function address
|
||||
if (!addr)
|
||||
if (u64 addr = RTDyldMemoryManager::getSymbolAddress(name))
|
||||
{
|
||||
addr = RTDyldMemoryManager::getSymbolAddress(name);
|
||||
|
||||
if (addr)
|
||||
{
|
||||
LOG_WARNING(GENERAL, "LLVM: Symbol requested: %s -> 0x%016llx", name, addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(GENERAL, "LLVM: Linkage failed: %s", name);
|
||||
addr = (u64)null;
|
||||
}
|
||||
// This may be bad if LLVM requests some built-in functions like fma.
|
||||
LOG_ERROR(GENERAL, "LLVM: Symbol requested %s -> 0x%016llx", name, addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
// Verify address for small code model
|
||||
if ((u64)s_memory > 0x80000000 - s_memory_size ? (u64)addr - (u64)s_memory >= s_memory_size : addr >= 0x80000000)
|
||||
const auto found = table.find(name);
|
||||
|
||||
if (found != table.end())
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// Allocate memory for trampolines
|
||||
if (!m_tramps)
|
||||
{
|
||||
m_tramps = reinterpret_cast<decltype(m_tramps)>(s_next);
|
||||
utils::memory_commit(s_next, 4096, utils::protection::wx);
|
||||
s_next = (u8*)((u64)s_next + 4096);
|
||||
}
|
||||
|
||||
// Create a trampoline
|
||||
auto& data = *m_tramps++;
|
||||
data[0x0] = 0xff; // JMP [rip+2]
|
||||
data[0x1] = 0x25;
|
||||
data[0x2] = 0x02;
|
||||
data[0x3] = 0x00;
|
||||
data[0x4] = 0x00;
|
||||
data[0x5] = 0x00;
|
||||
data[0x6] = 0x48; // MOV rax, imm64 (not executed)
|
||||
data[0x7] = 0xb8;
|
||||
std::memcpy(data.data() + 8, &addr, 8);
|
||||
addr = (u64)&data;
|
||||
|
||||
// Reset pointer (memory page exhausted)
|
||||
if (((u64)m_tramps % 4096) == 0)
|
||||
{
|
||||
m_tramps = nullptr;
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
return {addr, llvm::JITSymbolFlags::Exported};
|
||||
// It's fine if some function is never called, for example.
|
||||
LOG_ERROR(GENERAL, "LLVM: Linkage failed for %s", name);
|
||||
return (u64)null;
|
||||
}
|
||||
|
||||
virtual u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// Simple allocation
|
||||
const u64 next = ::align((u64)s_next + size, 4096);
|
||||
const u64 next = ::align((u64)m_next + size, 4096);
|
||||
|
||||
if (next > (u64)s_memory + s_memory_size)
|
||||
{
|
||||
@@ -177,20 +118,27 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
utils::memory_commit(s_next, size, utils::protection::wx);
|
||||
m_code_addr = (u8*)s_next;
|
||||
#ifdef _WIN32
|
||||
if (!VirtualAlloc(m_next, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
|
||||
#else
|
||||
if (::mprotect(m_next, size, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
#endif
|
||||
{
|
||||
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at %p", m_next);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LOG_NOTICE(GENERAL, "LLVM: Code section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x)", sec_id, sec_name.data(), s_next, size, align);
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
s_code_addr = (u8*)m_next;
|
||||
s_code_size = size;
|
||||
|
||||
LOG_SUCCESS(GENERAL, "LLVM: Code section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x)", sec_id, sec_name.data(), m_next, size, align);
|
||||
return (u8*)std::exchange(m_next, (void*)next);
|
||||
}
|
||||
|
||||
virtual u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// Simple allocation
|
||||
const u64 next = ::align((u64)s_next + size, 4096);
|
||||
const u64 next = ::align((u64)m_next + size, 4096);
|
||||
|
||||
if (next > (u64)s_memory + s_memory_size)
|
||||
{
|
||||
@@ -203,298 +151,195 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
LOG_ERROR(GENERAL, "LLVM: Writeable data section not supported!");
|
||||
}
|
||||
|
||||
utils::memory_commit(s_next, size);
|
||||
#ifdef _WIN32
|
||||
if (!VirtualAlloc(m_next, size, MEM_COMMIT, PAGE_READWRITE))
|
||||
#else
|
||||
if (::mprotect(m_next, size, PROT_READ | PROT_WRITE))
|
||||
#endif
|
||||
{
|
||||
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at %p", m_next);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LOG_NOTICE(GENERAL, "LLVM: Data section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), s_next, size, align, is_ro ? "ro" : "rw");
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
LOG_SUCCESS(GENERAL, "LLVM: Data section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), m_next, size, align, is_ro ? "ro" : "rw");
|
||||
return (u8*)std::exchange(m_next, (void*)next);
|
||||
}
|
||||
|
||||
virtual bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// TODO: make only read-only sections read-only
|
||||
//#ifdef _WIN32
|
||||
// DWORD op;
|
||||
// VirtualProtect(s_memory, (u64)m_next - (u64)s_memory, PAGE_READONLY, &op);
|
||||
// VirtualProtect(s_code_addr, s_code_size, PAGE_EXECUTE_READ, &op);
|
||||
//#else
|
||||
// ::mprotect(s_memory, (u64)m_next - (u64)s_memory, PROT_READ);
|
||||
// ::mprotect(s_code_addr, s_code_size, PROT_READ | PROT_EXEC);
|
||||
//#endif
|
||||
#ifdef _WIN32
|
||||
DWORD op;
|
||||
VirtualProtect(s_memory, (u64)m_next - (u64)s_memory, PAGE_READONLY, &op);
|
||||
VirtualProtect(s_code_addr, s_code_size, PAGE_EXECUTE_READ, &op);
|
||||
#else
|
||||
::mprotect(s_memory, (u64)m_next - (u64)s_memory, PROT_READ);
|
||||
::mprotect(s_code_addr, s_code_size, PROT_READ | PROT_EXEC);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// Use s_memory as a BASE, compute the difference
|
||||
const u64 unwind_diff = (u64)addr - (u64)s_memory;
|
||||
|
||||
// Fix RUNTIME_FUNCTION records (.pdata section)
|
||||
auto pdata = std::move(s_unwater.front());
|
||||
s_unwater.pop_front();
|
||||
|
||||
for (auto& rf : pdata)
|
||||
{
|
||||
rf.UnwindData += static_cast<DWORD>(unwind_diff);
|
||||
}
|
||||
|
||||
// Register .xdata UNWIND_INFO structs
|
||||
if (!RtlAddFunctionTable(pdata.data(), (DWORD)pdata.size(), (u64)s_memory))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "RtlAddFunctionTable() failed! Error %u", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
s_unwind.emplace_back(std::move(pdata));
|
||||
}
|
||||
#endif
|
||||
s_unwind_info = addr;
|
||||
s_unwind_size = size;
|
||||
|
||||
return RTDyldMemoryManager::registerEHFrames(addr, load_addr, size);
|
||||
}
|
||||
|
||||
virtual void deregisterEHFrames() override
|
||||
virtual void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
LOG_ERROR(GENERAL, "deregisterEHFrames() called"); // Not expected
|
||||
|
||||
return RTDyldMemoryManager::deregisterEHFrames();
|
||||
}
|
||||
};
|
||||
|
||||
// Helper class
|
||||
struct EventListener : llvm::JITEventListener
|
||||
{
|
||||
MemoryManager& m_mem;
|
||||
|
||||
EventListener(MemoryManager& mem)
|
||||
: m_mem(mem)
|
||||
{
|
||||
return RTDyldMemoryManager::deregisterEHFrames(addr, load_addr, size);
|
||||
}
|
||||
|
||||
virtual void NotifyObjectEmitted(const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
|
||||
~MemoryManager()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (auto it = obj.section_begin(), end = obj.section_end(); it != end; ++it)
|
||||
if (!RtlDeleteFunctionTable(s_unwind.data()))
|
||||
{
|
||||
llvm::StringRef name;
|
||||
it->getName(name);
|
||||
|
||||
if (name == ".pdata")
|
||||
{
|
||||
llvm::StringRef data;
|
||||
it->getContents(data);
|
||||
|
||||
std::vector<RUNTIME_FUNCTION> rfs(data.size() / sizeof(RUNTIME_FUNCTION));
|
||||
|
||||
auto offsets = reinterpret_cast<DWORD*>(rfs.data());
|
||||
|
||||
// Initialize .pdata section using relocation info
|
||||
for (auto ri = it->relocation_begin(), end = it->relocation_end(); ri != end; ++ri)
|
||||
{
|
||||
if (ri->getType() == 3 /*R_X86_64_GOT32*/)
|
||||
{
|
||||
const u64 value = *reinterpret_cast<const DWORD*>(data.data() + ri->getOffset());
|
||||
offsets[ri->getOffset() / sizeof(DWORD)] = static_cast<DWORD>(value + ri->getSymbol()->getAddress().get());
|
||||
}
|
||||
}
|
||||
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
// Use s_memory as a BASE, compute the difference
|
||||
const u64 code_diff = (u64)m_mem.m_code_addr - (u64)s_memory;
|
||||
|
||||
// Fix RUNTIME_FUNCTION records (.pdata section)
|
||||
for (auto& rf : rfs)
|
||||
{
|
||||
rf.BeginAddress += static_cast<DWORD>(code_diff);
|
||||
rf.EndAddress += static_cast<DWORD>(code_diff);
|
||||
}
|
||||
|
||||
s_unwater.emplace_back(std::move(rfs));
|
||||
}
|
||||
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
}
|
||||
|
||||
if (!VirtualFree(s_memory, 0, MEM_DECOMMIT))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "VirtualFree(%p) failed! Error %u", s_memory, GetLastError());
|
||||
}
|
||||
#else
|
||||
if (::mprotect(s_memory, s_memory_size, PROT_NONE))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "mprotect(%p) failed! Error %d", s_memory, errno);
|
||||
}
|
||||
|
||||
// TODO: unregister EH frames if necessary
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void* m_next = s_memory;
|
||||
};
|
||||
|
||||
// Helper class
|
||||
class ObjectCache final : public llvm::ObjectCache
|
||||
struct EventListener final : llvm::JITEventListener
|
||||
{
|
||||
const std::string& m_path;
|
||||
|
||||
public:
|
||||
ObjectCache(const std::string& path)
|
||||
: m_path(path)
|
||||
virtual void NotifyObjectEmitted(const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
|
||||
{
|
||||
}
|
||||
|
||||
~ObjectCache() override = default;
|
||||
|
||||
void notifyObjectCompiled(const llvm::Module* module, llvm::MemoryBufferRef obj) override
|
||||
{
|
||||
std::string name = m_path;
|
||||
name.append(module->getName());
|
||||
fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize());
|
||||
LOG_SUCCESS(GENERAL, "LLVM: Created module: %s", module->getName().data());
|
||||
}
|
||||
|
||||
static std::unique_ptr<llvm::MemoryBuffer> load(const std::string& path)
|
||||
{
|
||||
if (fs::file cached{path, fs::read})
|
||||
{
|
||||
auto buf = llvm::MemoryBuffer::getNewUninitMemBuffer(cached.size());
|
||||
cached.read(const_cast<char*>(buf->getBufferStart()), buf->getBufferSize());
|
||||
return buf;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* module) override
|
||||
{
|
||||
std::string path = m_path;
|
||||
path.append(module->getName());
|
||||
|
||||
if (auto buf = load(path))
|
||||
{
|
||||
LOG_SUCCESS(GENERAL, "LLVM: Loaded module: %s", module->getName().data());
|
||||
return buf;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
const llvm::StringRef elf = obj.getData();
|
||||
fs::file(fs::get_config_dir() + "LLVM.obj", fs::rewrite)
|
||||
.write(elf.data(), elf.size());
|
||||
}
|
||||
};
|
||||
|
||||
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, std::string _cpu)
|
||||
: m_link(std::move(_link))
|
||||
, m_cpu(std::move(_cpu))
|
||||
{
|
||||
if (m_cpu.empty())
|
||||
{
|
||||
m_cpu = llvm::sys::getHostCPUName();
|
||||
static EventListener s_listener;
|
||||
|
||||
if (m_cpu == "sandybridge" ||
|
||||
m_cpu == "ivybridge" ||
|
||||
m_cpu == "haswell" ||
|
||||
m_cpu == "broadwell" ||
|
||||
m_cpu == "skylake" ||
|
||||
m_cpu == "skylake-avx512" ||
|
||||
m_cpu == "cannonlake")
|
||||
{
|
||||
if (!utils::has_avx())
|
||||
{
|
||||
m_cpu = "nehalem";
|
||||
}
|
||||
}
|
||||
}
|
||||
jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unordered_map<std::string, std::uintptr_t>&& table)
|
||||
{
|
||||
verify(HERE), s_memory;
|
||||
|
||||
std::string result;
|
||||
|
||||
if (m_link.empty())
|
||||
{
|
||||
// Auxiliary JIT (does not use custom memory manager, only writes the objects)
|
||||
m_engine.reset(llvm::EngineBuilder(std::make_unique<llvm::Module>("null_", m_context))
|
||||
.setErrorStr(&result)
|
||||
.setOptLevel(llvm::CodeGenOpt::Aggressive)
|
||||
.setCodeModel(llvm::CodeModel::Small)
|
||||
.setMCPU(m_cpu)
|
||||
.create());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Primary JIT
|
||||
auto mem = std::make_unique<MemoryManager>(m_link);
|
||||
m_jit_el = std::make_unique<EventListener>(*mem);
|
||||
const auto module_ptr = _module.get();
|
||||
|
||||
m_engine.reset(llvm::EngineBuilder(std::make_unique<llvm::Module>("null", m_context))
|
||||
.setErrorStr(&result)
|
||||
.setMCJITMemoryManager(std::move(mem))
|
||||
.setOptLevel(llvm::CodeGenOpt::Aggressive)
|
||||
.setCodeModel(llvm::CodeModel::Small)
|
||||
.setMCPU(m_cpu)
|
||||
.create());
|
||||
// Initialization
|
||||
llvm::InitializeNativeTarget();
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
LLVMLinkInMCJIT();
|
||||
const auto _cpu = llvm::sys::getHostCPUName();
|
||||
|
||||
if (m_engine)
|
||||
{
|
||||
m_engine->RegisterJITEventListener(m_jit_el.get());
|
||||
}
|
||||
}
|
||||
m_engine.reset(llvm::EngineBuilder(std::move(_module))
|
||||
.setErrorStr(&result)
|
||||
.setMCJITMemoryManager(std::make_unique<MemoryManager>(std::move(table)))
|
||||
.setOptLevel(llvm::CodeGenOpt::Aggressive)
|
||||
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Small : llvm::CodeModel::Large) // TODO
|
||||
.setMCPU(_cpu == "skylake" ? "haswell" : _cpu)
|
||||
.create());
|
||||
|
||||
if (!m_engine)
|
||||
{
|
||||
fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result);
|
||||
}
|
||||
|
||||
m_engine->setProcessAllSections(true); // ???
|
||||
m_engine->RegisterJITEventListener(&s_listener);
|
||||
m_engine->finalizeObject();
|
||||
|
||||
for (auto& func : module_ptr->functions())
|
||||
{
|
||||
if (!func.empty())
|
||||
{
|
||||
const std::string& name = func.getName();
|
||||
|
||||
// Register compiled function
|
||||
m_map[name] = m_engine->getFunctionAddress(name);
|
||||
}
|
||||
|
||||
// Delete IR to lower memory consumption
|
||||
func.deleteBody();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register .xdata UNWIND_INFO (.pdata section is empty for some reason)
|
||||
std::set<u64> func_set;
|
||||
|
||||
for (const auto& pair : m_map)
|
||||
{
|
||||
func_set.emplace(pair.second);
|
||||
}
|
||||
|
||||
const u64 base = (u64)s_memory;
|
||||
const u8* bits = s_unwind_info;
|
||||
|
||||
s_unwind.clear();
|
||||
s_unwind.reserve(m_map.size());
|
||||
|
||||
for (const u64 addr : func_set)
|
||||
{
|
||||
// Find next function address
|
||||
const auto _next = func_set.upper_bound(addr);
|
||||
const u64 next = _next != func_set.end() ? *_next : (u64)s_code_addr + s_code_size;
|
||||
|
||||
// Generate RUNTIME_FUNCTION record
|
||||
RUNTIME_FUNCTION uw;
|
||||
uw.BeginAddress = static_cast<u32>(addr - base);
|
||||
uw.EndAddress = static_cast<u32>(next - base);
|
||||
uw.UnwindData = static_cast<u32>((u64)bits - base);
|
||||
s_unwind.emplace_back(uw);
|
||||
|
||||
// Parse .xdata UNWIND_INFO record
|
||||
const u8 flags = *bits++; // Version and flags
|
||||
const u8 prolog = *bits++; // Size of prolog
|
||||
const u8 count = *bits++; // Count of unwind codes
|
||||
const u8 frame = *bits++; // Frame Reg + Off
|
||||
bits += ::align(std::max<u8>(1, count), 2) * sizeof(u16); // UNWIND_CODE array
|
||||
|
||||
if (flags != 1)
|
||||
{
|
||||
// Can't happen for trivial code
|
||||
LOG_ERROR(GENERAL, "LLVM: unsupported UNWIND_INFO version/flags (0x%02x)", flags);
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_TRACE(GENERAL, "LLVM: .xdata at 0x%llx: function 0x%x..0x%x: p0x%02x, c0x%02x, f0x%02x", uw.UnwindData + base, uw.BeginAddress + base, uw.EndAddress + base, prolog, count, frame);
|
||||
}
|
||||
|
||||
if (s_unwind_info + s_unwind_size != bits)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "LLVM: .xdata analysis failed! (%p != %p)", s_unwind_info + s_unwind_size, bits);
|
||||
}
|
||||
else if (!RtlAddFunctionTable(s_unwind.data(), (DWORD)s_unwind.size(), base))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "RtlAddFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (%p, size=0x%llx)", s_unwind_info, s_unwind_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
jit_compiler::~jit_compiler()
|
||||
{
|
||||
}
|
||||
|
||||
void jit_compiler::add(std::unique_ptr<llvm::Module> module, const std::string& path)
|
||||
{
|
||||
ObjectCache cache{path};
|
||||
m_engine->setObjectCache(&cache);
|
||||
|
||||
const auto ptr = module.get();
|
||||
m_engine->addModule(std::move(module));
|
||||
m_engine->generateCodeForModule(ptr);
|
||||
m_engine->setObjectCache(nullptr);
|
||||
|
||||
for (auto& func : ptr->functions())
|
||||
{
|
||||
// Delete IR to lower memory consumption
|
||||
func.deleteBody();
|
||||
}
|
||||
}
|
||||
|
||||
void jit_compiler::add(const std::string& path)
|
||||
{
|
||||
m_engine->addObjectFile(std::move(llvm::object::ObjectFile::createObjectFile(*ObjectCache::load(path)).get()));
|
||||
}
|
||||
|
||||
void jit_compiler::fin()
|
||||
{
|
||||
m_engine->finalizeObject();
|
||||
}
|
||||
|
||||
u64 jit_compiler::get(const std::string& name)
|
||||
{
|
||||
return m_engine->getGlobalValueAddress(name);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, u64> jit_compiler::add(std::unordered_map<std::string, std::string> data)
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
|
||||
std::unordered_map<std::string, u64> result;
|
||||
|
||||
std::size_t size = 0;
|
||||
|
||||
for (auto&& pair : data)
|
||||
{
|
||||
size += ::align(pair.second.size(), 16);
|
||||
}
|
||||
|
||||
utils::memory_commit(s_next, size, utils::protection::wx);
|
||||
std::memset(s_next, 0xc3, ::align(size, 4096));
|
||||
|
||||
for (auto&& pair : data)
|
||||
{
|
||||
std::memcpy(s_next, pair.second.data(), pair.second.size());
|
||||
result.emplace(pair.first, (u64)s_next);
|
||||
s_next = (void*)::align((u64)s_next + pair.second.size(), 16);
|
||||
}
|
||||
|
||||
s_next = (void*)::align((u64)s_next, 4096);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
-43
@@ -7,9 +7,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "types.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include "restore_new.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
@@ -19,61 +17,33 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
extern llvm::LLVMContext g_llvm_ctx;
|
||||
|
||||
// Temporary compiler interface
|
||||
class jit_compiler final
|
||||
{
|
||||
// Local LLVM context
|
||||
llvm::LLVMContext m_context;
|
||||
|
||||
// JIT Event Listener
|
||||
std::unique_ptr<struct EventListener> m_jit_el;
|
||||
|
||||
// Execution instance
|
||||
std::unique_ptr<llvm::ExecutionEngine> m_engine;
|
||||
|
||||
// Link table
|
||||
std::unordered_map<std::string, u64> m_link;
|
||||
|
||||
// Arch
|
||||
std::string m_cpu;
|
||||
// Compiled functions
|
||||
std::unordered_map<std::string, std::uintptr_t> m_map;
|
||||
|
||||
public:
|
||||
jit_compiler(const std::unordered_map<std::string, u64>& _link, std::string _cpu);
|
||||
jit_compiler(std::unique_ptr<llvm::Module>&&, std::unordered_map<std::string, std::uintptr_t>&&);
|
||||
~jit_compiler();
|
||||
|
||||
// Get LLVM context
|
||||
auto& get_context()
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
// Add module (path to obj cache dir)
|
||||
void add(std::unique_ptr<llvm::Module> module, const std::string& path);
|
||||
|
||||
// Add object (path to obj file)
|
||||
void add(const std::string& path);
|
||||
|
||||
// Finalize
|
||||
void fin();
|
||||
|
||||
// Get compiled function address
|
||||
u64 get(const std::string& name);
|
||||
|
||||
// Add functions directly to the memory manager (name -> code)
|
||||
static std::unordered_map<std::string, u64> add(std::unordered_map<std::string, std::string>);
|
||||
|
||||
// Get CPU info
|
||||
const std::string& cpu() const
|
||||
std::uintptr_t get(const std::string& name) const
|
||||
{
|
||||
return m_cpu;
|
||||
}
|
||||
const auto found = m_map.find(name);
|
||||
|
||||
if (found != m_map.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
// Check JIT purpose
|
||||
bool is_primary() const
|
||||
{
|
||||
return !m_link.empty();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "LUrlParser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
|
||||
// check if the scheme name is valid
|
||||
static bool IsSchemeValid( const std::string& SchemeName )
|
||||
{
|
||||
for ( auto c : SchemeName )
|
||||
{
|
||||
if ( !isalpha( c ) && c != '+' && c != '-' && c != '.' ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LUrlParser::clParseURL::GetPort( int* OutPort ) const
|
||||
{
|
||||
if ( !IsValid() ) { return false; }
|
||||
|
||||
int Port = atoi( m_Port.c_str() );
|
||||
|
||||
if ( Port <= 0 || Port > 65535 ) { return false; }
|
||||
|
||||
if ( OutPort ) { *OutPort = Port; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// based on RFC 1738 and RFC 3986
|
||||
LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL )
|
||||
{
|
||||
LUrlParser::clParseURL Result;
|
||||
|
||||
const char* CurrentString = URL.c_str();
|
||||
|
||||
/*
|
||||
* <scheme>:<scheme-specific-part>
|
||||
* <scheme> := [a-z\+\-\.]+
|
||||
* For resiliency, programs interpreting URLs should treat upper case letters as equivalent to lower case in scheme names
|
||||
*/
|
||||
|
||||
// try to read scheme
|
||||
{
|
||||
const char* LocalString = strchr( CurrentString, ':' );
|
||||
|
||||
if ( !LocalString )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoUrlCharacter );
|
||||
}
|
||||
|
||||
// save the scheme name
|
||||
Result.m_Scheme = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
if ( !IsSchemeValid( Result.m_Scheme ) )
|
||||
{
|
||||
return clParseURL( LUrlParserError_InvalidSchemeName );
|
||||
}
|
||||
|
||||
// scheme should be lowercase
|
||||
std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower );
|
||||
|
||||
// skip ':'
|
||||
CurrentString = LocalString+1;
|
||||
}
|
||||
|
||||
/*
|
||||
* //<user>:<password>@<host>:<port>/<url-path>
|
||||
* any ":", "@" and "/" must be normalized
|
||||
*/
|
||||
|
||||
// skip "//"
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash );
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash );
|
||||
|
||||
// check if the user name and password are specified
|
||||
bool bHasUserName = false;
|
||||
|
||||
const char* LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString )
|
||||
{
|
||||
if ( *LocalString == '@' )
|
||||
{
|
||||
// user name and password are specified
|
||||
bHasUserName = true;
|
||||
break;
|
||||
}
|
||||
else if ( *LocalString == '/' )
|
||||
{
|
||||
// end of <host>:<port> specification
|
||||
bHasUserName = false;
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
// user name and password
|
||||
LocalString = CurrentString;
|
||||
|
||||
if ( bHasUserName )
|
||||
{
|
||||
// read user name
|
||||
while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++;
|
||||
|
||||
Result.m_UserName = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
// proceed with the current pointer
|
||||
CurrentString = LocalString;
|
||||
|
||||
if ( *CurrentString == ':' )
|
||||
{
|
||||
// skip ':'
|
||||
CurrentString++;
|
||||
|
||||
// read password
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '@' ) LocalString++;
|
||||
|
||||
Result.m_Password = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// skip '@'
|
||||
if ( *CurrentString != '@' )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoAtSign );
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
}
|
||||
|
||||
bool bHasBracket = ( *CurrentString == '[' );
|
||||
|
||||
// go ahead, read the host name
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString )
|
||||
{
|
||||
if ( bHasBracket && *LocalString == ']' )
|
||||
{
|
||||
// end of IPv6 address
|
||||
LocalString++;
|
||||
break;
|
||||
}
|
||||
else if ( !bHasBracket && ( *LocalString == ':' || *LocalString == '/' ) )
|
||||
{
|
||||
// port number is specified
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
Result.m_Host = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// is port number specified?
|
||||
if ( *CurrentString == ':' )
|
||||
{
|
||||
CurrentString++;
|
||||
|
||||
// read port number
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '/' ) LocalString++;
|
||||
|
||||
Result.m_Port = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// end of string
|
||||
if ( !*CurrentString )
|
||||
{
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// skip '/'
|
||||
if ( *CurrentString != '/' )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoSlash );
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
|
||||
// parse the path
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++;
|
||||
|
||||
Result.m_Path = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// check for query
|
||||
if ( *CurrentString == '?' )
|
||||
{
|
||||
// skip '?'
|
||||
CurrentString++;
|
||||
|
||||
// read query
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '#' ) LocalString++;
|
||||
|
||||
Result.m_Query = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// check for fragment
|
||||
if ( *CurrentString == '#' )
|
||||
{
|
||||
// skip '#'
|
||||
CurrentString++;
|
||||
|
||||
// read fragment
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString ) LocalString++;
|
||||
|
||||
Result.m_Fragment = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace LUrlParser
|
||||
{
|
||||
enum LUrlParserError
|
||||
{
|
||||
LUrlParserError_Ok = 0,
|
||||
LUrlParserError_Uninitialized = 1,
|
||||
LUrlParserError_NoUrlCharacter = 2,
|
||||
LUrlParserError_InvalidSchemeName = 3,
|
||||
LUrlParserError_NoDoubleSlash = 4,
|
||||
LUrlParserError_NoAtSign = 5,
|
||||
LUrlParserError_UnexpectedEndOfLine = 6,
|
||||
LUrlParserError_NoSlash = 7,
|
||||
};
|
||||
|
||||
class clParseURL
|
||||
{
|
||||
public:
|
||||
LUrlParserError m_ErrorCode;
|
||||
std::string m_Scheme;
|
||||
std::string m_Host;
|
||||
std::string m_Port;
|
||||
std::string m_Path;
|
||||
std::string m_Query;
|
||||
std::string m_Fragment;
|
||||
std::string m_UserName;
|
||||
std::string m_Password;
|
||||
|
||||
clParseURL()
|
||||
: m_ErrorCode( LUrlParserError_Uninitialized )
|
||||
{}
|
||||
|
||||
/// return 'true' if the parsing was successful
|
||||
bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; }
|
||||
|
||||
/// helper to convert the port number to int, return 'true' if the port is valid (within the 0..65535 range)
|
||||
bool GetPort( int* OutPort ) const;
|
||||
|
||||
/// parse the URL
|
||||
static clParseURL ParseURL( const std::string& URL );
|
||||
|
||||
private:
|
||||
explicit clParseURL( LUrlParserError ErrorCode )
|
||||
: m_ErrorCode( ErrorCode )
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace LUrlParser
|
||||
+34
-315
@@ -1,30 +1,12 @@
|
||||
#include "Log.h"
|
||||
#include "File.h"
|
||||
#include "StrFmt.h"
|
||||
#include "sema.h"
|
||||
|
||||
#include "Utilities/sysinfo.h"
|
||||
#include "rpcs3_version.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <chrono>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
static std::string empty_string()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// Thread-specific log prefix provider
|
||||
thread_local std::string(*g_tls_log_prefix)() = &empty_string;
|
||||
thread_local std::string(*g_tls_log_prefix)() = nullptr;
|
||||
|
||||
template<>
|
||||
void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
@@ -49,71 +31,32 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
|
||||
namespace logs
|
||||
{
|
||||
constexpr std::size_t s_log_size = 128 * 1024 * 1024;
|
||||
constexpr std::size_t s_log_size_s = s_log_size / 2;
|
||||
constexpr std::size_t s_log_size_t = s_log_size / 4 + s_log_size_s;
|
||||
constexpr std::size_t s_log_size_e = s_log_size / 8 + s_log_size_t;
|
||||
constexpr std::size_t s_log_size_f = s_log_size / 16 + s_log_size_e;
|
||||
|
||||
class file_writer
|
||||
{
|
||||
// Could be memory-mapped file
|
||||
fs::file m_file;
|
||||
std::string m_name;
|
||||
|
||||
#ifdef _WIN32
|
||||
::HANDLE m_fmap;
|
||||
#endif
|
||||
atomic_t<std::size_t> m_pos{0};
|
||||
std::size_t m_size{0};
|
||||
uchar* m_fptr{};
|
||||
|
||||
public:
|
||||
file_writer(const std::string& name);
|
||||
|
||||
virtual ~file_writer();
|
||||
virtual ~file_writer() = default;
|
||||
|
||||
// Append raw data
|
||||
void log(logs::level sev, const char* text, std::size_t size);
|
||||
};
|
||||
|
||||
struct channel_info
|
||||
{
|
||||
channel* pointer = nullptr;
|
||||
level enabled = level::notice;
|
||||
|
||||
void set_level(level value)
|
||||
{
|
||||
enabled = value;
|
||||
|
||||
if (pointer)
|
||||
{
|
||||
pointer->enabled = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct stored_message
|
||||
{
|
||||
message m;
|
||||
u64 stamp;
|
||||
std::string prefix;
|
||||
std::string text;
|
||||
void log(const char* text, std::size_t size);
|
||||
};
|
||||
|
||||
struct file_listener : public file_writer, public listener
|
||||
{
|
||||
file_listener(const std::string& name);
|
||||
|
||||
virtual ~file_listener() = default;
|
||||
file_listener(const std::string& name)
|
||||
: file_writer(name)
|
||||
, listener()
|
||||
{
|
||||
const std::string& start = fmt::format("\xEF\xBB\xBF" "RPCS3 v%s\n", rpcs3::version.to_string());
|
||||
file_writer::log(start.data(), start.size());
|
||||
}
|
||||
|
||||
// Encode level, current thread name, channel name and write log message
|
||||
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) override;
|
||||
|
||||
// Channel registry
|
||||
std::unordered_map<std::string, channel_info> channels;
|
||||
|
||||
// Messages for delayed listener initialization
|
||||
std::vector<stored_message> messages;
|
||||
virtual void log(const message& msg, const std::string& prefix, const std::string& text) override;
|
||||
};
|
||||
|
||||
static file_listener* get_logger()
|
||||
@@ -123,85 +66,14 @@ namespace logs
|
||||
return &logger;
|
||||
}
|
||||
|
||||
static u64 get_stamp()
|
||||
{
|
||||
static struct time_initializer
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER start;
|
||||
|
||||
time_initializer()
|
||||
{
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&start);
|
||||
}
|
||||
#else
|
||||
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
|
||||
#endif
|
||||
|
||||
u64 get() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
const LONGLONG diff = now.QuadPart - start.QuadPart;
|
||||
return diff / freq.QuadPart * 1'000'000 + diff % freq.QuadPart * 1'000'000 / freq.QuadPart;
|
||||
#else
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
|
||||
#endif
|
||||
}
|
||||
} timebase{};
|
||||
|
||||
return timebase.get();
|
||||
}
|
||||
|
||||
channel GENERAL("");
|
||||
channel LOADER("LDR");
|
||||
channel MEMORY("MEM");
|
||||
channel RSX("RSX");
|
||||
channel HLE("HLE");
|
||||
channel PPU("PPU");
|
||||
channel SPU("SPU");
|
||||
channel GENERAL(nullptr, level::notice);
|
||||
channel LOADER("LDR", level::notice);
|
||||
channel MEMORY("MEM", level::notice);
|
||||
channel RSX("RSX", level::notice);
|
||||
channel HLE("HLE", level::notice);
|
||||
channel PPU("PPU", level::notice);
|
||||
channel SPU("SPU", level::notice);
|
||||
channel ARMv7("ARMv7");
|
||||
|
||||
// Channel registry mutex
|
||||
semaphore<> g_mutex;
|
||||
|
||||
// Must be set to true in main()
|
||||
atomic_t<bool> g_init{false};
|
||||
|
||||
void reset()
|
||||
{
|
||||
semaphore_lock lock(g_mutex);
|
||||
|
||||
for (auto&& pair : get_logger()->channels)
|
||||
{
|
||||
pair.second.set_level(level::notice);
|
||||
}
|
||||
}
|
||||
|
||||
void set_level(const std::string& ch_name, level value)
|
||||
{
|
||||
semaphore_lock lock(g_mutex);
|
||||
|
||||
get_logger()->channels[ch_name].set_level(value);
|
||||
}
|
||||
|
||||
// Must be called in main() to stop accumulating messages in g_messages
|
||||
void set_init()
|
||||
{
|
||||
if (!g_init)
|
||||
{
|
||||
semaphore_lock lock(g_mutex);
|
||||
get_logger()->messages.clear();
|
||||
g_init = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logs::listener::~listener()
|
||||
{
|
||||
}
|
||||
|
||||
void logs::listener::add(logs::listener* _new)
|
||||
@@ -209,79 +81,25 @@ void logs::listener::add(logs::listener* _new)
|
||||
// Get first (main) listener
|
||||
listener* lis = get_logger();
|
||||
|
||||
semaphore_lock lock(g_mutex);
|
||||
|
||||
// Install new listener at the end of linked list
|
||||
while (lis->m_next || !lis->m_next.compare_and_swap_test(nullptr, _new))
|
||||
{
|
||||
lis = lis->m_next;
|
||||
}
|
||||
|
||||
// Send initial messages
|
||||
for (const auto& msg : get_logger()->messages)
|
||||
{
|
||||
_new->log(msg.stamp, msg.m, msg.prefix, msg.text);
|
||||
}
|
||||
}
|
||||
|
||||
void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u64* args)
|
||||
{
|
||||
// Get timestamp
|
||||
const u64 stamp = get_stamp();
|
||||
|
||||
// Register channel
|
||||
if (ch->enabled == level::_uninit)
|
||||
{
|
||||
semaphore_lock lock(g_mutex);
|
||||
|
||||
auto& info = get_logger()->channels[ch->name];
|
||||
|
||||
if (info.pointer && info.pointer != ch)
|
||||
{
|
||||
fmt::throw_exception("logs::channel repetition: %s", ch->name);
|
||||
}
|
||||
else if (!info.pointer)
|
||||
{
|
||||
info.pointer = ch;
|
||||
ch->enabled = info.enabled;
|
||||
|
||||
// Check level again
|
||||
if (info.enabled < sev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get text
|
||||
thread_local std::string text; text.clear();
|
||||
fmt::raw_append(text, fmt, sup, args);
|
||||
std::string prefix = g_tls_log_prefix();
|
||||
std::string text; fmt::raw_append(text, fmt, sup, args);
|
||||
std::string prefix(g_tls_log_prefix ? g_tls_log_prefix() : "");
|
||||
|
||||
// Get first (main) listener
|
||||
listener* lis = get_logger();
|
||||
|
||||
if (!g_init)
|
||||
{
|
||||
semaphore_lock lock(g_mutex);
|
||||
|
||||
if (!g_init)
|
||||
{
|
||||
while (lis)
|
||||
{
|
||||
lis->log(stamp, *this, prefix, text);
|
||||
lis = lis->m_next;
|
||||
}
|
||||
|
||||
// Store message additionally
|
||||
get_logger()->messages.emplace_back(stored_message{*this, stamp, std::move(prefix), text});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Send message to all listeners
|
||||
while (lis)
|
||||
{
|
||||
lis->log(stamp, *this, prefix, text);
|
||||
lis->log(*this, prefix, text);
|
||||
lis = lis->m_next;
|
||||
}
|
||||
}
|
||||
@@ -289,30 +107,13 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u
|
||||
[[noreturn]] extern void catch_all_exceptions();
|
||||
|
||||
logs::file_writer::file_writer(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
|
||||
{
|
||||
fmt::throw_exception("Can't create file %s (error %s)", name, fs::g_tls_error);
|
||||
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
m_fmap = CreateFileMappingW(m_file.get_handle(), 0, PAGE_READWRITE, s_log_size >> 32, s_log_size & 0xffffffff, 0);
|
||||
m_fptr = m_fmap ? (uchar*)MapViewOfFile(m_fmap, FILE_MAP_WRITE, 0, 0, 0) : nullptr;
|
||||
#else
|
||||
m_file.trunc(s_log_size);
|
||||
m_fptr = (uchar*)::mmap(0, s_log_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_file.get_handle(), 0);
|
||||
#endif
|
||||
|
||||
verify(name.c_str()), m_fptr;
|
||||
std::memset(m_fptr, '\n', s_log_size);
|
||||
|
||||
// Rotate backups (TODO)
|
||||
fs::remove_file(fs::get_config_dir() + name + "1.gz");
|
||||
fs::create_dir(fs::get_config_dir() + "old_logs");
|
||||
fs::rename(fs::get_config_dir() + m_name + ".gz", fs::get_config_dir() + "old_logs/" + m_name + ".gz", true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -320,91 +121,14 @@ logs::file_writer::file_writer(const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
logs::file_writer::~file_writer()
|
||||
void logs::file_writer::log(const char* text, std::size_t size)
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
m_size = std::min<std::size_t>(+m_pos, s_log_size);
|
||||
}
|
||||
|
||||
// Compress
|
||||
z_stream zs{};
|
||||
if (deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY) == Z_OK)
|
||||
{
|
||||
auto buf = std::make_unique<uchar[]>(s_log_size);
|
||||
zs.avail_in = ::narrow<u32>(m_size);
|
||||
zs.avail_out = s_log_size;
|
||||
zs.next_in = m_fptr;
|
||||
zs.next_out = buf.get();
|
||||
|
||||
if (deflate(&zs, Z_FINISH) != Z_STREAM_ERROR)
|
||||
{
|
||||
fs::file(fs::get_config_dir() + m_name + ".gz", fs::rewrite).write(buf.get(), zs.total_out);
|
||||
}
|
||||
|
||||
if (deflateEnd(&zs) != Z_OK)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile(m_fptr);
|
||||
CloseHandle(m_fmap);
|
||||
#else
|
||||
::munmap(m_fptr, s_log_size);
|
||||
#endif
|
||||
m_file.trunc(m_size);
|
||||
m_file.write(text, size);
|
||||
}
|
||||
|
||||
void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
|
||||
void logs::file_listener::log(const logs::message& msg, const std::string& prefix, const std::string& _text)
|
||||
{
|
||||
// Adaptive log limit
|
||||
const auto lim =
|
||||
sev >= logs::level::success ? s_log_size_s :
|
||||
sev == logs::level::todo ? s_log_size_t :
|
||||
sev == logs::level::error ? s_log_size_e : s_log_size_f;
|
||||
|
||||
if (m_pos >= lim)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire memory
|
||||
const auto pos = m_pos.fetch_add(size);
|
||||
|
||||
// Write if possible
|
||||
if (pos + size <= s_log_size)
|
||||
{
|
||||
std::memcpy(m_fptr + pos, text, size);
|
||||
}
|
||||
else if (pos <= s_log_size)
|
||||
{
|
||||
m_size = pos;
|
||||
}
|
||||
}
|
||||
|
||||
logs::file_listener::file_listener(const std::string& name)
|
||||
: file_writer(name)
|
||||
, listener()
|
||||
{
|
||||
// Write UTF-8 BOM
|
||||
file_writer::log(logs::level::always, "\xEF\xBB\xBF", 3);
|
||||
|
||||
// Write initial message
|
||||
stored_message ver;
|
||||
ver.m.ch = nullptr;
|
||||
ver.m.sev = level::always;
|
||||
ver.stamp = 0;
|
||||
ver.text = fmt::format("RPCS3 v%s | %s\n%s", rpcs3::version.to_string(), rpcs3::get_branch(), utils::get_system_info());
|
||||
|
||||
file_writer::log(logs::level::always, ver.text.data(), ver.text.size());
|
||||
file_writer::log(logs::level::always, "\n", 1);
|
||||
messages.emplace_back(std::move(ver));
|
||||
}
|
||||
|
||||
void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::string& prefix, const std::string& _text)
|
||||
{
|
||||
thread_local std::string text;
|
||||
std::string text; text.reserve(prefix.size() + _text.size() + 200);
|
||||
|
||||
// Used character: U+00B7 (Middle Dot)
|
||||
switch (msg.sev)
|
||||
@@ -419,12 +143,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
case level::trace: text = u8"·T "; break;
|
||||
}
|
||||
|
||||
// Print miscosecond timestamp
|
||||
const u64 hours = stamp / 3600'000'000;
|
||||
const u64 mins = (stamp % 3600'000'000) / 60'000'000;
|
||||
const u64 secs = (stamp % 60'000'000) / 1'000'000;
|
||||
const u64 frac = (stamp % 1'000'000);
|
||||
fmt::append(text, "%u:%02u:%02u.%06u ", hours, mins, secs, frac);
|
||||
// TODO: print time?
|
||||
|
||||
if (prefix.size() > 0)
|
||||
{
|
||||
@@ -432,8 +151,8 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
text += prefix;
|
||||
text += "} ";
|
||||
}
|
||||
|
||||
if (msg.ch && '\0' != *msg.ch->name)
|
||||
|
||||
if (msg.ch->name)
|
||||
{
|
||||
text += msg.ch->name;
|
||||
text += msg.sev == level::todo ? " TODO: " : ": ";
|
||||
@@ -442,9 +161,9 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
{
|
||||
text += "TODO: ";
|
||||
}
|
||||
|
||||
|
||||
text += _text;
|
||||
text += '\n';
|
||||
|
||||
file_writer::log(msg.sev, text.data(), text.size());
|
||||
file_writer::log(text.data(), text.size());
|
||||
}
|
||||
|
||||
+10
-19
@@ -3,22 +3,19 @@
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
#include "StrFmt.h"
|
||||
#include <climits>
|
||||
|
||||
namespace logs
|
||||
{
|
||||
enum class level : uint
|
||||
{
|
||||
always, // Highest log severity (unused, cannot be disabled)
|
||||
always, // highest level (unused, cannot be disabled)
|
||||
fatal,
|
||||
error,
|
||||
todo,
|
||||
success,
|
||||
warning,
|
||||
notice,
|
||||
trace, // Lowest severity (usually disabled)
|
||||
|
||||
_uninit = UINT_MAX, // Special value for delayed initialization
|
||||
trace, // lowest level (usually disabled)
|
||||
};
|
||||
|
||||
struct channel;
|
||||
@@ -26,7 +23,7 @@ namespace logs
|
||||
// Message information (temporary data)
|
||||
struct message
|
||||
{
|
||||
channel* ch;
|
||||
const channel* ch;
|
||||
level sev;
|
||||
|
||||
// Send log message to global logger instance
|
||||
@@ -43,10 +40,10 @@ namespace logs
|
||||
public:
|
||||
constexpr listener() = default;
|
||||
|
||||
virtual ~listener();
|
||||
virtual ~listener() = default;
|
||||
|
||||
// Process log message
|
||||
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) = 0;
|
||||
virtual void log(const message& msg, const std::string& prefix, const std::string& text) = 0;
|
||||
|
||||
// Add new listener
|
||||
static void add(listener*);
|
||||
@@ -60,16 +57,16 @@ namespace logs
|
||||
// The lowest logging level enabled for this channel (used for early filtering)
|
||||
atomic_t<level> enabled;
|
||||
|
||||
// Constant initialization: channel name
|
||||
constexpr channel(const char* name)
|
||||
// Constant initialization: name and initial log level
|
||||
constexpr channel(const char* name, level enabled = level::trace)
|
||||
: name(name)
|
||||
, enabled(level::_uninit)
|
||||
, enabled(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
// Formatting function
|
||||
template<typename... Args>
|
||||
SAFE_BUFFERS FORCE_INLINE void format(level sev, const char* fmt, const Args&... args)
|
||||
SAFE_BUFFERS FORCE_INLINE void format(level sev, const char* fmt, const Args&... args) const
|
||||
{
|
||||
if (UNLIKELY(sev <= enabled))
|
||||
{
|
||||
@@ -79,7 +76,7 @@ namespace logs
|
||||
|
||||
#define GEN_LOG_METHOD(_sev)\
|
||||
template<typename... Args>\
|
||||
SAFE_BUFFERS void _sev(const char* fmt, const Args&... args)\
|
||||
SAFE_BUFFERS void _sev(const char* fmt, const Args&... args) const\
|
||||
{\
|
||||
return format<Args...>(level::_sev, fmt, args...);\
|
||||
}
|
||||
@@ -105,12 +102,6 @@ namespace logs
|
||||
extern channel PPU;
|
||||
extern channel SPU;
|
||||
extern channel ARMv7;
|
||||
|
||||
// Log level control: set all channels to level::notice
|
||||
void reset();
|
||||
|
||||
// Log level control: register channel if necessary, set channel level
|
||||
void set_level(const std::string&, level);
|
||||
}
|
||||
|
||||
// Legacy:
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
class MTProgressDialog : public wxDialog
|
||||
{
|
||||
wxGauge** m_gauge;
|
||||
wxStaticText** m_msg;
|
||||
|
||||
wxArrayLong m_maximum;
|
||||
const u8 m_cores;
|
||||
|
||||
static const uint layout = 16;
|
||||
static const uint maxdial = 65536;
|
||||
wxArrayInt m_lastupdate;
|
||||
|
||||
public:
|
||||
MTProgressDialog(wxWindow* parent, const wxSize& size, const wxString& title,
|
||||
const wxString& msg, const wxArrayLong& maximum, const u8 cores)
|
||||
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition)
|
||||
, m_maximum(maximum)
|
||||
, m_cores(cores)
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_gauge = new wxGauge*[m_cores];
|
||||
m_msg = new wxStaticText*[m_cores];
|
||||
|
||||
m_lastupdate.SetCount(cores);
|
||||
|
||||
for(uint i=0; i<m_cores; ++i)
|
||||
{
|
||||
m_lastupdate[i] = -1;
|
||||
|
||||
m_msg[i] = new wxStaticText(this, wxID_ANY, msg);
|
||||
sizer->Add(m_msg[i], 0, wxLEFT | wxTOP, layout);
|
||||
|
||||
m_gauge[i] = new wxGauge(this, wxID_ANY, maxdial,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxGA_HORIZONTAL );
|
||||
|
||||
sizer->Add(m_gauge[i], 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, layout);
|
||||
m_gauge[i]->SetValue(0);
|
||||
|
||||
sizer->AddSpacer(5);
|
||||
}
|
||||
|
||||
SetSizerAndFit(sizer);
|
||||
if(size != wxDefaultSize)
|
||||
{
|
||||
SetSize(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxSize ws;
|
||||
ws.x = 400;
|
||||
ws.y = GetSize().y + 8;
|
||||
SetSize(ws);
|
||||
}
|
||||
|
||||
m_maximum.SetCount(m_cores);
|
||||
|
||||
Show();
|
||||
}
|
||||
|
||||
void Update(const u8 thread_id, const u64 value, const wxString& msg)
|
||||
{
|
||||
if(thread_id > m_cores) return;
|
||||
|
||||
const int curupdate = (int)(((double)value/(double)m_maximum[thread_id])*1000);
|
||||
if(curupdate == m_lastupdate[thread_id]) return;
|
||||
m_lastupdate[thread_id] = curupdate;
|
||||
|
||||
m_msg[thread_id]->SetLabel(msg);
|
||||
|
||||
if(value >= (u32)m_maximum[thread_id]) return;
|
||||
m_gauge[thread_id]->SetValue(((double)value / (double)m_maximum[thread_id]) * maxdial);
|
||||
}
|
||||
|
||||
const u32 GetMaxValue(const uint thread_id) const
|
||||
{
|
||||
if(thread_id > m_cores) return 0;
|
||||
return m_maximum[thread_id];
|
||||
}
|
||||
|
||||
void SetMaxFor(const uint thread_id, const u64 val)
|
||||
{
|
||||
if(thread_id > m_cores) return;
|
||||
m_maximum[thread_id] = val;
|
||||
m_lastupdate[thread_id] = 0;
|
||||
}
|
||||
|
||||
virtual void Close(bool force = false)
|
||||
{
|
||||
m_lastupdate.Empty();
|
||||
m_maximum.Empty();
|
||||
|
||||
wxDialog::Close(force);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "Utilities/Semaphore.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
struct benaphore::internal
|
||||
{
|
||||
std::mutex mutex;
|
||||
|
||||
std::size_t acq_order{};
|
||||
std::size_t rel_order{};
|
||||
|
||||
std::condition_variable cond;
|
||||
};
|
||||
|
||||
void benaphore::wait_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
// Notify non-zero waiter queue size
|
||||
if (m_value.exchange(-1) == 1)
|
||||
{
|
||||
// Return immediately (acquired)
|
||||
m_value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember the order
|
||||
const std::size_t order = ++m_data->acq_order;
|
||||
|
||||
// Wait for the appropriate rel_order (TODO)
|
||||
while (m_data->rel_order < order)
|
||||
{
|
||||
m_data->cond.wait(lock);
|
||||
}
|
||||
|
||||
if (order == m_data->acq_order && m_data->acq_order == m_data->rel_order)
|
||||
{
|
||||
// Cleaup
|
||||
m_data->acq_order = 0;
|
||||
m_data->rel_order = 0;
|
||||
m_value.compare_and_swap(-1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void benaphore::post_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
if (m_value.compare_and_swap(0, 1) != -1)
|
||||
{
|
||||
// Do nothing (released)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_data->acq_order == m_data->rel_order)
|
||||
{
|
||||
m_value = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Awake one thread
|
||||
m_data->rel_order += 1;
|
||||
|
||||
// Unlock and notify
|
||||
lock.unlock();
|
||||
m_data->cond.notify_one();
|
||||
}
|
||||
|
||||
void benaphore::initialize_once()
|
||||
{
|
||||
if (UNLIKELY(!m_data))
|
||||
{
|
||||
auto ptr = new benaphore::internal;
|
||||
|
||||
if (!m_data.compare_and_swap_test(nullptr, ptr))
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
benaphore::~benaphore()
|
||||
{
|
||||
delete m_data;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
// Binary semaphore
|
||||
class benaphore
|
||||
{
|
||||
struct internal;
|
||||
|
||||
// Reserved value (-1) enforces *_hard() calls
|
||||
atomic_t<u32> m_value{};
|
||||
|
||||
atomic_t<internal*> m_data{};
|
||||
|
||||
void wait_hard();
|
||||
void post_hard();
|
||||
|
||||
public:
|
||||
constexpr benaphore() = default;
|
||||
|
||||
~benaphore();
|
||||
|
||||
// Initialize internal data
|
||||
void initialize_once();
|
||||
|
||||
void wait()
|
||||
{
|
||||
if (UNLIKELY(!m_value.compare_and_swap_test(1, 0)))
|
||||
{
|
||||
wait_hard();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_wait()
|
||||
{
|
||||
return m_value.compare_and_swap_test(1, 0);
|
||||
}
|
||||
|
||||
void post()
|
||||
{
|
||||
if (UNLIKELY(!m_value.compare_and_swap_test(0, 1)))
|
||||
{
|
||||
post_hard();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "SharedMutex.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
struct shared_mutex::internal
|
||||
{
|
||||
std::mutex mutex;
|
||||
|
||||
std::size_t rq_size{}; // Reader queue size (threads waiting on m_rcv)
|
||||
std::size_t wq_size{}; // Writer queue size (threads waiting on m_wcv and m_ocv)
|
||||
|
||||
std::condition_variable rcv; // Reader queue
|
||||
std::condition_variable wcv; // Writer queue
|
||||
std::condition_variable ocv; // For current exclusive owner
|
||||
};
|
||||
|
||||
void shared_mutex::lock_shared_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
// Validate
|
||||
if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock_shared(): Invalid bit");
|
||||
if ((m_ctrl & SM_READER_MASK) == 0) throw std::runtime_error("shared_mutex::lock_shared(): No readers");
|
||||
|
||||
// Notify non-zero reader queue size
|
||||
m_ctrl |= SM_WAITERS_BIT, m_data->rq_size++;
|
||||
|
||||
// Fix excess reader count
|
||||
if ((--m_ctrl & SM_READER_MASK) == 0 && m_data->wq_size)
|
||||
{
|
||||
// Notify exclusive owner
|
||||
m_data->ocv.notify_one();
|
||||
}
|
||||
|
||||
// Obtain the reader lock
|
||||
while (true)
|
||||
{
|
||||
const auto ctrl = m_ctrl.load();
|
||||
|
||||
// Check writers and reader limit
|
||||
if (m_data->wq_size || (ctrl & ~SM_WAITERS_BIT) >= SM_READER_MAX)
|
||||
{
|
||||
m_data->rcv.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_ctrl.compare_and_swap_test(ctrl, ctrl + 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!--m_data->rq_size && !m_data->wq_size)
|
||||
{
|
||||
m_ctrl &= ~SM_WAITERS_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::unlock_shared_notify()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
if ((m_ctrl & SM_READER_MASK) == 0 && m_data->wq_size)
|
||||
{
|
||||
// Notify exclusive owner
|
||||
lock.unlock();
|
||||
m_data->ocv.notify_one();
|
||||
}
|
||||
else if (m_data->rq_size)
|
||||
{
|
||||
// Notify other readers
|
||||
lock.unlock();
|
||||
m_data->rcv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::lock_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
// Validate
|
||||
if ((m_ctrl & SM_INVALID_BIT) != 0) throw std::runtime_error("shared_mutex::lock(): Invalid bit");
|
||||
|
||||
// Notify non-zero writer queue size
|
||||
m_ctrl |= SM_WAITERS_BIT, m_data->wq_size++;
|
||||
|
||||
// Obtain the writer lock
|
||||
while (true)
|
||||
{
|
||||
const auto ctrl = m_ctrl.load();
|
||||
|
||||
if (ctrl & SM_WRITER_LOCK)
|
||||
{
|
||||
m_data->wcv.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_ctrl.compare_and_swap_test(ctrl, ctrl | SM_WRITER_LOCK))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for remaining readers
|
||||
while ((m_ctrl & SM_READER_MASK) != 0)
|
||||
{
|
||||
m_data->ocv.wait(lock);
|
||||
}
|
||||
|
||||
if (!--m_data->wq_size && !m_data->rq_size)
|
||||
{
|
||||
m_ctrl &= ~SM_WAITERS_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::unlock_notify()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
if (m_data->wq_size)
|
||||
{
|
||||
// Notify next exclusive owner
|
||||
lock.unlock();
|
||||
m_data->wcv.notify_one();
|
||||
}
|
||||
else if (m_data->rq_size)
|
||||
{
|
||||
// Notify all readers
|
||||
lock.unlock();
|
||||
m_data->rcv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::lock_upgrade_hard()
|
||||
{
|
||||
unlock_shared();
|
||||
lock();
|
||||
}
|
||||
|
||||
void shared_mutex::lock_degrade_hard()
|
||||
{
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
|
||||
m_ctrl -= SM_WRITER_LOCK - 1;
|
||||
|
||||
if (m_data->rq_size)
|
||||
{
|
||||
// Notify all readers
|
||||
lock.unlock();
|
||||
m_data->rcv.notify_all();
|
||||
}
|
||||
else if (m_data->wq_size)
|
||||
{
|
||||
// Notify next exclusive owner
|
||||
lock.unlock();
|
||||
m_data->wcv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::initialize_once()
|
||||
{
|
||||
if (UNLIKELY(!m_data))
|
||||
{
|
||||
auto ptr = new shared_mutex::internal;
|
||||
|
||||
if (!m_data.compare_and_swap_test(nullptr, ptr))
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shared_mutex::~shared_mutex()
|
||||
{
|
||||
delete m_data;
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
//! An attempt to create effective implementation of "shared mutex", lock-free in optimistic case.
|
||||
//! All locking and unlocking may be done by a single LOCK XADD or LOCK CMPXCHG instruction.
|
||||
//! MSVC implementation of std::shared_timed_mutex seems suboptimal.
|
||||
//! std::shared_mutex is not available until C++17.
|
||||
class shared_mutex final
|
||||
{
|
||||
enum : u32
|
||||
{
|
||||
SM_WRITER_LOCK = 1u << 31, // Exclusive lock flag, must be MSB
|
||||
SM_WAITERS_BIT = 1u << 30, // Flag set if m_wq_size or m_rq_size is non-zero
|
||||
SM_INVALID_BIT = 1u << 29, // Unreachable reader count bit (may be set by incorrect unlock_shared() call)
|
||||
|
||||
SM_READER_MASK = SM_WAITERS_BIT - 1, // Valid reader count bit mask
|
||||
SM_READER_MAX = 1u << 24, // Max reader count
|
||||
};
|
||||
|
||||
atomic_t<u32> m_ctrl{}; // Control variable: reader count | SM_* flags
|
||||
|
||||
struct internal;
|
||||
|
||||
atomic_t<internal*> m_data{}; // Internal data
|
||||
|
||||
void lock_shared_hard();
|
||||
void unlock_shared_notify();
|
||||
|
||||
void lock_hard();
|
||||
void unlock_notify();
|
||||
|
||||
void lock_upgrade_hard();
|
||||
void lock_degrade_hard();
|
||||
|
||||
public:
|
||||
constexpr shared_mutex() = default;
|
||||
|
||||
// Initialize internal data
|
||||
void initialize_once();
|
||||
|
||||
~shared_mutex();
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
const u32 ctrl = m_ctrl.load();
|
||||
|
||||
return ctrl < SM_READER_MAX && m_ctrl.compare_and_swap_test(ctrl, ctrl + 1);
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
// Optimization: unconditional increment, compensated later
|
||||
if (UNLIKELY(m_ctrl++ >= SM_READER_MAX))
|
||||
{
|
||||
lock_shared_hard();
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_shared()
|
||||
{
|
||||
if (UNLIKELY(m_ctrl-- >= SM_READER_MAX))
|
||||
{
|
||||
unlock_shared_notify();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
return !m_ctrl && m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK)))
|
||||
{
|
||||
lock_hard();
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_ctrl &= ~SM_WRITER_LOCK;
|
||||
|
||||
if (UNLIKELY(m_ctrl))
|
||||
{
|
||||
unlock_notify();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
return m_ctrl == 1 && m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK);
|
||||
}
|
||||
|
||||
bool try_lock_degrade()
|
||||
{
|
||||
return m_ctrl == SM_WRITER_LOCK && m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1);
|
||||
}
|
||||
|
||||
void lock_upgrade()
|
||||
{
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK)))
|
||||
{
|
||||
lock_upgrade_hard();
|
||||
}
|
||||
}
|
||||
|
||||
void lock_degrade()
|
||||
{
|
||||
if (UNLIKELY(!m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1)))
|
||||
{
|
||||
lock_degrade_hard();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! Simplified shared (reader) lock implementation.
|
||||
//! std::shared_lock may be used instead if necessary.
|
||||
class reader_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
|
||||
public:
|
||||
reader_lock(const reader_lock&) = delete;
|
||||
|
||||
reader_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock_shared();
|
||||
}
|
||||
|
||||
~reader_lock()
|
||||
{
|
||||
m_mutex.unlock_shared();
|
||||
}
|
||||
};
|
||||
|
||||
//! Simplified exclusive (writer) lock implementation.
|
||||
//! std::lock_guard may or std::unique_lock be used instead if necessary.
|
||||
class writer_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
|
||||
public:
|
||||
writer_lock(const writer_lock&) = delete;
|
||||
|
||||
writer_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
~writer_lock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Exclusive (writer) lock in the scope of shared (reader) lock.
|
||||
class upgraded_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
|
||||
public:
|
||||
upgraded_lock(const writer_lock&) = delete;
|
||||
|
||||
upgraded_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock_upgrade();
|
||||
}
|
||||
|
||||
~upgraded_lock()
|
||||
{
|
||||
m_mutex.lock_degrade();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
|
||||
// Tag used in sleep_entry<> constructor
|
||||
static struct defer_sleep_tag {} constexpr defer_sleep{};
|
||||
|
||||
// Define sleep queue as std::deque with T* pointers, T - thread type
|
||||
template<typename T> using sleep_queue = std::deque<T*>;
|
||||
|
||||
// Automatic object handling a thread pointer (T*) in the sleep queue
|
||||
// Sleep queue is actually std::deque with pointers, be careful about the lifetime
|
||||
template<typename T>
|
||||
class sleep_entry final
|
||||
{
|
||||
sleep_queue<T>& m_queue;
|
||||
T& m_thread;
|
||||
|
||||
public:
|
||||
// Constructor; enter() not called
|
||||
sleep_entry(sleep_queue<T>& queue, T& entry, const defer_sleep_tag&)
|
||||
: m_queue(queue)
|
||||
, m_thread(entry)
|
||||
{
|
||||
}
|
||||
|
||||
// Constructor; calls enter()
|
||||
sleep_entry(sleep_queue<T>& queue, T& entry)
|
||||
: sleep_entry(queue, entry, defer_sleep)
|
||||
{
|
||||
enter();
|
||||
}
|
||||
|
||||
// Destructor; calls leave()
|
||||
~sleep_entry()
|
||||
{
|
||||
leave();
|
||||
}
|
||||
|
||||
// Add thread to the sleep queue
|
||||
void enter()
|
||||
{
|
||||
for (auto t : m_queue)
|
||||
{
|
||||
if (t == &m_thread)
|
||||
{
|
||||
// Already exists, is it an error?
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.emplace_back(&m_thread);
|
||||
}
|
||||
|
||||
// Remove thread from the sleep queue
|
||||
void leave()
|
||||
{
|
||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
|
||||
{
|
||||
if (*it == &m_thread)
|
||||
{
|
||||
m_queue.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the thread exists in the sleep queue
|
||||
explicit operator bool() const
|
||||
{
|
||||
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
|
||||
{
|
||||
if (*it == &m_thread)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
+5
-26
@@ -11,18 +11,6 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
template <>
|
||||
void fmt_class_string<std::pair<const fmt_type_info*, u64>>::format(std::string& out, u64 arg)
|
||||
{
|
||||
// Dynamic format arg
|
||||
const auto& pair = get_object(arg);
|
||||
|
||||
if (pair.first)
|
||||
{
|
||||
pair.first->fmt_string(out, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
void fmt_class_string<const void*>::format(std::string& out, u64 arg)
|
||||
{
|
||||
if (arg)
|
||||
@@ -166,12 +154,12 @@ namespace fmt
|
||||
#ifdef _WIN32
|
||||
if (DWORD error = GetLastError())
|
||||
{
|
||||
fmt::append(out, " (e=%#x)", error);
|
||||
fmt::append(out, " (e%#x)", error);
|
||||
}
|
||||
#else
|
||||
if (int error = errno)
|
||||
{
|
||||
fmt::append(out, " (e=%d)", error);
|
||||
fmt::append(out, " (e%d)", error);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -252,13 +240,13 @@ struct fmt::cfmt_src
|
||||
template <typename T>
|
||||
T get(std::size_t index) const
|
||||
{
|
||||
return *reinterpret_cast<const T*>(reinterpret_cast<const u8*>(args + index));
|
||||
return reinterpret_cast<const T&>(args[index]);
|
||||
}
|
||||
|
||||
void skip(std::size_t extra)
|
||||
{
|
||||
sup += extra + 1;
|
||||
args += extra + 1;
|
||||
++sup += extra;
|
||||
++args += extra;
|
||||
}
|
||||
|
||||
std::size_t fmt_string(std::string& out, std::size_t extra) const
|
||||
@@ -286,15 +274,6 @@ struct fmt::cfmt_src
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr std::size_t size_char = 1;
|
||||
static constexpr std::size_t size_short = 2;
|
||||
static constexpr std::size_t size_int = 0;
|
||||
static constexpr std::size_t size_long = sizeof(ulong);
|
||||
static constexpr std::size_t size_llong = sizeof(ullong);
|
||||
static constexpr std::size_t size_size = sizeof(std::size_t);
|
||||
static constexpr std::size_t size_max = sizeof(std::uintmax_t);
|
||||
static constexpr std::size_t size_diff = sizeof(std::ptrdiff_t);
|
||||
};
|
||||
|
||||
void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept
|
||||
|
||||
+8
-39
@@ -15,7 +15,7 @@ namespace fmt
|
||||
template <typename T, typename>
|
||||
struct fmt_unveil
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "fmt_unveil<> error: incomplete type");
|
||||
static_assert(sizeof(T) > 0, "fmt_unveil<>: cannot pass forward-declared object");
|
||||
|
||||
using type = T;
|
||||
|
||||
@@ -59,21 +59,10 @@ struct fmt_unveil<T, std::enable_if_t<std::is_floating_point<T>::value && sizeof
|
||||
{
|
||||
using type = T;
|
||||
|
||||
// Convert FP to f64 and reinterpret as u64
|
||||
static inline u64 get(const f64& arg)
|
||||
// Convert FP to f64 and reinterpret (TODO?)
|
||||
static inline u64 get(f64 arg)
|
||||
{
|
||||
return *reinterpret_cast<const u64*>(reinterpret_cast<const u8*>(&arg));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt_unveil<f16, void>
|
||||
{
|
||||
using type = f16;
|
||||
|
||||
static inline u64 get(const f16& arg)
|
||||
{
|
||||
return fmt_unveil<f64>::get(arg.operator float());
|
||||
return reinterpret_cast<u64&>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -137,27 +126,15 @@ struct fmt_class_string
|
||||
return *reinterpret_cast<const T*>(static_cast<std::uintptr_t>(arg));
|
||||
}
|
||||
|
||||
// Enum -> string function type
|
||||
using convert_t = const char*(*)(T value);
|
||||
|
||||
// Enum -> string function registered
|
||||
static convert_t convert_enum;
|
||||
|
||||
// Helper function (safely converts arg to enum value)
|
||||
static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, convert_t convert)
|
||||
static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, const char* (*get)(T value))
|
||||
{
|
||||
// Save convert function
|
||||
if (convert_enum == nullptr)
|
||||
{
|
||||
convert_enum = convert;
|
||||
}
|
||||
|
||||
const auto value = static_cast<std::underlying_type_t<T>>(arg);
|
||||
|
||||
// Check narrowing
|
||||
if (static_cast<u64>(value) == arg)
|
||||
{
|
||||
if (const char* str = convert(static_cast<T>(value)))
|
||||
if (const char* str = get(static_cast<T>(value)))
|
||||
{
|
||||
out += str;
|
||||
return;
|
||||
@@ -176,7 +153,7 @@ struct fmt_class_string
|
||||
|
||||
out += prefix;
|
||||
|
||||
for (u64 i = 0; i < 63; i++)
|
||||
for (u64 i = 0; i < 64; i++)
|
||||
{
|
||||
const u64 mask = 1ull << i;
|
||||
|
||||
@@ -184,18 +161,13 @@ struct fmt_class_string
|
||||
{
|
||||
fmt(out, i);
|
||||
|
||||
if (arg >> (i + 1))
|
||||
if (arg > mask)
|
||||
{
|
||||
out += delim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arg & (1ull << 63))
|
||||
{
|
||||
fmt(out, 63);
|
||||
}
|
||||
|
||||
out += suffix;
|
||||
}
|
||||
|
||||
@@ -203,9 +175,6 @@ struct fmt_class_string
|
||||
static constexpr const char* unknown = nullptr;
|
||||
};
|
||||
|
||||
template <typename T, typename V>
|
||||
const char*(*fmt_class_string<T, V>::convert_enum)(T) = nullptr;
|
||||
|
||||
template <>
|
||||
struct fmt_class_string<const void*, void>
|
||||
{
|
||||
|
||||
+834
-444
File diff suppressed because it is too large
Load Diff
+258
-76
@@ -7,9 +7,6 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "sema.h"
|
||||
#include "cond.h"
|
||||
|
||||
// Will report exception and call std::abort() if put in catch(...)
|
||||
[[noreturn]] void catch_all_exceptions();
|
||||
|
||||
@@ -20,19 +17,19 @@ class task_stack
|
||||
{
|
||||
std::unique_ptr<task_base> next;
|
||||
|
||||
virtual ~task_base();
|
||||
virtual ~task_base() = default;
|
||||
|
||||
virtual void invoke()
|
||||
virtual void exec()
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
next->invoke();
|
||||
next->exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct task_type final : task_base
|
||||
template<typename F>
|
||||
struct task_type : task_base
|
||||
{
|
||||
std::remove_reference_t<F> func;
|
||||
|
||||
@@ -41,10 +38,10 @@ class task_stack
|
||||
{
|
||||
}
|
||||
|
||||
void invoke() final override
|
||||
void exec() override
|
||||
{
|
||||
func();
|
||||
task_base::invoke();
|
||||
task_base::exec();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,7 +50,7 @@ class task_stack
|
||||
public:
|
||||
task_stack() = default;
|
||||
|
||||
template <typename F>
|
||||
template<typename F>
|
||||
task_stack(F&& func)
|
||||
: m_stack(new task_type<F>(std::forward<F>(func)))
|
||||
{
|
||||
@@ -73,11 +70,11 @@ public:
|
||||
m_stack.reset();
|
||||
}
|
||||
|
||||
void invoke() const
|
||||
void exec() const
|
||||
{
|
||||
if (m_stack)
|
||||
{
|
||||
m_stack->invoke();
|
||||
m_stack->exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -85,32 +82,23 @@ public:
|
||||
// Thread control class
|
||||
class thread_ctrl final
|
||||
{
|
||||
// Current thread
|
||||
public: // TODO
|
||||
struct internal;
|
||||
|
||||
private:
|
||||
static thread_local thread_ctrl* g_tls_this_thread;
|
||||
|
||||
// Self pointer
|
||||
std::shared_ptr<thread_ctrl> m_self;
|
||||
// Thread handle storage
|
||||
std::aligned_storage_t<16> m_thread;
|
||||
|
||||
// Thread handle (platform-specific)
|
||||
atomic_t<std::uintptr_t> m_thread{0};
|
||||
// Thread join contention counter
|
||||
atomic_t<u32> m_joining{};
|
||||
|
||||
// Thread mutex
|
||||
mutable semaphore<> m_mutex;
|
||||
// Thread interrupt guard counter
|
||||
volatile u32 m_guard = 0x80000000;
|
||||
|
||||
// Thread condition variable
|
||||
cond_variable m_cond;
|
||||
|
||||
// Thread flags
|
||||
atomic_t<u32> m_signal{0};
|
||||
|
||||
// Thread joining condition variable
|
||||
cond_variable m_jcv;
|
||||
|
||||
// Remotely set or caught exception
|
||||
std::exception_ptr m_exception;
|
||||
|
||||
// Thread initial task or atexit task
|
||||
task_stack m_task;
|
||||
// Thread internals
|
||||
atomic_t<internal*> m_data{};
|
||||
|
||||
// Fixed name
|
||||
std::string m_name;
|
||||
@@ -122,19 +110,19 @@ class thread_ctrl final
|
||||
void initialize();
|
||||
|
||||
// Called at the thread end
|
||||
void finalize(std::exception_ptr) noexcept;
|
||||
void finalize() noexcept;
|
||||
|
||||
// Add task (atexit)
|
||||
static void _push(task_stack);
|
||||
// Get atexit function
|
||||
void push_atexit(task_stack);
|
||||
|
||||
// Internal waiting function, may throw. Infinite value is -1.
|
||||
static bool _wait_for(u64 usec);
|
||||
// Start waiting
|
||||
void wait_start(u64 timeout);
|
||||
|
||||
// Internal throwing function. Mutex must be locked and will be unlocked.
|
||||
[[noreturn]] void _throw();
|
||||
// Proceed waiting
|
||||
bool wait_wait(u64 timeout);
|
||||
|
||||
// Internal notification function
|
||||
void _notify(cond_variable thread_ctrl::*);
|
||||
// Check exception
|
||||
void test();
|
||||
|
||||
public:
|
||||
thread_ctrl(std::string&& name);
|
||||
@@ -149,57 +137,179 @@ public:
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// Get exception
|
||||
std::exception_ptr get_exception() const;
|
||||
|
||||
// Set exception
|
||||
void set_exception(std::exception_ptr ptr);
|
||||
// Initialize internal data
|
||||
void initialize_once();
|
||||
|
||||
// Get thread result (may throw, simultaneous joining allowed)
|
||||
void join();
|
||||
|
||||
// Notify the thread
|
||||
// Lock thread mutex
|
||||
void lock();
|
||||
|
||||
// Lock conditionally (double-checked)
|
||||
template<typename F>
|
||||
bool lock_if(F&& pred)
|
||||
{
|
||||
if (pred())
|
||||
{
|
||||
lock();
|
||||
|
||||
try
|
||||
{
|
||||
if (LIKELY(pred()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock thread mutex (internal data must be initialized)
|
||||
void unlock();
|
||||
|
||||
// Lock, unlock, notify the thread (required if the condition changed locklessly)
|
||||
void lock_notify();
|
||||
|
||||
// Notify the thread (internal data must be initialized)
|
||||
void notify();
|
||||
|
||||
// Wait once with timeout. Abortable, may throw. May spuriously return false.
|
||||
static inline bool wait_for(u64 usec)
|
||||
// Set exception (internal data must be initialized, thread mutex must be locked)
|
||||
void set_exception(std::exception_ptr);
|
||||
|
||||
// Internal
|
||||
static void handle_interrupt();
|
||||
|
||||
// Interrupt thread with specified handler call (thread mutex must be locked)
|
||||
void interrupt(void(*handler)());
|
||||
|
||||
// Interrupt guard recursive enter
|
||||
void guard_enter()
|
||||
{
|
||||
return _wait_for(usec);
|
||||
m_guard++;
|
||||
}
|
||||
|
||||
// Wait. Abortable, may throw.
|
||||
static inline void wait()
|
||||
// Interrupt guard recursive leave
|
||||
void guard_leave()
|
||||
{
|
||||
_wait_for(-1);
|
||||
if (UNLIKELY(--m_guard & 0x40000000))
|
||||
{
|
||||
test_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until pred(). Abortable, may throw.
|
||||
template<typename F, typename RT = std::result_of_t<F()>>
|
||||
static inline RT wait(F&& pred)
|
||||
// Allow interrupts
|
||||
void interrupt_enable()
|
||||
{
|
||||
m_guard &= ~0x80000000;
|
||||
}
|
||||
|
||||
// Disable and discard any interrupt
|
||||
void interrupt_disable()
|
||||
{
|
||||
m_guard |= 0x80000000;
|
||||
}
|
||||
|
||||
// Check interrupt if delayed by guard scope
|
||||
void test_interrupt();
|
||||
|
||||
// Current thread sleeps for specified amount of microseconds.
|
||||
// Wrapper for std::this_thread::sleep, doesn't require valid thread_ctrl.
|
||||
[[deprecated]] static void sleep(u64 useconds);
|
||||
|
||||
// Wait until pred(). Abortable, may throw. Thread must be locked.
|
||||
// Timeout in microseconds (zero means infinite).
|
||||
template<typename F>
|
||||
static inline auto wait_for(u64 useconds, F&& pred)
|
||||
{
|
||||
if (useconds)
|
||||
{
|
||||
g_tls_this_thread->wait_start(useconds);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
|
||||
if (auto&& result = pred())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if (!g_tls_this_thread->wait_wait(useconds) && useconds)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait once. Abortable, may throw. Thread must be locked.
|
||||
// Timeout in microseconds (zero means infinite).
|
||||
static inline bool wait_for(u64 useconds = 0)
|
||||
{
|
||||
if (useconds)
|
||||
{
|
||||
g_tls_this_thread->wait_start(useconds);
|
||||
}
|
||||
|
||||
g_tls_this_thread->test();
|
||||
|
||||
if (!g_tls_this_thread->wait_wait(useconds) && useconds)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
g_tls_this_thread->test();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wait until pred(). Abortable, may throw. Thread must be locked.
|
||||
template<typename F>
|
||||
static inline auto wait(F&& pred)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (RT result = pred())
|
||||
g_tls_this_thread->test();
|
||||
|
||||
if (auto&& result = pred())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
_wait_for(-1);
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait eternally until aborted.
|
||||
// Wait once. Abortable, may throw. Thread must be locked.
|
||||
static inline void wait()
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
g_tls_this_thread->test();
|
||||
}
|
||||
|
||||
// Wait eternally. Abortable, may throw. Thread must be locked.
|
||||
[[noreturn]] static inline void eternalize()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_wait_for(-1);
|
||||
g_tls_this_thread->test();
|
||||
g_tls_this_thread->wait_wait(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Test exception (may throw).
|
||||
static void test();
|
||||
|
||||
// Get current thread (may be nullptr)
|
||||
static thread_ctrl* get_current()
|
||||
{
|
||||
@@ -210,14 +320,14 @@ public:
|
||||
template<typename F>
|
||||
static inline void atexit(F&& func)
|
||||
{
|
||||
_push(std::forward<F>(func));
|
||||
return g_tls_this_thread->push_atexit(std::forward<F>(func));
|
||||
}
|
||||
|
||||
// Create detached named thread
|
||||
// Named thread factory
|
||||
template<typename N, typename F>
|
||||
static inline void spawn(N&& name, F&& func)
|
||||
{
|
||||
auto out = std::make_shared<thread_ctrl>(std::forward<N>(name));
|
||||
auto&& out = std::make_shared<thread_ctrl>(std::forward<N>(name));
|
||||
|
||||
thread_ctrl::start(out, std::forward<F>(func));
|
||||
}
|
||||
@@ -230,9 +340,6 @@ public:
|
||||
|
||||
thread_ctrl::start(out, std::forward<F>(func));
|
||||
}
|
||||
|
||||
static void set_native_priority(int priority);
|
||||
static void set_ideal_processor_core(int core);
|
||||
};
|
||||
|
||||
class named_thread
|
||||
@@ -261,9 +368,6 @@ protected:
|
||||
// Thread finalization (called after on_task)
|
||||
virtual void on_exit() {}
|
||||
|
||||
// Called once upon thread spawn within the thread's own context
|
||||
virtual void on_spawn() {}
|
||||
|
||||
public:
|
||||
// ID initialization
|
||||
virtual void on_init(const std::shared_ptr<void>& _this)
|
||||
@@ -278,7 +382,7 @@ public:
|
||||
}
|
||||
|
||||
// Access thread_ctrl
|
||||
thread_ctrl* get() const
|
||||
thread_ctrl* operator->() const
|
||||
{
|
||||
return m_thread.get();
|
||||
}
|
||||
@@ -288,12 +392,90 @@ public:
|
||||
return m_thread->join();
|
||||
}
|
||||
|
||||
void lock() const
|
||||
{
|
||||
return m_thread->lock();
|
||||
}
|
||||
|
||||
void unlock() const
|
||||
{
|
||||
return m_thread->unlock();
|
||||
}
|
||||
|
||||
void lock_notify() const
|
||||
{
|
||||
return m_thread->lock_notify();
|
||||
}
|
||||
|
||||
void notify() const
|
||||
{
|
||||
return m_thread->notify();
|
||||
}
|
||||
};
|
||||
|
||||
// Simple thread mutex locker
|
||||
class thread_lock final
|
||||
{
|
||||
thread_ctrl* m_thread;
|
||||
|
||||
public:
|
||||
thread_lock(const thread_lock&) = delete;
|
||||
|
||||
// Lock specified thread
|
||||
thread_lock(thread_ctrl* thread)
|
||||
: m_thread(thread)
|
||||
{
|
||||
m_thread->lock();
|
||||
}
|
||||
|
||||
// Lock specified named_thread
|
||||
thread_lock(named_thread& thread)
|
||||
: thread_lock(thread.operator->())
|
||||
{
|
||||
}
|
||||
|
||||
// Lock current thread
|
||||
thread_lock()
|
||||
: thread_lock(thread_ctrl::get_current())
|
||||
{
|
||||
}
|
||||
|
||||
~thread_lock()
|
||||
{
|
||||
m_thread->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Interrupt guard scope
|
||||
class thread_guard final
|
||||
{
|
||||
thread_ctrl* m_thread;
|
||||
|
||||
public:
|
||||
thread_guard(const thread_guard&) = delete;
|
||||
|
||||
thread_guard(thread_ctrl* thread)
|
||||
: m_thread(thread)
|
||||
{
|
||||
m_thread->guard_enter();
|
||||
}
|
||||
|
||||
thread_guard(named_thread& thread)
|
||||
: thread_guard(thread.operator->())
|
||||
{
|
||||
}
|
||||
|
||||
thread_guard()
|
||||
: thread_guard(thread_ctrl::get_current())
|
||||
{
|
||||
}
|
||||
|
||||
~thread_guard() noexcept(false)
|
||||
{
|
||||
m_thread->guard_leave();
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for named thread, joins automatically in the destructor, can only be used in function scope
|
||||
class scope_thread final
|
||||
{
|
||||
@@ -316,7 +498,7 @@ public:
|
||||
}
|
||||
|
||||
// Access thread_ctrl
|
||||
thread_ctrl* get() const
|
||||
thread_ctrl* operator->() const
|
||||
{
|
||||
return m_thread.get();
|
||||
}
|
||||
|
||||
+6
-6
@@ -6,8 +6,8 @@ class Timer
|
||||
{
|
||||
private:
|
||||
bool m_stopped;
|
||||
std::chrono::steady_clock::time_point m_start;
|
||||
std::chrono::steady_clock::time_point m_end;
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
std::chrono::high_resolution_clock::time_point m_end;
|
||||
|
||||
public:
|
||||
Timer() : m_stopped(false)
|
||||
@@ -17,13 +17,13 @@ public:
|
||||
void Start()
|
||||
{
|
||||
m_stopped = false;
|
||||
m_start = std::chrono::steady_clock::now();
|
||||
m_start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
m_stopped = true;
|
||||
m_end = std::chrono::steady_clock::now();
|
||||
m_end = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
double GetElapsedTimeInSec() const
|
||||
@@ -38,14 +38,14 @@ public:
|
||||
|
||||
u64 GetElapsedTimeInMicroSec() const
|
||||
{
|
||||
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
|
||||
std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(now - m_start).count();
|
||||
}
|
||||
|
||||
u64 GetElapsedTimeInNanoSec() const
|
||||
{
|
||||
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
|
||||
std::chrono::high_resolution_clock::time_point now = m_stopped ? m_end : std::chrono::high_resolution_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(now - m_start).count();
|
||||
}
|
||||
|
||||
+10
-56
@@ -11,78 +11,32 @@
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace utils
|
||||
namespace memory_helper
|
||||
{
|
||||
// Convert memory protection (internal)
|
||||
static auto operator +(protection prot)
|
||||
void* reserve_memory(size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD _prot = PAGE_NOACCESS;
|
||||
switch (prot)
|
||||
{
|
||||
case protection::rw: _prot = PAGE_READWRITE; break;
|
||||
case protection::ro: _prot = PAGE_READONLY; break;
|
||||
case protection::no: break;
|
||||
case protection::wx: _prot = PAGE_EXECUTE_READWRITE; break;
|
||||
case protection::rx: _prot = PAGE_EXECUTE_READ; break;
|
||||
}
|
||||
return verify("reserve_memory" HERE, VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS));
|
||||
#else
|
||||
int _prot = PROT_NONE;
|
||||
switch (prot)
|
||||
{
|
||||
case protection::rw: _prot = PROT_READ | PROT_WRITE; break;
|
||||
case protection::ro: _prot = PROT_READ; break;
|
||||
case protection::no: break;
|
||||
case protection::wx: _prot = PROT_READ | PROT_WRITE | PROT_EXEC; break;
|
||||
case protection::rx: _prot = PROT_READ | PROT_EXEC; break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return _prot;
|
||||
}
|
||||
|
||||
void* memory_reserve(std::size_t size, void* use_addr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::VirtualAlloc(use_addr, size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
auto ptr = ::mmap(use_addr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (use_addr && ptr != use_addr)
|
||||
{
|
||||
::munmap(ptr, size);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return verify("reserve_memory" HERE, ::mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_commit(void* pointer, std::size_t size, protection prot)
|
||||
void commit_page_memory(void* pointer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), ::VirtualAlloc(pointer, size, MEM_COMMIT, +prot);
|
||||
verify(HERE), VirtualAlloc(pointer, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
#else
|
||||
verify(HERE), ::mprotect((void*)((u64)pointer & -4096), ::align(size, 4096), +prot) != -1;
|
||||
verify(HERE), ::mprotect((void*)((u64)pointer & -4096), size, PROT_READ | PROT_WRITE) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_decommit(void* pointer, std::size_t size)
|
||||
void free_reserved_memory(void* pointer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), ::VirtualFree(pointer, size, MEM_DECOMMIT);
|
||||
verify(HERE), VirtualFree(pointer, 0, MEM_DECOMMIT);
|
||||
#else
|
||||
verify(HERE), ::mmap(pointer, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_protect(void* pointer, std::size_t size, protection prot)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD old;
|
||||
verify(HERE), ::VirtualProtect(pointer, size, +prot, &old);
|
||||
#else
|
||||
verify(HERE), ::mprotect((void*)((u64)pointer & -4096), ::align(size, 4096), +prot) != -1;
|
||||
verify(HERE), ::mprotect(pointer, size, PROT_NONE) != -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
namespace utils
|
||||
namespace memory_helper
|
||||
{
|
||||
// Memory protection type
|
||||
enum class protection
|
||||
{
|
||||
rw, // Read + write (default)
|
||||
ro, // Read only
|
||||
no, // No access
|
||||
wx, // Read + write + execute
|
||||
rx, // Read + execute
|
||||
};
|
||||
|
||||
/**
|
||||
* Reserve `size` bytes of virtual memory and returns it.
|
||||
* The memory should be commited before usage.
|
||||
*/
|
||||
void* memory_reserve(std::size_t size, void* use_addr = nullptr);
|
||||
void* reserve_memory(std::size_t size);
|
||||
|
||||
/**
|
||||
* Commit `size` bytes of virtual memory starting at pointer.
|
||||
* That is, bake reserved memory with physical memory.
|
||||
* pointer should belong to a range of reserved memory.
|
||||
*/
|
||||
void memory_commit(void* pointer, std::size_t size, protection prot = protection::rw);
|
||||
void commit_page_memory(void* pointer, std::size_t size);
|
||||
|
||||
/**
|
||||
* Decommit all memory committed via commit_page_memory.
|
||||
*/
|
||||
void memory_decommit(void* pointer, std::size_t size);
|
||||
|
||||
// Set memory protection
|
||||
void memory_protect(void* pointer, std::size_t size, protection prot);
|
||||
void free_reserved_memory(void* pointer, std::size_t size);
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
#include "bin_patch.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include "File.h"
|
||||
#include "Config.h"
|
||||
|
||||
template <>
|
||||
void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](patch_type value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case patch_type::load: return "load";
|
||||
case patch_type::byte: return "byte";
|
||||
case patch_type::le16: return "le16";
|
||||
case patch_type::le32: return "le32";
|
||||
case patch_type::le64: return "le64";
|
||||
case patch_type::bef32: return "bef32";
|
||||
case patch_type::bef64: return "bef64";
|
||||
case patch_type::be16: return "be16";
|
||||
case patch_type::be32: return "be32";
|
||||
case patch_type::be64: return "be64";
|
||||
case patch_type::lef32: return "lef32";
|
||||
case patch_type::lef64: return "lef64";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
void patch_engine::append(const std::string& patch)
|
||||
{
|
||||
if (fs::file f{patch})
|
||||
{
|
||||
auto root = YAML::Load(f.to_string());
|
||||
|
||||
for (auto pair : root)
|
||||
{
|
||||
auto& name = pair.first.Scalar();
|
||||
auto& data = m_map[name];
|
||||
|
||||
for (auto patch : pair.second)
|
||||
{
|
||||
u64 type64 = 0;
|
||||
cfg::try_to_enum_value(&type64, &fmt_class_string<patch_type>::format, patch[0].Scalar());
|
||||
|
||||
struct patch info{};
|
||||
info.type = static_cast<patch_type>(type64);
|
||||
info.offset = patch[1].as<u32>(0);
|
||||
|
||||
switch (info.type)
|
||||
{
|
||||
case patch_type::load:
|
||||
{
|
||||
// Special syntax: copy named sequence (must be loaded before)
|
||||
const auto found = m_map.find(patch[1].Scalar());
|
||||
|
||||
if (found != m_map.end())
|
||||
{
|
||||
// Address modifier (optional)
|
||||
const u32 mod = patch[2].as<u32>(0);
|
||||
|
||||
for (const auto& rd : found->second)
|
||||
{
|
||||
info = rd;
|
||||
info.offset += mod;
|
||||
data.emplace_back(info);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: error
|
||||
break;
|
||||
}
|
||||
case patch_type::bef32:
|
||||
case patch_type::lef32:
|
||||
{
|
||||
info.value_as<f32>() = patch[2].as<f32>();
|
||||
break;
|
||||
}
|
||||
case patch_type::bef64:
|
||||
case patch_type::lef64:
|
||||
{
|
||||
info.value_as<f64>() = patch[2].as<f64>();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
info.value = patch[2].as<u64>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data.emplace_back(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t patch_engine::apply(const std::string& name, u8* dst) const
|
||||
{
|
||||
const auto found = m_map.find(name);
|
||||
|
||||
if (found == m_map.cend())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Apply modifications sequentially
|
||||
for (const auto& p : found->second)
|
||||
{
|
||||
auto ptr = dst + p.offset;
|
||||
|
||||
switch (p.type)
|
||||
{
|
||||
case patch_type::load:
|
||||
{
|
||||
// Invalid in this context
|
||||
break;
|
||||
}
|
||||
case patch_type::byte:
|
||||
{
|
||||
*ptr = static_cast<u8>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::le16:
|
||||
{
|
||||
*reinterpret_cast<le_t<u16, 1>*>(ptr) = static_cast<u16>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::le32:
|
||||
case patch_type::lef32:
|
||||
{
|
||||
*reinterpret_cast<le_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::le64:
|
||||
case patch_type::lef64:
|
||||
{
|
||||
*reinterpret_cast<le_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::be16:
|
||||
{
|
||||
*reinterpret_cast<be_t<u16, 1>*>(ptr) = static_cast<u16>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::be32:
|
||||
case patch_type::bef32:
|
||||
{
|
||||
*reinterpret_cast<be_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
|
||||
break;
|
||||
}
|
||||
case patch_type::be64:
|
||||
case patch_type::bef64:
|
||||
{
|
||||
*reinterpret_cast<be_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found->second.size();
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "BEType.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
enum class patch_type
|
||||
{
|
||||
load,
|
||||
byte,
|
||||
le16,
|
||||
le32,
|
||||
le64,
|
||||
lef32,
|
||||
lef64,
|
||||
be16,
|
||||
be32,
|
||||
be64,
|
||||
bef32,
|
||||
bef64,
|
||||
};
|
||||
|
||||
class patch_engine
|
||||
{
|
||||
struct patch
|
||||
{
|
||||
patch_type type;
|
||||
u32 offset;
|
||||
u64 value;
|
||||
|
||||
template <typename T>
|
||||
T& value_as()
|
||||
{
|
||||
return *reinterpret_cast<T*>(reinterpret_cast<char*>(&value));
|
||||
}
|
||||
};
|
||||
|
||||
// Database
|
||||
std::unordered_map<std::string, std::vector<patch>> m_map;
|
||||
|
||||
public:
|
||||
// Load from file
|
||||
void append(const std::string& path);
|
||||
|
||||
// Apply patch (returns the number of entries applied)
|
||||
std::size_t apply(const std::string& name, u8* dst) const;
|
||||
};
|
||||
+8
-28
@@ -204,11 +204,11 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
else if (fmt[0] == 'h')
|
||||
{
|
||||
fmt++, ctx.size++;
|
||||
ctx.type = src.size_char;
|
||||
ctx.type = sizeof(char);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.type = src.size_short;
|
||||
ctx.type = sizeof(short);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -223,11 +223,11 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
else if (fmt[0] == 'l')
|
||||
{
|
||||
fmt++, ctx.size++;
|
||||
ctx.type = src.size_llong;
|
||||
ctx.type = sizeof(llong);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.type = src.size_long;
|
||||
ctx.type = sizeof(long);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -241,7 +241,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.type = src.size_size;
|
||||
ctx.type = sizeof(std::size_t);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -255,7 +255,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.type = src.size_max;
|
||||
ctx.type = sizeof(std::intmax_t);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -269,7 +269,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.type = src.size_diff;
|
||||
ctx.type = sizeof(std::ptrdiff_t);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -339,11 +339,6 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = (u8)src.type(ctx.args);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = src.size_int;
|
||||
}
|
||||
}
|
||||
|
||||
// Sign-extended argument expected
|
||||
@@ -401,11 +396,6 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = (u8)src.type(ctx.args);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = src.size_int;
|
||||
}
|
||||
}
|
||||
|
||||
const u64 mask =
|
||||
@@ -457,11 +447,6 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = (u8)src.type(ctx.args);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = src.size_int;
|
||||
}
|
||||
}
|
||||
|
||||
const u64 mask =
|
||||
@@ -520,11 +505,6 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = (u8)src.type(ctx.args);
|
||||
|
||||
if (!ctx.type)
|
||||
{
|
||||
ctx.type = src.size_int;
|
||||
}
|
||||
}
|
||||
|
||||
const u64 mask =
|
||||
@@ -601,7 +581,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
const std::string _fmt(fmt - ctx.size, fmt);
|
||||
|
||||
const f64 arg0 = src.template get<f64>(0);
|
||||
const u64 arg0 = src.template get<u64>(0);
|
||||
const u64 arg1 = ctx.args >= 1 ? src.template get<u64>(1) : 0;
|
||||
const u64 arg2 = ctx.args >= 2 ? src.template get<u64>(2) : 0;
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
#include "cond.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
bool cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
|
||||
{
|
||||
verify(HERE), _old != -1; // Very unlikely: it requires 2^32 distinct threads to wait simultaneously
|
||||
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = _timeout * -10;
|
||||
|
||||
if (HRESULT rc = NtWaitForKeyedEvent(nullptr, &m_value, false, _timeout == -1 ? nullptr : &timeout))
|
||||
{
|
||||
verify(HERE), rc == WAIT_TIMEOUT;
|
||||
|
||||
// Retire
|
||||
if (!m_value.fetch_op([](u32& value) { if (value) value--; }))
|
||||
{
|
||||
NtWaitForKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
timespec timeout;
|
||||
timeout.tv_sec = _timeout / 1000000;
|
||||
timeout.tv_nsec = (_timeout % 1000000) * 1000;
|
||||
|
||||
for (u32 value = _old + 1;; value = m_value)
|
||||
{
|
||||
const int err = futex((int*)&m_value.raw(), FUTEX_WAIT_PRIVATE, value, _timeout == -1 ? nullptr : &timeout, nullptr, 0) == 0
|
||||
? 0
|
||||
: errno;
|
||||
|
||||
// Normal or timeout wakeup
|
||||
if (!err || (_timeout != -1 && err == ETIMEDOUT))
|
||||
{
|
||||
// Cleanup (remove waiter)
|
||||
verify(HERE), m_value--;
|
||||
return !err;
|
||||
}
|
||||
|
||||
// Not a wakeup
|
||||
verify(HERE), err == EAGAIN;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void cond_variable::imp_wake(u32 _count) noexcept
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Try to subtract required amount of waiters
|
||||
const u32 count = m_value.atomic_op([=](u32& value)
|
||||
{
|
||||
if (value > _count)
|
||||
{
|
||||
value -= _count;
|
||||
return _count;
|
||||
}
|
||||
|
||||
return std::exchange(value, 0);
|
||||
});
|
||||
|
||||
for (u32 i = count; i > 0; i--)
|
||||
{
|
||||
NtReleaseKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
}
|
||||
#else
|
||||
for (u32 i = _count; i > 0; std::this_thread::yield())
|
||||
{
|
||||
const u32 value = m_value;
|
||||
|
||||
// Constrain remaining amount with imaginary waiter count
|
||||
if (i > value)
|
||||
{
|
||||
i = value;
|
||||
}
|
||||
|
||||
if (!value || i == 0)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (const int res = futex((int*)&m_value.raw(), FUTEX_WAKE_PRIVATE, i > INT_MAX ? INT_MAX : i, nullptr, nullptr, 0))
|
||||
{
|
||||
verify(HERE), res >= 0 && (u32)res <= i;
|
||||
i -= res;
|
||||
}
|
||||
|
||||
if (!m_value || i == 0)
|
||||
{
|
||||
// Escape
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
// Lightweight condition variable
|
||||
class cond_variable
|
||||
{
|
||||
// Internal waiter counter
|
||||
atomic_t<u32> m_value{0};
|
||||
|
||||
protected:
|
||||
// Internal waiting function
|
||||
bool imp_wait(u32 _old, u64 _timeout) noexcept;
|
||||
|
||||
// Try to notify up to _count threads
|
||||
void imp_wake(u32 _count) noexcept;
|
||||
|
||||
public:
|
||||
constexpr cond_variable() = default;
|
||||
|
||||
// Intrusive wait algorithm for lockable objects
|
||||
template <typename T>
|
||||
explicit_bool_t wait(T& object, u64 usec_timeout = -1)
|
||||
{
|
||||
const u32 _old = m_value.fetch_add(1); // Increment waiter counter
|
||||
object.unlock();
|
||||
const bool res = imp_wait(_old, usec_timeout);
|
||||
object.lock();
|
||||
return res;
|
||||
}
|
||||
|
||||
// Wake one thread
|
||||
void notify_one() noexcept
|
||||
{
|
||||
if (m_value)
|
||||
{
|
||||
imp_wake(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake all threads
|
||||
void notify_all() noexcept
|
||||
{
|
||||
if (m_value)
|
||||
{
|
||||
imp_wake(-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -57,13 +57,4 @@ namespace utils
|
||||
{
|
||||
return loaded();
|
||||
}
|
||||
|
||||
void* get_proc_address(const char* lib, const char* name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<void*>(GetProcAddress(GetModuleHandleA(lib), name));
|
||||
#else
|
||||
return dlsym(dlopen(lib, RTLD_NOLOAD), name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,43 +38,4 @@ namespace utils
|
||||
bool loaded() const;
|
||||
explicit operator bool() const;
|
||||
};
|
||||
|
||||
// (assume the lib is always loaded)
|
||||
void* get_proc_address(const char* lib, const char* name);
|
||||
|
||||
template <typename F>
|
||||
struct dynamic_import
|
||||
{
|
||||
static_assert(sizeof(F) == 0, "Invalid function type");
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct dynamic_import<R(Args...)>
|
||||
{
|
||||
R(*ptr)(Args...);
|
||||
const char* const lib;
|
||||
const char* const name;
|
||||
|
||||
// Constant initialization
|
||||
constexpr dynamic_import(const char* lib, const char* name)
|
||||
: ptr(nullptr)
|
||||
, lib(lib)
|
||||
, name(name)
|
||||
{
|
||||
}
|
||||
|
||||
// Caller
|
||||
R operator()(Args... args)
|
||||
{
|
||||
if (!ptr)
|
||||
{
|
||||
// TODO: atomic
|
||||
ptr = reinterpret_cast<R(*)(Args...)>(get_proc_address(lib, name));
|
||||
}
|
||||
|
||||
return ptr(args...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define DYNAMIC_IMPORT(lib, name, ...) static utils::dynamic_import<__VA_ARGS__> name(lib, #name);
|
||||
|
||||
@@ -1,193 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
|
||||
#include "Atomic.h"
|
||||
|
||||
template <typename T, T Mod = T::__state_enum_max, typename Under = std::underlying_type_t<T>>
|
||||
T operator ++(T& value, int)
|
||||
{
|
||||
return std::exchange(value, static_cast<T>(value < T{} || value >= Mod ? static_cast<Under>(0) : static_cast<Under>(value) + 1));
|
||||
}
|
||||
|
||||
template <typename T, T Mod = T::__state_enum_max, typename Under = std::underlying_type_t<T>>
|
||||
T operator --(T& value, int)
|
||||
{
|
||||
return std::exchange(value, static_cast<T>(value <= T{} || value >= static_cast<Under>(Mod) - 1 ? static_cast<Under>(Mod) - 1 : static_cast<Under>(value) - 1));
|
||||
}
|
||||
|
||||
template <typename T, typename CRT, std::size_t Size = static_cast<std::underlying_type_t<T>>(T::__state_enum_max)>
|
||||
class state_machine
|
||||
{
|
||||
using under = std::underlying_type_t<T>;
|
||||
using ftype = void(CRT::*)(T);
|
||||
|
||||
atomic_t<T> m_value;
|
||||
|
||||
template <std::size_t... Ind>
|
||||
static inline ftype transition_map(std::integer_sequence<std::size_t, Ind...>, T state)
|
||||
{
|
||||
// Constantly initialized list of functions
|
||||
static constexpr ftype map[Size]{&CRT::template transition<static_cast<T>(Ind)>...};
|
||||
|
||||
// Unsafe table lookup (TODO)
|
||||
return map[static_cast<under>(state)];
|
||||
}
|
||||
|
||||
// "Convert" variable argument to template argument
|
||||
static inline ftype transition_get(T state)
|
||||
{
|
||||
return transition_map(std::make_index_sequence<Size>(), state);
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr state_machine()
|
||||
: m_value{T{}}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr state_machine(T state)
|
||||
: m_value{state}
|
||||
{
|
||||
}
|
||||
|
||||
// Get current state
|
||||
T state_get() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// Unconditionally set state
|
||||
void state_set(T state)
|
||||
{
|
||||
T _old = m_value.exchange(state);
|
||||
|
||||
if (_old != state)
|
||||
{
|
||||
(static_cast<CRT*>(this)->*transition_get(state))(_old);
|
||||
}
|
||||
}
|
||||
|
||||
// Conditionally set state (optimized)
|
||||
explicit_bool_t state_test_and_set(T expected, T state)
|
||||
{
|
||||
if (m_value == expected && m_value.compare_and_swap_test(expected, state))
|
||||
{
|
||||
(static_cast<CRT*>(this)->*transition_get(state))(expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Conditionally set state (list version)
|
||||
explicit_bool_t state_test_and_set(std::initializer_list<T> expected, T state)
|
||||
{
|
||||
T _old;
|
||||
|
||||
if (m_value.atomic_op([&](T& value)
|
||||
{
|
||||
for (T x : expected)
|
||||
{
|
||||
if (value == x)
|
||||
{
|
||||
_old = std::exchange(value, state);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}))
|
||||
{
|
||||
(static_cast<CRT*>(this)->*transition_get(state))(_old);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unconditionally set next state
|
||||
void state_next()
|
||||
{
|
||||
T _old, state = m_value.op_fetch([&](T& value)
|
||||
{
|
||||
_old = value++;
|
||||
});
|
||||
|
||||
(static_cast<CRT*>(this)->*transition_get(state))(_old);
|
||||
}
|
||||
|
||||
// Unconditionally set previous state
|
||||
void state_prev()
|
||||
{
|
||||
T _old, state = m_value.op_fetch([&](T& value)
|
||||
{
|
||||
_old = value--;
|
||||
});
|
||||
|
||||
(static_cast<CRT*>(this)->*transition_get(state))(_old);
|
||||
}
|
||||
|
||||
// Get number of states
|
||||
static constexpr std::size_t size()
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
};
|
||||
|
||||
//enum class test_state
|
||||
//{
|
||||
// on,
|
||||
// off,
|
||||
// la,
|
||||
//
|
||||
// __state_enum_max // 3
|
||||
//};
|
||||
//
|
||||
//struct test_machine final : state_machine<test_state, test_machine>
|
||||
//{
|
||||
// template <test_state>
|
||||
// void transition(test_state old_state);
|
||||
//
|
||||
// void on()
|
||||
// {
|
||||
// state_set(test_state::on);
|
||||
// }
|
||||
//
|
||||
// void off()
|
||||
// {
|
||||
// state_set(test_state::off);
|
||||
// }
|
||||
//
|
||||
// void test()
|
||||
// {
|
||||
// state_next();
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//template <>
|
||||
//void test_machine::transition<test_state::on>(test_state)
|
||||
//{
|
||||
// LOG_SUCCESS(GENERAL, "ON");
|
||||
//}
|
||||
//
|
||||
//template <>
|
||||
//void test_machine::transition<test_state::off>(test_state)
|
||||
//{
|
||||
// LOG_SUCCESS(GENERAL, "OFF");
|
||||
//}
|
||||
//
|
||||
//
|
||||
//template <>
|
||||
//void test_machine::transition<test_state::la>(test_state)
|
||||
//{
|
||||
// on();
|
||||
// off();
|
||||
// test();
|
||||
//}
|
||||
|
||||
enum class event_result
|
||||
{
|
||||
skip,
|
||||
|
||||
@@ -731,9 +731,9 @@ struct area_base
|
||||
{
|
||||
return{ x1 * size.width, y1 * size.height, x2 * size.width, y2 * size.height };
|
||||
}
|
||||
constexpr area_base operator * (const f32& value) const
|
||||
constexpr area_base operator * (const T& value) const
|
||||
{
|
||||
return{ (T)(x1 * value), (T)(y1 * value), (T)(x2 * value), (T)(y2 * value) };
|
||||
return{ x1 * value, y1 * value, x2 * value, y2 * value };
|
||||
}
|
||||
|
||||
template<typename NT>
|
||||
|
||||
@@ -47,7 +47,6 @@ if errorlevel 1 (
|
||||
echo // This is a generated file. > "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION "unknown" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH "unknown" >> "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo // If you don't want this file to update/recompile, change to 1. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION_NO_UPDATE 0 >> "%GIT_VERSION_FILE%"
|
||||
@@ -56,7 +55,6 @@ if errorlevel 1 (
|
||||
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set GIT_VERSION=%%I
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%GIT_VERSION%-%%I
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
|
||||
rem // Don't modify the file if it already has the current version.
|
||||
if exist "%GIT_VERSION_FILE%" (
|
||||
@@ -69,7 +67,6 @@ if exist "%GIT_VERSION_FILE%" (
|
||||
echo // This is a generated file. > "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION "%GIT_VERSION%" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH "%GIT_BRANCH%" >> "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo // If you don't want this file to update/recompile, change to 1. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION_NO_UPDATE 0 >> "%GIT_VERSION_FILE%"
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
namespace rpcs3
|
||||
{
|
||||
template<typename T>
|
||||
static size_t hash_base(T value)
|
||||
{
|
||||
return static_cast<size_t>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static size_t hash_struct(const T& value)
|
||||
{
|
||||
// FNV 64-bit
|
||||
size_t result = 14695981039346656037ull;
|
||||
const unsigned char *bytes = reinterpret_cast<const unsigned char*>(&value);
|
||||
|
||||
for (size_t n = 0; n < sizeof(T); ++n)
|
||||
{
|
||||
result ^= bytes[n];
|
||||
result *= 1099511628211ull;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+3
-186
@@ -66,9 +66,9 @@ public:
|
||||
constexpr lf_fifo() = default;
|
||||
|
||||
// Get current "push" position
|
||||
u32 size() const
|
||||
u32 size()
|
||||
{
|
||||
return reinterpret_cast<const atomic_t<u32>&>(m_ctrl).load(); // Hack
|
||||
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).load(); // Hack
|
||||
}
|
||||
|
||||
// Acquire the place for one or more elements.
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
}
|
||||
|
||||
// Get current "pop" position
|
||||
u32 peek() const
|
||||
u32 peek()
|
||||
{
|
||||
return m_ctrl.load().pop;
|
||||
}
|
||||
@@ -145,186 +145,3 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Fixed-size single-producer single-consumer queue
|
||||
template <typename T, std::uint32_t N>
|
||||
class lf_spsc
|
||||
{
|
||||
// If N is a power of 2, m_push/m_pop can safely overflow and the algorithm is simplified
|
||||
static_assert(N && (1u << 31) % N == 0, "lf_spsc<> error: size must be power of 2");
|
||||
|
||||
protected:
|
||||
volatile std::uint32_t m_push{0};
|
||||
volatile std::uint32_t m_pop{0};
|
||||
T m_data[N]{};
|
||||
|
||||
public:
|
||||
constexpr lf_spsc() = default;
|
||||
|
||||
// Try to push (producer only)
|
||||
template <typename T2>
|
||||
bool try_push(T2&& data)
|
||||
{
|
||||
const std::uint32_t pos = m_push;
|
||||
|
||||
if (pos - m_pop >= N)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_mm_lfence();
|
||||
m_data[pos % N] = std::forward<T2>(data);
|
||||
_mm_sfence();
|
||||
m_push = pos + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to get push pointer (producer only)
|
||||
operator T*()
|
||||
{
|
||||
const std::uint32_t pos = m_push;
|
||||
|
||||
if (pos - m_pop >= N)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_mm_lfence();
|
||||
return m_data + (pos % N);
|
||||
}
|
||||
|
||||
// Increment push counter (producer only)
|
||||
void end_push()
|
||||
{
|
||||
const std::uint32_t pos = m_push;
|
||||
|
||||
if (pos - m_pop < N)
|
||||
{
|
||||
_mm_sfence();
|
||||
m_push = pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe access
|
||||
T& get_push(std::size_t i)
|
||||
{
|
||||
_mm_lfence();
|
||||
return m_data[(m_push + i) % N];
|
||||
}
|
||||
|
||||
// Try to pop (consumer only)
|
||||
template <typename T2>
|
||||
bool try_pop(T2& out)
|
||||
{
|
||||
const std::uint32_t pos = m_pop;
|
||||
|
||||
if (m_push - pos <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_mm_lfence();
|
||||
out = std::move(m_data[pos % N]);
|
||||
_mm_sfence();
|
||||
m_pop = pos + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Increment pop counter (consumer only)
|
||||
void end_pop()
|
||||
{
|
||||
const std::uint32_t pos = m_pop;
|
||||
|
||||
if (m_push - pos > 0)
|
||||
{
|
||||
_mm_sfence();
|
||||
m_pop = pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Get size (consumer only)
|
||||
std::uint32_t size() const
|
||||
{
|
||||
return m_push - m_pop;
|
||||
}
|
||||
|
||||
// Direct access (consumer only)
|
||||
T& operator [](std::size_t i)
|
||||
{
|
||||
_mm_lfence();
|
||||
return m_data[(m_pop + i) % N];
|
||||
}
|
||||
};
|
||||
|
||||
// Fixed-size multi-producer single-consumer queue
|
||||
template <typename T, std::uint32_t N>
|
||||
class lf_mpsc : lf_spsc<T, N>
|
||||
{
|
||||
protected:
|
||||
using lf_spsc<T, N>::m_push;
|
||||
using lf_spsc<T, N>::m_pop;
|
||||
using lf_spsc<T, N>::m_data;
|
||||
|
||||
enum : std::uint64_t
|
||||
{
|
||||
c_ack = 1ull << 0,
|
||||
c_rel = 1ull << 32,
|
||||
};
|
||||
|
||||
atomic_t<std::uint64_t> m_lock{0};
|
||||
|
||||
void release(std::uint64_t value)
|
||||
{
|
||||
// Push all pending elements at once when possible
|
||||
if (value && value % c_rel == value / c_rel)
|
||||
{
|
||||
_mm_sfence();
|
||||
m_push += value % c_rel;
|
||||
m_lock.compare_and_swap_test(value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr lf_mpsc() = default;
|
||||
|
||||
// Try to get push pointer
|
||||
operator T*()
|
||||
{
|
||||
const std::uint64_t old = m_lock.fetch_add(c_ack);
|
||||
const std::uint32_t pos = m_push;
|
||||
|
||||
if (old % N >= N || pos - m_pop >= N - (old % N))
|
||||
{
|
||||
release(m_lock.sub_fetch(c_ack));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_data + ((pos + old) % N);
|
||||
}
|
||||
|
||||
// Increment push counter (producer only)
|
||||
void end_push()
|
||||
{
|
||||
release(m_lock.add_fetch(c_rel));
|
||||
}
|
||||
|
||||
// Try to push
|
||||
template <typename T2>
|
||||
bool try_push(T2&& data)
|
||||
{
|
||||
if (T* ptr = *this)
|
||||
{
|
||||
*ptr = std::forward<T2>(data);
|
||||
end_push();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable consumer methods
|
||||
using lf_spsc<T, N>::try_pop;
|
||||
using lf_spsc<T, N>::end_pop;
|
||||
using lf_spsc<T, N>::size;
|
||||
using lf_spsc<T, N>::operator [];
|
||||
};
|
||||
|
||||
@@ -1,334 +0,0 @@
|
||||
#include "mutex.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include <climits>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
// TLS variable for tracking owned mutexes
|
||||
thread_local std::vector<shared_mutex*> g_tls_locks;
|
||||
|
||||
void shared_mutex::imp_lock_shared(s64 _old)
|
||||
{
|
||||
verify("shared_mutex overflow" HERE), _old <= c_max;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
busy_wait();
|
||||
|
||||
const s64 value = m_value.load();
|
||||
|
||||
if (value >= c_min && m_value.compare_and_swap_test(value, value - c_min))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Acquire writer lock
|
||||
imp_wait(m_value.load());
|
||||
|
||||
// Convert to reader lock
|
||||
s64 value = m_value.fetch_add(c_one - c_min);
|
||||
|
||||
// Proceed exclusively
|
||||
return;
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
imp_unlock(value);
|
||||
}
|
||||
|
||||
// Wait as a reader if necessary
|
||||
if (value + c_one - c_min < 0)
|
||||
{
|
||||
NtWaitForKeyedEvent(nullptr, (int*)&m_value + 1, false, nullptr);
|
||||
}
|
||||
#else
|
||||
// Acquire writer lock
|
||||
imp_wait(0);
|
||||
|
||||
// Convert to reader lock
|
||||
m_value += c_one - c_min;
|
||||
|
||||
// Disabled code
|
||||
while (false)
|
||||
{
|
||||
const s64 value0 = m_value.fetch_op([](s64& value)
|
||||
{
|
||||
if (value >= c_min)
|
||||
{
|
||||
value -= c_min;
|
||||
}
|
||||
});
|
||||
|
||||
if (value0 >= c_min)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire writer lock
|
||||
imp_wait(value0);
|
||||
|
||||
// Convert to reader lock
|
||||
s64 value1 = m_value.fetch_add(c_one - c_min);
|
||||
|
||||
if (value1 != 0)
|
||||
{
|
||||
imp_unlock(value1);
|
||||
}
|
||||
|
||||
value1 += c_one - c_min;
|
||||
|
||||
if (value1 > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait as a reader if necessary
|
||||
while (futex((int*)&m_value.raw() + IS_LE_MACHINE, FUTEX_WAIT_BITSET_PRIVATE, int(value1 >> 32), nullptr, nullptr, INT_MIN))
|
||||
{
|
||||
value1 = m_value.load();
|
||||
|
||||
if (value1 >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If blocked by writers, release the reader lock and try again
|
||||
const s64 value2 = m_value.fetch_op([](s64& value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
value += c_min;
|
||||
}
|
||||
});
|
||||
|
||||
if (value2 >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
imp_unlock_shared(value2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void shared_mutex::imp_unlock_shared(s64 _old)
|
||||
{
|
||||
verify("shared_mutex overflow" HERE), _old + c_min <= c_max;
|
||||
|
||||
// Check reader count, notify the writer if necessary
|
||||
if ((_old + c_min) % c_one == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
NtReleaseKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
#else
|
||||
m_value -= c_sig;
|
||||
|
||||
futex((int*)&m_value.raw() + IS_LE_MACHINE, FUTEX_WAKE_BITSET_PRIVATE, 1, nullptr, nullptr, u32(c_sig >> 32));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::imp_wait(s64)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_value.sub_fetch(c_one))
|
||||
{
|
||||
NtWaitForKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
}
|
||||
#else
|
||||
if (!m_value.sub_fetch(c_one))
|
||||
{
|
||||
// Return immediately if locked
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Load new value, try to acquire c_sig
|
||||
const s64 value = m_value.fetch_op([](s64& value)
|
||||
{
|
||||
if (value <= c_one - c_sig)
|
||||
{
|
||||
value += c_sig;
|
||||
}
|
||||
});
|
||||
|
||||
if (value <= c_one - c_sig)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
futex((int*)&m_value.raw() + IS_LE_MACHINE, FUTEX_WAIT_BITSET_PRIVATE, int(value >> 32), nullptr, nullptr, u32(c_sig >> 32));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void shared_mutex::imp_lock(s64 _old)
|
||||
{
|
||||
verify("shared_mutex overflow" HERE), _old <= c_max;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
busy_wait();
|
||||
|
||||
const s64 value = m_value.load();
|
||||
|
||||
if (value == c_one && m_value.compare_and_swap_test(c_one, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
imp_wait(m_value.load());
|
||||
}
|
||||
|
||||
void shared_mutex::imp_unlock(s64 _old)
|
||||
{
|
||||
verify("shared_mutex overflow" HERE), _old + c_one <= c_max;
|
||||
|
||||
// 1) Notify the next writer if necessary
|
||||
// 2) Notify all readers otherwise if necessary
|
||||
#ifdef _WIN32
|
||||
if (_old + c_one <= 0)
|
||||
{
|
||||
NtReleaseKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
}
|
||||
else if (s64 count = -_old / c_min * 0)
|
||||
{
|
||||
// Disabled code
|
||||
while (count--)
|
||||
{
|
||||
NtReleaseKeyedEvent(nullptr, (int*)&m_value + 1, false, nullptr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_old + c_one <= 0)
|
||||
{
|
||||
m_value -= c_sig;
|
||||
|
||||
futex((int*)&m_value.raw() + IS_LE_MACHINE, FUTEX_WAKE_BITSET_PRIVATE, 1, nullptr, nullptr, u32(c_sig >> 32));
|
||||
}
|
||||
else if (false)
|
||||
{
|
||||
// Disabled code
|
||||
futex((int*)&m_value.raw() + IS_LE_MACHINE, FUTEX_WAKE_BITSET_PRIVATE, INT_MAX, nullptr, nullptr, INT_MIN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void shared_mutex::imp_lock_upgrade()
|
||||
{
|
||||
// TODO
|
||||
unlock_shared();
|
||||
lock();
|
||||
}
|
||||
|
||||
void shared_mutex::imp_lock_degrade()
|
||||
{
|
||||
// TODO
|
||||
unlock();
|
||||
lock_shared();
|
||||
}
|
||||
|
||||
bool shared_mutex::try_lock_shared()
|
||||
{
|
||||
// Conditional decrement
|
||||
return m_value.fetch_op([](s64& value) { if (value >= c_min) value -= c_min; }) >= c_min;
|
||||
}
|
||||
|
||||
bool shared_mutex::try_lock()
|
||||
{
|
||||
// Conditional decrement (TODO: obtain c_sig)
|
||||
return m_value.compare_and_swap_test(c_one, 0);
|
||||
}
|
||||
|
||||
bool shared_mutex::try_lock_upgrade()
|
||||
{
|
||||
// TODO
|
||||
return m_value.compare_and_swap_test(c_one - c_min, 0);
|
||||
}
|
||||
|
||||
bool shared_mutex::try_lock_degrade()
|
||||
{
|
||||
// TODO
|
||||
return m_value.compare_and_swap_test(0, c_one - c_min);
|
||||
}
|
||||
|
||||
safe_reader_lock::safe_reader_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
, m_is_owned(false)
|
||||
{
|
||||
if (std::count(g_tls_locks.cbegin(), g_tls_locks.cend(), &m_mutex) == 0)
|
||||
{
|
||||
m_is_owned = true;
|
||||
|
||||
if (m_is_owned)
|
||||
{
|
||||
m_mutex.lock_shared();
|
||||
g_tls_locks.emplace_back(&m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: order locks
|
||||
}
|
||||
}
|
||||
|
||||
safe_reader_lock::~safe_reader_lock()
|
||||
{
|
||||
if (m_is_owned)
|
||||
{
|
||||
m_mutex.unlock_shared();
|
||||
g_tls_locks.erase(std::remove(g_tls_locks.begin(), g_tls_locks.end(), &m_mutex), g_tls_locks.cend());
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: order locks
|
||||
}
|
||||
|
||||
safe_writer_lock::safe_writer_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
, m_is_owned(false)
|
||||
, m_is_upgraded(false)
|
||||
{
|
||||
if (std::count(g_tls_locks.cbegin(), g_tls_locks.cend(), &m_mutex) == 0)
|
||||
{
|
||||
m_is_owned = true;
|
||||
|
||||
if (m_is_owned)
|
||||
{
|
||||
m_mutex.lock_shared();
|
||||
g_tls_locks.emplace_back(&m_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: order locks
|
||||
}
|
||||
|
||||
if (m_mutex.is_reading())
|
||||
{
|
||||
m_is_upgraded = true;
|
||||
m_mutex.lock_upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
safe_writer_lock::~safe_writer_lock()
|
||||
{
|
||||
if (m_is_upgraded)
|
||||
{
|
||||
m_mutex.lock_degrade();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_is_owned)
|
||||
{
|
||||
m_mutex.unlock();
|
||||
g_tls_locks.erase(std::remove(g_tls_locks.begin(), g_tls_locks.end(), &m_mutex), g_tls_locks.cend());
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: order locks
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
// Shared mutex.
|
||||
class shared_mutex final
|
||||
{
|
||||
enum : s64
|
||||
{
|
||||
c_one = 1ull << 31, // Fixed-point 1.0 value (one writer)
|
||||
c_min = 0x00000001, // Fixed-point 1.0/max_readers value
|
||||
c_sig = 1ull << 62,
|
||||
c_max = c_one
|
||||
};
|
||||
|
||||
atomic_t<s64> m_value{c_one}; // Semaphore-alike counter
|
||||
|
||||
void imp_lock_shared(s64 _old);
|
||||
void imp_unlock_shared(s64 _old);
|
||||
void imp_wait(s64 _old);
|
||||
void imp_lock(s64 _old);
|
||||
void imp_unlock(s64 _old);
|
||||
|
||||
void imp_lock_upgrade();
|
||||
void imp_lock_degrade();
|
||||
|
||||
public:
|
||||
constexpr shared_mutex() = default;
|
||||
|
||||
bool try_lock_shared();
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
const s64 value = m_value.load();
|
||||
|
||||
// Fast path: decrement if positive
|
||||
if (UNLIKELY(value < c_min || value > c_one || !m_value.compare_and_swap_test(value, value - c_min)))
|
||||
{
|
||||
imp_lock_shared(value);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_shared()
|
||||
{
|
||||
// Unconditional increment
|
||||
const s64 value = m_value.fetch_add(c_min);
|
||||
|
||||
if (value < 0 || value > c_one - c_min)
|
||||
{
|
||||
imp_unlock_shared(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock();
|
||||
|
||||
void lock()
|
||||
{
|
||||
// Try to lock
|
||||
const s64 value = m_value.compare_and_swap(c_one, 0);
|
||||
|
||||
if (value != c_one)
|
||||
{
|
||||
imp_lock(value);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
// Unconditional increment
|
||||
const s64 value = m_value.fetch_add(c_one);
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
imp_unlock(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgrade();
|
||||
|
||||
void lock_upgrade()
|
||||
{
|
||||
if (!m_value.compare_and_swap_test(c_one - c_min, 0))
|
||||
{
|
||||
imp_lock_upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_degrade();
|
||||
|
||||
void lock_degrade()
|
||||
{
|
||||
if (!m_value.compare_and_swap_test(0, c_one - c_min))
|
||||
{
|
||||
imp_lock_degrade();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_reading() const
|
||||
{
|
||||
return (m_value.load() % c_one) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Simplified shared (reader) lock implementation.
|
||||
class reader_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
bool m_upgraded = false;
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_upgraded ? m_mutex.lock() : m_mutex.lock_shared();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
friend class cond_variable;
|
||||
|
||||
public:
|
||||
reader_lock(const reader_lock&) = delete;
|
||||
|
||||
explicit reader_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
|
||||
// One-way lock upgrade
|
||||
void upgrade()
|
||||
{
|
||||
if (!m_upgraded)
|
||||
{
|
||||
m_mutex.lock_upgrade();
|
||||
m_upgraded = true;
|
||||
}
|
||||
}
|
||||
|
||||
~reader_lock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Simplified exclusive (writer) lock implementation.
|
||||
class writer_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
friend class cond_variable;
|
||||
|
||||
public:
|
||||
writer_lock(const writer_lock&) = delete;
|
||||
|
||||
explicit writer_lock(shared_mutex& mutex)
|
||||
: m_mutex(mutex)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
|
||||
~writer_lock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
};
|
||||
|
||||
// Safe reader lock. Can be recursive above other safe locks (reader or writer).
|
||||
class safe_reader_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
bool m_is_owned;
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_mutex.lock_shared();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
friend class cond_variable;
|
||||
|
||||
public:
|
||||
safe_reader_lock(const safe_reader_lock&) = delete;
|
||||
|
||||
explicit safe_reader_lock(shared_mutex& mutex);
|
||||
|
||||
~safe_reader_lock();
|
||||
};
|
||||
|
||||
// Safe writer lock. Can be recursive above other safe locks. Performs upgrade and degrade operations above existing reader lock if necessary.
|
||||
class safe_writer_lock final
|
||||
{
|
||||
shared_mutex& m_mutex;
|
||||
bool m_is_owned;
|
||||
bool m_is_upgraded;
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
friend class cond_variable;
|
||||
|
||||
public:
|
||||
safe_writer_lock(const safe_writer_lock&) = delete;
|
||||
|
||||
explicit safe_writer_lock(shared_mutex& mutex);
|
||||
|
||||
~safe_writer_lock();
|
||||
};
|
||||
+3
-4
@@ -1,7 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "restore_new.h"
|
||||
#include "Utilities/rXml.h"
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
rXmlNode::rXmlNode() : handle()
|
||||
{
|
||||
@@ -61,9 +59,10 @@ rXmlDocument::rXmlDocument() : handle()
|
||||
{
|
||||
}
|
||||
|
||||
void rXmlDocument::Read(const std::string& data)
|
||||
void rXmlDocument::Load(const std::string & path)
|
||||
{
|
||||
handle.load_buffer(data.data(), data.size());
|
||||
// TODO: Unsure of use of c_str.
|
||||
handle.load_file(path.c_str());
|
||||
}
|
||||
|
||||
std::shared_ptr<rXmlNode> rXmlDocument::GetRoot()
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct rXmlDocument
|
||||
rXmlDocument();
|
||||
rXmlDocument(const rXmlDocument& other) = delete;
|
||||
rXmlDocument &operator=(const rXmlDocument& other) = delete;
|
||||
void Read(const std::string& data);
|
||||
void Load(const std::string & path);
|
||||
std::shared_ptr<rXmlNode> GetRoot();
|
||||
|
||||
pugi::xml_document handle;
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
#include "sema.h"
|
||||
#include "sync.h"
|
||||
|
||||
void semaphore_base::imp_wait()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
busy_wait();
|
||||
|
||||
const s32 value = m_value.load();
|
||||
|
||||
if (value > 0 && m_value.compare_and_swap_test(value, value - 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
const s32 value = m_value.fetch_sub(1);
|
||||
|
||||
if (value <= 0)
|
||||
{
|
||||
NtWaitForKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
}
|
||||
#else
|
||||
while (true)
|
||||
{
|
||||
// Try hard way
|
||||
const s32 value = m_value.op_fetch([](s32& value)
|
||||
{
|
||||
// Use sign bit to acknowledge waiter presence
|
||||
if (value && value > INT32_MIN)
|
||||
{
|
||||
value--;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
// Remove sign bit
|
||||
value -= INT32_MIN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set sign bit
|
||||
value = INT32_MIN;
|
||||
}
|
||||
});
|
||||
|
||||
if (value >= 0)
|
||||
{
|
||||
// Signal other waiter to wake up or to restore sign bit
|
||||
futex(&m_value.raw(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
futex(&m_value.raw(), FUTEX_WAIT_PRIVATE, value, nullptr, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void semaphore_base::imp_post(s32 _old)
|
||||
{
|
||||
verify("semaphore_base: overflow" HERE), _old < 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
NtReleaseKeyedEvent(nullptr, &m_value, false, nullptr);
|
||||
#else
|
||||
futex(&m_value.raw(), FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool semaphore_base::try_wait()
|
||||
{
|
||||
// Conditional decrement
|
||||
const s32 value = m_value.fetch_op([](s32& value)
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
value -= 1;
|
||||
}
|
||||
});
|
||||
|
||||
return value > 0;
|
||||
}
|
||||
|
||||
bool semaphore_base::try_post(s32 _max)
|
||||
{
|
||||
// Conditional increment
|
||||
const s32 value = m_value.fetch_op([&](s32& value)
|
||||
{
|
||||
if (value < _max)
|
||||
{
|
||||
value += 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
imp_post(value);
|
||||
}
|
||||
|
||||
return value < _max;
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
// Lightweight semaphore helper class
|
||||
class semaphore_base
|
||||
{
|
||||
// Semaphore value
|
||||
atomic_t<s32> m_value;
|
||||
|
||||
void imp_wait();
|
||||
|
||||
void imp_post(s32 _old);
|
||||
|
||||
friend class semaphore_lock;
|
||||
|
||||
protected:
|
||||
explicit constexpr semaphore_base(s32 value)
|
||||
: m_value{value}
|
||||
{
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
// Load value
|
||||
const s32 value = m_value.load();
|
||||
|
||||
// Conditional decrement
|
||||
if (UNLIKELY(value <= 0 || !m_value.compare_and_swap_test(value, value - 1)))
|
||||
{
|
||||
imp_wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool try_wait();
|
||||
|
||||
void post(s32 _max)
|
||||
{
|
||||
// Unconditional increment
|
||||
const s32 value = m_value.fetch_add(1);
|
||||
|
||||
if (UNLIKELY(value < 0 || value >= _max))
|
||||
{
|
||||
imp_post(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_post(s32 _max);
|
||||
|
||||
public:
|
||||
// Get current semaphore value
|
||||
s32 get() const
|
||||
{
|
||||
// Load value
|
||||
const s32 value = m_value;
|
||||
|
||||
// Return only positive value
|
||||
return value < 0 ? 0 : value;
|
||||
}
|
||||
};
|
||||
|
||||
// Lightweight semaphore template (default arguments define binary semaphore and Def == Max)
|
||||
template <s32 Max = 1, s32 Def = Max>
|
||||
class semaphore final : public semaphore_base
|
||||
{
|
||||
static_assert(Max >= 0, "semaphore<>: Max is out of bounds");
|
||||
static_assert(Def >= 0, "semaphore<>: Def is out of bounds");
|
||||
static_assert(Def <= Max, "semaphore<>: Def is too big");
|
||||
|
||||
using base = semaphore_base;
|
||||
|
||||
public:
|
||||
// Default constructor (recommended)
|
||||
constexpr semaphore()
|
||||
: base{Def}
|
||||
{
|
||||
}
|
||||
|
||||
// Explicit value constructor (not recommended)
|
||||
explicit constexpr semaphore(s32 value)
|
||||
: base{value}
|
||||
{
|
||||
}
|
||||
|
||||
// Obtain a semaphore
|
||||
void wait()
|
||||
{
|
||||
return base::wait();
|
||||
}
|
||||
|
||||
// Try to obtain a semaphore
|
||||
explicit_bool_t try_wait()
|
||||
{
|
||||
return base::try_wait();
|
||||
}
|
||||
|
||||
// Return a semaphore
|
||||
void post()
|
||||
{
|
||||
return base::post(Max);
|
||||
}
|
||||
|
||||
// Try to return a semaphore
|
||||
explicit_bool_t try_post()
|
||||
{
|
||||
return base::try_post(Max);
|
||||
}
|
||||
|
||||
// Get max semaphore value
|
||||
static constexpr s32 size()
|
||||
{
|
||||
return Max;
|
||||
}
|
||||
};
|
||||
|
||||
class semaphore_lock
|
||||
{
|
||||
semaphore_base& m_base;
|
||||
|
||||
void lock()
|
||||
{
|
||||
m_base.wait();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m_base.post(INT32_MAX);
|
||||
}
|
||||
|
||||
friend class cond_variable;
|
||||
|
||||
public:
|
||||
explicit semaphore_lock(const semaphore_lock&) = delete;
|
||||
|
||||
semaphore_lock(semaphore_base& sema)
|
||||
: m_base(sema)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
|
||||
~semaphore_lock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user