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
-13
@@ -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,11 +55,9 @@
|
||||
rpcs3/git-version.h
|
||||
|
||||
# Visual Studio Files
|
||||
.vs/*
|
||||
*.vspx
|
||||
*.psess
|
||||
*.VC.*
|
||||
*.vcxproj.user
|
||||
|
||||
# Copyrighted files
|
||||
/bin/data/
|
||||
@@ -74,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
|
||||
@@ -91,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
|
||||
|
||||
+15
-16
@@ -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
|
||||
@@ -7,8 +11,11 @@
|
||||
ignore = dirty
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
url = https://github.com/RPCS3/llvm
|
||||
branch = release_60
|
||||
url = https://github.com/llvm-mirror/llvm
|
||||
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
|
||||
@@ -25,20 +32,12 @@
|
||||
[submodule "Utilities/yaml-cpp"]
|
||||
path = Utilities/yaml-cpp
|
||||
url = https://github.com/RPCS3/yaml-cpp
|
||||
[submodule "3rdparty/pugixml"]
|
||||
path = 3rdparty/pugixml
|
||||
url = https://github.com/RPCS3/pugixml
|
||||
[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/RPCS3/hidapi
|
||||
branch = master
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/Optional"]
|
||||
path = 3rdparty/Optional
|
||||
url = https://github.com/akrzemi1/Optional.git
|
||||
[submodule "3rdparty/pugixml"]
|
||||
path = 3rdparty/pugixml
|
||||
url = https://github.com/zeux/pugixml
|
||||
[submodule "rsx-debugger"]
|
||||
path = rsx-debugger
|
||||
url = https://github.com/RPCS3/rsx-debugger.git
|
||||
|
||||
+60
-94
@@ -1,124 +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:
|
||||
depth: false # Unshallow clone to obtain proper GIT_VERSION
|
||||
submodules: false
|
||||
|
||||
before_install:
|
||||
# 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 ;
|
||||
travis_wait 60 ./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations --verbose ;
|
||||
fi;
|
||||
|
||||
# Install updated libglew-dev since the version provided by trusty is outdated
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/g/glew/libglew-dev_2.0.0-5_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/g/glew/libglew2.0_2.0.0-5_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
sudo dpkg -i libglew2.0_2.0.0-5_amd64.deb libglew-dev_2.0.0-5_amd64.deb libvulkan1_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.61.1+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 3rdparty/Optional Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
- mkdir build
|
||||
- cd build
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.10.0/gcc_64/lib/cmake
|
||||
- export CXXFLAGS="$CXXFLAGS -DTRAVIS=true";
|
||||
- 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 -G Ninja;
|
||||
- ninja
|
||||
- # AppImage generation
|
||||
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.10.0/gcc_64/lib;
|
||||
DESTDIR=appdir ninja 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.10.0/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.10.0/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
rm ./appdir/usr/lib/libfreetype.so.6 ;
|
||||
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
|
||||
- ninja-build
|
||||
- libasound2-dev
|
||||
- libopenal-dev
|
||||
- freeglut3-dev
|
||||
#- libglew-dev
|
||||
#- libvulkan1
|
||||
#- libvulkan-dev
|
||||
- libc6-dev
|
||||
- llvm-4.0
|
||||
- llvm-4.0-dev
|
||||
# Clang 5.0 is now bundled in travis, so we no longer need the ppa version.
|
||||
#- clang-4.0
|
||||
- libedit-dev
|
||||
- g++-5
|
||||
- gcc-5
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
# We need to install qt 5.10.0 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
+292
-9
@@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2013-2014 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
|
||||
@@ -33,7 +33,7 @@ extern "C" {
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 31191 $ on $Date: 2015-05-14 06:31:39 -0400 (Thu, 14 May 2015) $
|
||||
** 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__)
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
|
||||
#define GL_GLEXT_VERSION 20150514
|
||||
#define GL_GLEXT_VERSION 20161024
|
||||
|
||||
/* Generated C header for:
|
||||
* API: gl
|
||||
@@ -2654,7 +2654,7 @@ typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint fram
|
||||
typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
|
||||
typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
|
||||
typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil);
|
||||
typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
|
||||
typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target);
|
||||
typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param);
|
||||
@@ -2777,7 +2777,7 @@ GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLs
|
||||
GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
|
||||
GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
|
||||
GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
|
||||
GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil);
|
||||
GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
|
||||
GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target);
|
||||
GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param);
|
||||
@@ -2875,6 +2875,17 @@ GLAPI void APIENTRY glTextureBarrier (void);
|
||||
#define GL_ARB_ES3_1_compatibility 1
|
||||
#endif /* GL_ARB_ES3_1_compatibility */
|
||||
|
||||
#ifndef GL_ARB_ES3_2_compatibility
|
||||
#define GL_ARB_ES3_2_compatibility 1
|
||||
#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE
|
||||
#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381
|
||||
#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382
|
||||
typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXARBPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
|
||||
#endif
|
||||
#endif /* GL_ARB_ES3_2_compatibility */
|
||||
|
||||
#ifndef GL_ARB_ES3_compatibility
|
||||
#define GL_ARB_ES3_compatibility 1
|
||||
#endif /* GL_ARB_ES3_compatibility */
|
||||
@@ -3288,6 +3299,10 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
|
||||
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
|
||||
#endif /* GL_ARB_fragment_shader */
|
||||
|
||||
#ifndef GL_ARB_fragment_shader_interlock
|
||||
#define GL_ARB_fragment_shader_interlock 1
|
||||
#endif /* GL_ARB_fragment_shader_interlock */
|
||||
|
||||
#ifndef GL_ARB_framebuffer_no_attachments
|
||||
#define GL_ARB_framebuffer_no_attachments 1
|
||||
#endif /* GL_ARB_framebuffer_no_attachments */
|
||||
@@ -3348,6 +3363,91 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen
|
||||
#define GL_ARB_gpu_shader_fp64 1
|
||||
#endif /* GL_ARB_gpu_shader_fp64 */
|
||||
|
||||
#ifndef GL_ARB_gpu_shader_int64
|
||||
#define GL_ARB_gpu_shader_int64 1
|
||||
#define GL_INT64_ARB 0x140E
|
||||
#define GL_INT64_VEC2_ARB 0x8FE9
|
||||
#define GL_INT64_VEC3_ARB 0x8FEA
|
||||
#define GL_INT64_VEC4_ARB 0x8FEB
|
||||
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
|
||||
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
|
||||
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1I64ARBPROC) (GLint location, GLint64 x);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2I64ARBPROC) (GLint location, GLint64 x, GLint64 y);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM3I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM3I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1UI64ARBPROC) (GLint location, GLuint64 x);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM3UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM3UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLGETUNIFORMI64VARBPROC) (GLuint program, GLint location, GLint64 *params);
|
||||
typedef void (APIENTRYP PFNGLGETUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLuint64 *params);
|
||||
typedef void (APIENTRYP PFNGLGETNUNIFORMI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
|
||||
typedef void (APIENTRYP PFNGLGETNUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64ARBPROC) (GLuint program, GLint location, GLint64 x);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64ARBPROC) (GLuint program, GLint location, GLuint64 x);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glUniform1i64ARB (GLint location, GLint64 x);
|
||||
GLAPI void APIENTRY glUniform2i64ARB (GLint location, GLint64 x, GLint64 y);
|
||||
GLAPI void APIENTRY glUniform3i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z);
|
||||
GLAPI void APIENTRY glUniform4i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
|
||||
GLAPI void APIENTRY glUniform1i64vARB (GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glUniform2i64vARB (GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glUniform3i64vARB (GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glUniform4i64vARB (GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glUniform1ui64ARB (GLint location, GLuint64 x);
|
||||
GLAPI void APIENTRY glUniform2ui64ARB (GLint location, GLuint64 x, GLuint64 y);
|
||||
GLAPI void APIENTRY glUniform3ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
|
||||
GLAPI void APIENTRY glUniform4ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
|
||||
GLAPI void APIENTRY glUniform1ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glUniform2ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glUniform3ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glUniform4ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glGetUniformi64vARB (GLuint program, GLint location, GLint64 *params);
|
||||
GLAPI void APIENTRY glGetUniformui64vARB (GLuint program, GLint location, GLuint64 *params);
|
||||
GLAPI void APIENTRY glGetnUniformi64vARB (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
|
||||
GLAPI void APIENTRY glGetnUniformui64vARB (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
|
||||
GLAPI void APIENTRY glProgramUniform1i64ARB (GLuint program, GLint location, GLint64 x);
|
||||
GLAPI void APIENTRY glProgramUniform2i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y);
|
||||
GLAPI void APIENTRY glProgramUniform3i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
|
||||
GLAPI void APIENTRY glProgramUniform4i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
|
||||
GLAPI void APIENTRY glProgramUniform1i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform2i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform3i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform4i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform1ui64ARB (GLuint program, GLint location, GLuint64 x);
|
||||
GLAPI void APIENTRY glProgramUniform2ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y);
|
||||
GLAPI void APIENTRY glProgramUniform3ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
|
||||
GLAPI void APIENTRY glProgramUniform4ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
|
||||
GLAPI void APIENTRY glProgramUniform1ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform2ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform3ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
|
||||
#endif
|
||||
#endif /* GL_ARB_gpu_shader_int64 */
|
||||
|
||||
#ifndef GL_ARB_half_float_pixel
|
||||
#define GL_ARB_half_float_pixel 1
|
||||
typedef unsigned short GLhalfARB;
|
||||
@@ -3727,6 +3827,16 @@ GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *par
|
||||
#define GL_ARB_occlusion_query2 1
|
||||
#endif /* GL_ARB_occlusion_query2 */
|
||||
|
||||
#ifndef GL_ARB_parallel_shader_compile
|
||||
#define GL_ARB_parallel_shader_compile 1
|
||||
#define GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0
|
||||
#define GL_COMPLETION_STATUS_ARB 0x91B1
|
||||
typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSARBPROC) (GLuint count);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glMaxShaderCompilerThreadsARB (GLuint count);
|
||||
#endif
|
||||
#endif /* GL_ARB_parallel_shader_compile */
|
||||
|
||||
#ifndef GL_ARB_pipeline_statistics_query
|
||||
#define GL_ARB_pipeline_statistics_query 1
|
||||
#define GL_VERTICES_SUBMITTED_ARB 0x82EE
|
||||
@@ -3769,6 +3879,10 @@ GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
|
||||
#define GL_COORD_REPLACE_ARB 0x8862
|
||||
#endif /* GL_ARB_point_sprite */
|
||||
|
||||
#ifndef GL_ARB_post_depth_coverage
|
||||
#define GL_ARB_post_depth_coverage 1
|
||||
#endif /* GL_ARB_post_depth_coverage */
|
||||
|
||||
#ifndef GL_ARB_program_interface_query
|
||||
#define GL_ARB_program_interface_query 1
|
||||
#endif /* GL_ARB_program_interface_query */
|
||||
@@ -3842,6 +3956,26 @@ GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum form
|
||||
#define GL_ARB_robustness_isolation 1
|
||||
#endif /* GL_ARB_robustness_isolation */
|
||||
|
||||
#ifndef GL_ARB_sample_locations
|
||||
#define GL_ARB_sample_locations 1
|
||||
#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D
|
||||
#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E
|
||||
#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F
|
||||
#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340
|
||||
#define GL_SAMPLE_LOCATION_ARB 0x8E50
|
||||
#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341
|
||||
#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342
|
||||
#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
|
||||
typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
|
||||
typedef void (APIENTRYP PFNGLEVALUATEDEPTHVALUESARBPROC) (void);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glFramebufferSampleLocationsfvARB (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
|
||||
GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvARB (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
|
||||
GLAPI void APIENTRY glEvaluateDepthValuesARB (void);
|
||||
#endif
|
||||
#endif /* GL_ARB_sample_locations */
|
||||
|
||||
#ifndef GL_ARB_sample_shading
|
||||
#define GL_ARB_sample_shading 1
|
||||
#define GL_SAMPLE_SHADING_ARB 0x8C36
|
||||
@@ -3868,14 +4002,26 @@ GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
|
||||
#define GL_ARB_separate_shader_objects 1
|
||||
#endif /* GL_ARB_separate_shader_objects */
|
||||
|
||||
#ifndef GL_ARB_shader_atomic_counter_ops
|
||||
#define GL_ARB_shader_atomic_counter_ops 1
|
||||
#endif /* GL_ARB_shader_atomic_counter_ops */
|
||||
|
||||
#ifndef GL_ARB_shader_atomic_counters
|
||||
#define GL_ARB_shader_atomic_counters 1
|
||||
#endif /* GL_ARB_shader_atomic_counters */
|
||||
|
||||
#ifndef GL_ARB_shader_ballot
|
||||
#define GL_ARB_shader_ballot 1
|
||||
#endif /* GL_ARB_shader_ballot */
|
||||
|
||||
#ifndef GL_ARB_shader_bit_encoding
|
||||
#define GL_ARB_shader_bit_encoding 1
|
||||
#endif /* GL_ARB_shader_bit_encoding */
|
||||
|
||||
#ifndef GL_ARB_shader_clock
|
||||
#define GL_ARB_shader_clock 1
|
||||
#endif /* GL_ARB_shader_clock */
|
||||
|
||||
#ifndef GL_ARB_shader_draw_parameters
|
||||
#define GL_ARB_shader_draw_parameters 1
|
||||
#endif /* GL_ARB_shader_draw_parameters */
|
||||
@@ -4040,6 +4186,10 @@ GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GL
|
||||
#define GL_ARB_shader_texture_lod 1
|
||||
#endif /* GL_ARB_shader_texture_lod */
|
||||
|
||||
#ifndef GL_ARB_shader_viewport_layer_array
|
||||
#define GL_ARB_shader_viewport_layer_array 1
|
||||
#endif /* GL_ARB_shader_viewport_layer_array */
|
||||
|
||||
#ifndef GL_ARB_shading_language_100
|
||||
#define GL_ARB_shading_language_100 1
|
||||
#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
|
||||
@@ -4119,6 +4269,14 @@ GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xo
|
||||
#endif
|
||||
#endif /* GL_ARB_sparse_texture */
|
||||
|
||||
#ifndef GL_ARB_sparse_texture2
|
||||
#define GL_ARB_sparse_texture2 1
|
||||
#endif /* GL_ARB_sparse_texture2 */
|
||||
|
||||
#ifndef GL_ARB_sparse_texture_clamp
|
||||
#define GL_ARB_sparse_texture_clamp 1
|
||||
#endif /* GL_ARB_sparse_texture_clamp */
|
||||
|
||||
#ifndef GL_ARB_stencil_texturing
|
||||
#define GL_ARB_stencil_texturing 1
|
||||
#endif /* GL_ARB_stencil_texturing */
|
||||
@@ -4271,6 +4429,12 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
|
||||
#define GL_DOT3_RGBA_ARB 0x86AF
|
||||
#endif /* GL_ARB_texture_env_dot3 */
|
||||
|
||||
#ifndef GL_ARB_texture_filter_minmax
|
||||
#define GL_ARB_texture_filter_minmax 1
|
||||
#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
|
||||
#define GL_WEIGHTED_AVERAGE_ARB 0x9367
|
||||
#endif /* GL_ARB_texture_filter_minmax */
|
||||
|
||||
#ifndef GL_ARB_texture_float
|
||||
#define GL_ARB_texture_float 1
|
||||
#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
|
||||
@@ -4815,6 +4979,10 @@ GLAPI void APIENTRY glBlendBarrierKHR (void);
|
||||
#define GL_KHR_texture_compression_astc_ldr 1
|
||||
#endif /* GL_KHR_texture_compression_astc_ldr */
|
||||
|
||||
#ifndef GL_KHR_texture_compression_astc_sliced_3d
|
||||
#define GL_KHR_texture_compression_astc_sliced_3d 1
|
||||
#endif /* GL_KHR_texture_compression_astc_sliced_3d */
|
||||
|
||||
#ifndef GL_OES_byte_coordinates
|
||||
#define GL_OES_byte_coordinates 1
|
||||
typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s);
|
||||
@@ -5210,6 +5378,23 @@ GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRG
|
||||
#define GL_AMD_gcn_shader 1
|
||||
#endif /* GL_AMD_gcn_shader */
|
||||
|
||||
#ifndef GL_AMD_gpu_shader_half_float
|
||||
#define GL_AMD_gpu_shader_half_float 1
|
||||
#define GL_FLOAT16_NV 0x8FF8
|
||||
#define GL_FLOAT16_VEC2_NV 0x8FF9
|
||||
#define GL_FLOAT16_VEC3_NV 0x8FFA
|
||||
#define GL_FLOAT16_VEC4_NV 0x8FFB
|
||||
#define GL_FLOAT16_MAT2_AMD 0x91C5
|
||||
#define GL_FLOAT16_MAT3_AMD 0x91C6
|
||||
#define GL_FLOAT16_MAT4_AMD 0x91C7
|
||||
#define GL_FLOAT16_MAT2x3_AMD 0x91C8
|
||||
#define GL_FLOAT16_MAT2x4_AMD 0x91C9
|
||||
#define GL_FLOAT16_MAT3x2_AMD 0x91CA
|
||||
#define GL_FLOAT16_MAT3x4_AMD 0x91CB
|
||||
#define GL_FLOAT16_MAT4x2_AMD 0x91CC
|
||||
#define GL_FLOAT16_MAT4x3_AMD 0x91CD
|
||||
#endif /* GL_AMD_gpu_shader_half_float */
|
||||
|
||||
#ifndef GL_AMD_gpu_shader_int64
|
||||
#define GL_AMD_gpu_shader_int64 1
|
||||
typedef int64_t GLint64EXT;
|
||||
@@ -5237,10 +5422,6 @@ typedef int64_t GLint64EXT;
|
||||
#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
|
||||
#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
|
||||
#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
|
||||
#define GL_FLOAT16_NV 0x8FF8
|
||||
#define GL_FLOAT16_VEC2_NV 0x8FF9
|
||||
#define GL_FLOAT16_VEC3_NV 0x8FFA
|
||||
#define GL_FLOAT16_VEC4_NV 0x8FFB
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
|
||||
@@ -5428,6 +5609,14 @@ GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLf
|
||||
#define GL_AMD_shader_atomic_counter_ops 1
|
||||
#endif /* GL_AMD_shader_atomic_counter_ops */
|
||||
|
||||
#ifndef GL_AMD_shader_ballot
|
||||
#define GL_AMD_shader_ballot 1
|
||||
#endif /* GL_AMD_shader_ballot */
|
||||
|
||||
#ifndef GL_AMD_shader_explicit_vertex_parameter
|
||||
#define GL_AMD_shader_explicit_vertex_parameter 1
|
||||
#endif /* GL_AMD_shader_explicit_vertex_parameter */
|
||||
|
||||
#ifndef GL_AMD_shader_stencil_export
|
||||
#define GL_AMD_shader_stencil_export 1
|
||||
#endif /* GL_AMD_shader_stencil_export */
|
||||
@@ -8468,6 +8657,20 @@ GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei s
|
||||
#endif
|
||||
#endif /* GL_EXT_vertex_weighting */
|
||||
|
||||
#ifndef GL_EXT_window_rectangles
|
||||
#define GL_EXT_window_rectangles 1
|
||||
#define GL_INCLUSIVE_EXT 0x8F10
|
||||
#define GL_EXCLUSIVE_EXT 0x8F11
|
||||
#define GL_WINDOW_RECTANGLE_EXT 0x8F12
|
||||
#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13
|
||||
#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14
|
||||
#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15
|
||||
typedef void (APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box);
|
||||
#endif
|
||||
#endif /* GL_EXT_window_rectangles */
|
||||
|
||||
#ifndef GL_EXT_x11_sync_object
|
||||
#define GL_EXT_x11_sync_object 1
|
||||
#define GL_SYNC_X11_FENCE_EXT 0x90E1
|
||||
@@ -8645,10 +8848,23 @@ GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRG
|
||||
#define GL_INTERLACE_READ_INGR 0x8568
|
||||
#endif /* GL_INGR_interlace_read */
|
||||
|
||||
#ifndef GL_INTEL_conservative_rasterization
|
||||
#define GL_INTEL_conservative_rasterization 1
|
||||
#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
|
||||
#endif /* GL_INTEL_conservative_rasterization */
|
||||
|
||||
#ifndef GL_INTEL_fragment_shader_ordering
|
||||
#define GL_INTEL_fragment_shader_ordering 1
|
||||
#endif /* GL_INTEL_fragment_shader_ordering */
|
||||
|
||||
#ifndef GL_INTEL_framebuffer_CMAA
|
||||
#define GL_INTEL_framebuffer_CMAA 1
|
||||
typedef void (APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
|
||||
#endif
|
||||
#endif /* GL_INTEL_framebuffer_CMAA */
|
||||
|
||||
#ifndef GL_INTEL_map_texture
|
||||
#define GL_INTEL_map_texture 1
|
||||
#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
|
||||
@@ -8953,6 +9169,17 @@ GLAPI void APIENTRY glBlendBarrierNV (void);
|
||||
#define GL_NV_blend_square 1
|
||||
#endif /* GL_NV_blend_square */
|
||||
|
||||
#ifndef GL_NV_clip_space_w_scaling
|
||||
#define GL_NV_clip_space_w_scaling 1
|
||||
#define GL_VIEWPORT_POSITION_W_SCALE_NV 0x937C
|
||||
#define GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D
|
||||
#define GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTPOSITIONWSCALENVPROC) (GLuint index, GLfloat xcoeff, GLfloat ycoeff);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glViewportPositionWScaleNV (GLuint index, GLfloat xcoeff, GLfloat ycoeff);
|
||||
#endif
|
||||
#endif /* GL_NV_clip_space_w_scaling */
|
||||
|
||||
#ifndef GL_NV_command_list
|
||||
#define GL_NV_command_list 1
|
||||
#define GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000
|
||||
@@ -9044,6 +9271,28 @@ GLAPI void APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
|
||||
#endif
|
||||
#endif /* GL_NV_conservative_raster */
|
||||
|
||||
#ifndef GL_NV_conservative_raster_dilate
|
||||
#define GL_NV_conservative_raster_dilate 1
|
||||
#define GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379
|
||||
#define GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A
|
||||
#define GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B
|
||||
typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERFNVPROC) (GLenum pname, GLfloat value);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat value);
|
||||
#endif
|
||||
#endif /* GL_NV_conservative_raster_dilate */
|
||||
|
||||
#ifndef GL_NV_conservative_raster_pre_snap_triangles
|
||||
#define GL_NV_conservative_raster_pre_snap_triangles 1
|
||||
#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D
|
||||
#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E
|
||||
#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F
|
||||
typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param);
|
||||
#endif
|
||||
#endif /* GL_NV_conservative_raster_pre_snap_triangles */
|
||||
|
||||
#ifndef GL_NV_copy_depth_to_color
|
||||
#define GL_NV_copy_depth_to_color 1
|
||||
#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
|
||||
@@ -10036,6 +10285,11 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname,
|
||||
#endif
|
||||
#endif /* GL_NV_register_combiners2 */
|
||||
|
||||
#ifndef GL_NV_robustness_video_memory_purge
|
||||
#define GL_NV_robustness_video_memory_purge 1
|
||||
#define GL_PURGED_CONTEXT_RESET_NV 0x92BB
|
||||
#endif /* GL_NV_robustness_video_memory_purge */
|
||||
|
||||
#ifndef GL_NV_sample_locations
|
||||
#define GL_NV_sample_locations 1
|
||||
#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
|
||||
@@ -10068,6 +10322,10 @@ GLAPI void APIENTRY glResolveDepthValuesNV (void);
|
||||
#define GL_NV_shader_atomic_float 1
|
||||
#endif /* GL_NV_shader_atomic_float */
|
||||
|
||||
#ifndef GL_NV_shader_atomic_float64
|
||||
#define GL_NV_shader_atomic_float64 1
|
||||
#endif /* GL_NV_shader_atomic_float64 */
|
||||
|
||||
#ifndef GL_NV_shader_atomic_fp16_vector
|
||||
#define GL_NV_shader_atomic_fp16_vector 1
|
||||
#endif /* GL_NV_shader_atomic_fp16_vector */
|
||||
@@ -10131,6 +10389,10 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs
|
||||
#define GL_NV_shader_thread_shuffle 1
|
||||
#endif /* GL_NV_shader_thread_shuffle */
|
||||
|
||||
#ifndef GL_NV_stereo_view_rendering
|
||||
#define GL_NV_stereo_view_rendering 1
|
||||
#endif /* GL_NV_stereo_view_rendering */
|
||||
|
||||
#ifndef GL_NV_tessellation_program5
|
||||
#define GL_NV_tessellation_program5 1
|
||||
#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
|
||||
@@ -10901,6 +11163,26 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot
|
||||
#define GL_NV_viewport_array2 1
|
||||
#endif /* GL_NV_viewport_array2 */
|
||||
|
||||
#ifndef GL_NV_viewport_swizzle
|
||||
#define GL_NV_viewport_swizzle 1
|
||||
#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350
|
||||
#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351
|
||||
#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352
|
||||
#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353
|
||||
#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354
|
||||
#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355
|
||||
#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356
|
||||
#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357
|
||||
#define GL_VIEWPORT_SWIZZLE_X_NV 0x9358
|
||||
#define GL_VIEWPORT_SWIZZLE_Y_NV 0x9359
|
||||
#define GL_VIEWPORT_SWIZZLE_Z_NV 0x935A
|
||||
#define GL_VIEWPORT_SWIZZLE_W_NV 0x935B
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
|
||||
#endif
|
||||
#endif /* GL_NV_viewport_swizzle */
|
||||
|
||||
#ifndef GL_OML_interlace
|
||||
#define GL_OML_interlace 1
|
||||
#define GL_INTERLACE_OML 0x8980
|
||||
@@ -10928,6 +11210,7 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
|
||||
#define GL_MAX_VIEWS_OVR 0x9631
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
|
||||
|
||||
Vendored
-1
Submodule 3rdparty/Optional deleted from f27e79084a
Vendored
+1
-1
Submodule 3rdparty/ffmpeg updated: 7b7ae7b067...2f6023d14a
Vendored
-1
Submodule 3rdparty/hidapi deleted from ca39ce8939
Vendored
+1
-1
Submodule 3rdparty/libpng updated: 1dcba4d6eb...ea77a6fd49
Vendored
+1156
-4571
File diff suppressed because it is too large
Load Diff
Vendored
+777
-3138
File diff suppressed because it is too large
Load Diff
Vendored
+46
-651
@@ -33,20 +33,14 @@ typedef interface ID2D1Device1 ID2D1Device1;
|
||||
|
||||
#endif
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_RENDERING_PRIORITY
|
||||
//
|
||||
// Synopsis:
|
||||
// Specifies the extent to which D2D will throttle work sent to the GPU.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Specifies the extent to which D2D will throttle work sent to the GPU.
|
||||
/// </summary>
|
||||
typedef enum D2D1_RENDERING_PRIORITY
|
||||
{
|
||||
D2D1_RENDERING_PRIORITY_NORMAL = 0,
|
||||
D2D1_RENDERING_PRIORITY_LOW = 1,
|
||||
D2D1_RENDERING_PRIORITY_FORCE_DWORD = 0xffffffff
|
||||
D2D1_RENDERING_PRIORITY_NORMAL = 0,
|
||||
D2D1_RENDERING_PRIORITY_LOW = 1,
|
||||
D2D1_RENDERING_PRIORITY_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_RENDERING_PRIORITY;
|
||||
|
||||
@@ -54,32 +48,25 @@ typedef enum D2D1_RENDERING_PRIORITY
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1GeometryRealization
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Encapsulates a device- and transform-dependent representation of a filled or
|
||||
/// stroked geometry.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("a16907d7-bc02-4801-99e8-8cf7f485f774") ID2D1GeometryRealization : public ID2D1Resource
|
||||
{
|
||||
}; // interface ID2D1GeometryRealization
|
||||
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1DeviceContext1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Enables creation and drawing of geometry realization objects.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1DeviceContext1 : public ID2D1DeviceContext
|
||||
{
|
||||
|
||||
STDMETHOD(CreateFilledGeometryRealization)(
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
_COM_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateStrokedGeometryRealization)(
|
||||
@@ -87,7 +74,7 @@ interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1Devi
|
||||
FLOAT flatteningTolerance,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
_COM_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, DrawGeometryRealization)(
|
||||
@@ -97,82 +84,69 @@ interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1Devi
|
||||
}; // interface ID2D1DeviceContext1
|
||||
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1Device1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Represents a resource domain whose objects and device contexts can be used
|
||||
/// together.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("d21768e1-23a4-4823-a14b-7c3eba85d658") ID2D1Device1 : public ID2D1Device
|
||||
{
|
||||
|
||||
|
||||
//
|
||||
// Retrieves the rendering priority currently set on the device.
|
||||
//
|
||||
/// <summary>
|
||||
/// Retrieves the rendering priority currently set on the device.
|
||||
/// </summary>
|
||||
STDMETHOD_(D2D1_RENDERING_PRIORITY, GetRenderingPriority)(
|
||||
) PURE;
|
||||
|
||||
|
||||
//
|
||||
// Sets the rendering priority of the device.
|
||||
//
|
||||
/// <summary>
|
||||
/// Sets the rendering priority of the device.
|
||||
/// </summary>
|
||||
STDMETHOD_(void, SetRenderingPriority)(
|
||||
D2D1_RENDERING_PRIORITY renderingPriority
|
||||
) PURE;
|
||||
|
||||
|
||||
//
|
||||
// Creates a new device context with no initially assigned target.
|
||||
//
|
||||
/// <summary>
|
||||
/// Creates a new device context with no initially assigned target.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateDeviceContext)(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS options,
|
||||
_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
_COM_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
) PURE;
|
||||
|
||||
using ID2D1Device::CreateDeviceContext;
|
||||
}; // interface ID2D1Device1
|
||||
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1Factory2
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Creates Direct2D resources. This interface also enables the creation of
|
||||
/// ID2D1Device1 objects.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("94f81a73-9212-4376-9c58-b16a3a0d3992") ID2D1Factory2 : public ID2D1Factory1
|
||||
{
|
||||
|
||||
|
||||
//
|
||||
// This creates a new Direct2D device from the given IDXGIDevice.
|
||||
//
|
||||
/// <summary>
|
||||
/// This creates a new Direct2D device from the given IDXGIDevice.
|
||||
/// </summary>
|
||||
STDMETHOD(CreateDevice)(
|
||||
_In_ IDXGIDevice *dxgiDevice,
|
||||
_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
_COM_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
) PURE;
|
||||
|
||||
using ID2D1Factory1::CreateDevice;
|
||||
}; // interface ID2D1Factory2
|
||||
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1CommandSink1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// This interface performs all the same functions as the existing ID2D1CommandSink
|
||||
/// interface. It also enables access to the new primitive blend modes, MIN and ADD,
|
||||
/// through its SetPrimitiveBlend1 method.
|
||||
/// </summary>
|
||||
interface DX_DECLARE_INTERFACE("9eb767fd-4269-4467-b8c2-eb30cb305743") ID2D1CommandSink1 : public ID2D1CommandSink
|
||||
{
|
||||
|
||||
|
||||
//
|
||||
// This method is called if primitiveBlend value was added after Windows 8.
|
||||
// SetPrimitiveBlend method is used for Win8 values (_SOURCE_OVER and _COPY).
|
||||
//
|
||||
/// <summary>
|
||||
/// This method is called if primitiveBlend value was added after Windows 8.
|
||||
/// SetPrimitiveBlend method is used for Win8 values (_SOURCE_OVER and _COPY).
|
||||
/// </summary>
|
||||
STDMETHOD(SetPrimitiveBlend1)(
|
||||
D2D1_PRIMITIVE_BLEND primitiveBlend
|
||||
) PURE;
|
||||
@@ -195,593 +169,14 @@ EXTERN_C CONST IID IID_ID2D1CommandSink1;
|
||||
|
||||
typedef interface ID2D1GeometryRealization ID2D1GeometryRealization;
|
||||
|
||||
typedef struct ID2D1GeometryRealizationVtbl
|
||||
{
|
||||
|
||||
ID2D1ResourceVtbl Base;
|
||||
|
||||
} ID2D1GeometryRealizationVtbl;
|
||||
|
||||
interface ID2D1GeometryRealization
|
||||
{
|
||||
CONST struct ID2D1GeometryRealizationVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1GeometryRealization_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1GeometryRealization_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1GeometryRealization_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1GeometryRealization_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
typedef interface ID2D1DeviceContext1 ID2D1DeviceContext1;
|
||||
|
||||
typedef struct ID2D1DeviceContext1Vtbl
|
||||
{
|
||||
|
||||
ID2D1DeviceContextVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(CreateFilledGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateStrokedGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, DrawGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1GeometryRealization *geometryRealization,
|
||||
_In_ ID2D1Brush *brush
|
||||
) PURE;
|
||||
} ID2D1DeviceContext1Vtbl;
|
||||
|
||||
interface ID2D1DeviceContext1
|
||||
{
|
||||
CONST struct ID2D1DeviceContext1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1DeviceContext1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1DeviceContext1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.Base.Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateSharedBitmap(This, riid, data, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.Base.CreateSharedBitmap((ID2D1RenderTarget *)This, riid, data, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateSolidColorBrush(This, color, brushProperties, solidColorBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateSolidColorBrush((ID2D1RenderTarget *)This, color, brushProperties, solidColorBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateLinearGradientBrush(This, linearGradientBrushProperties, brushProperties, gradientStopCollection, linearGradientBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateLinearGradientBrush((ID2D1RenderTarget *)This, linearGradientBrushProperties, brushProperties, gradientStopCollection, linearGradientBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateRadialGradientBrush(This, radialGradientBrushProperties, brushProperties, gradientStopCollection, radialGradientBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateRadialGradientBrush((ID2D1RenderTarget *)This, radialGradientBrushProperties, brushProperties, gradientStopCollection, radialGradientBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateCompatibleRenderTarget(This, desiredSize, desiredPixelSize, desiredFormat, options, bitmapRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateCompatibleRenderTarget((ID2D1RenderTarget *)This, desiredSize, desiredPixelSize, desiredFormat, options, bitmapRenderTarget))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateLayer(This, size, layer) \
|
||||
((This)->lpVtbl->Base.Base.CreateLayer((ID2D1RenderTarget *)This, size, layer))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateMesh(This, mesh) \
|
||||
((This)->lpVtbl->Base.Base.CreateMesh((ID2D1RenderTarget *)This, mesh))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawLine(This, point0, point1, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawLine((ID2D1RenderTarget *)This, point0, point1, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawRectangle(This, rect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawRectangle((ID2D1RenderTarget *)This, rect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillRectangle(This, rect, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillRectangle((ID2D1RenderTarget *)This, rect, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawRoundedRectangle(This, roundedRect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawRoundedRectangle((ID2D1RenderTarget *)This, roundedRect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillRoundedRectangle(This, roundedRect, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillRoundedRectangle((ID2D1RenderTarget *)This, roundedRect, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawEllipse(This, ellipse, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawEllipse((ID2D1RenderTarget *)This, ellipse, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillEllipse(This, ellipse, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillEllipse((ID2D1RenderTarget *)This, ellipse, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGeometry(This, geometry, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawGeometry((ID2D1RenderTarget *)This, geometry, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillGeometry(This, geometry, brush, opacityBrush) \
|
||||
((This)->lpVtbl->Base.Base.FillGeometry((ID2D1RenderTarget *)This, geometry, brush, opacityBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_FillMesh(This, mesh, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillMesh((ID2D1RenderTarget *)This, mesh, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawText(This, string, stringLength, textFormat, layoutRect, defaultForegroundBrush, options, measuringMode) \
|
||||
((This)->lpVtbl->Base.Base.DrawText((ID2D1RenderTarget *)This, string, stringLength, textFormat, layoutRect, defaultForegroundBrush, options, measuringMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawTextLayout(This, origin, textLayout, defaultForegroundBrush, options) \
|
||||
((This)->lpVtbl->Base.Base.DrawTextLayout((ID2D1RenderTarget *)This, origin, textLayout, defaultForegroundBrush, options))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.Base.SetTransform((ID2D1RenderTarget *)This, transform))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.Base.GetTransform((ID2D1RenderTarget *)This, transform))
|
||||
|
||||
#define ID2D1DeviceContext1_SetAntialiasMode(This, antialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.SetAntialiasMode((ID2D1RenderTarget *)This, antialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetAntialiasMode(This) \
|
||||
((This)->lpVtbl->Base.Base.GetAntialiasMode((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTextAntialiasMode(This, textAntialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.SetTextAntialiasMode((ID2D1RenderTarget *)This, textAntialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTextAntialiasMode(This) \
|
||||
((This)->lpVtbl->Base.Base.GetTextAntialiasMode((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.Base.SetTextRenderingParams((ID2D1RenderTarget *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.Base.GetTextRenderingParams((ID2D1RenderTarget *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.SetTags((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.GetTags((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_PopLayer(This) \
|
||||
((This)->lpVtbl->Base.Base.PopLayer((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Flush(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.Flush((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_SaveDrawingState(This, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.Base.SaveDrawingState((ID2D1RenderTarget *)This, drawingStateBlock))
|
||||
|
||||
#define ID2D1DeviceContext1_RestoreDrawingState(This, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.Base.RestoreDrawingState((ID2D1RenderTarget *)This, drawingStateBlock))
|
||||
|
||||
#define ID2D1DeviceContext1_PushAxisAlignedClip(This, clipRect, antialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.PushAxisAlignedClip((ID2D1RenderTarget *)This, clipRect, antialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_PopAxisAlignedClip(This) \
|
||||
((This)->lpVtbl->Base.Base.PopAxisAlignedClip((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Clear(This, clearColor) \
|
||||
((This)->lpVtbl->Base.Base.Clear((ID2D1RenderTarget *)This, clearColor))
|
||||
|
||||
#define ID2D1DeviceContext1_BeginDraw(This) \
|
||||
((This)->lpVtbl->Base.Base.BeginDraw((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_EndDraw(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.EndDraw((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPixelFormat(This) \
|
||||
((This)->lpVtbl->Base.Base.GetPixelFormat((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.SetDpi((ID2D1RenderTarget *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1DeviceContext1_GetDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.GetDpi((ID2D1RenderTarget *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1DeviceContext1_GetSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPixelSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetPixelSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetMaximumBitmapSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetMaximumBitmapSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_IsSupported(This, renderTargetProperties) \
|
||||
((This)->lpVtbl->Base.Base.IsSupported((ID2D1RenderTarget *)This, renderTargetProperties))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmap(This, size, sourceData, pitch, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmap((ID2D1DeviceContext *)This, size, sourceData, pitch, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapFromWicBitmap(This, wicBitmapSource, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmapFromWicBitmap((ID2D1DeviceContext *)This, wicBitmapSource, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContext(This, space, profile, profileSize, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContext((ID2D1DeviceContext *)This, space, profile, profileSize, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContextFromFilename(This, filename, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContextFromFilename((ID2D1DeviceContext *)This, filename, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContextFromWicColorContext(This, wicColorContext, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContextFromWicColorContext((ID2D1DeviceContext *)This, wicColorContext, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapFromDxgiSurface(This, surface, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmapFromDxgiSurface((ID2D1DeviceContext *)This, surface, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateEffect(This, effectId, effect) \
|
||||
((This)->lpVtbl->Base.CreateEffect((ID2D1DeviceContext *)This, effectId, effect))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateGradientStopCollection(This, straightAlphaGradientStops, straightAlphaGradientStopsCount, preInterpolationSpace, postInterpolationSpace, bufferPrecision, extendMode, colorInterpolationMode, gradientStopCollection1) \
|
||||
((This)->lpVtbl->Base.CreateGradientStopCollection((ID2D1DeviceContext *)This, straightAlphaGradientStops, straightAlphaGradientStopsCount, preInterpolationSpace, postInterpolationSpace, bufferPrecision, extendMode, colorInterpolationMode, gradientStopCollection1))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateImageBrush(This, image, imageBrushProperties, brushProperties, imageBrush) \
|
||||
((This)->lpVtbl->Base.CreateImageBrush((ID2D1DeviceContext *)This, image, imageBrushProperties, brushProperties, imageBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapBrush(This, bitmap, bitmapBrushProperties, brushProperties, bitmapBrush) \
|
||||
((This)->lpVtbl->Base.CreateBitmapBrush((ID2D1DeviceContext *)This, bitmap, bitmapBrushProperties, brushProperties, bitmapBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateCommandList(This, commandList) \
|
||||
((This)->lpVtbl->Base.CreateCommandList((ID2D1DeviceContext *)This, commandList))
|
||||
|
||||
#define ID2D1DeviceContext1_IsDxgiFormatSupported(This, format) \
|
||||
((This)->lpVtbl->Base.IsDxgiFormatSupported((ID2D1DeviceContext *)This, format))
|
||||
|
||||
#define ID2D1DeviceContext1_IsBufferPrecisionSupported(This, bufferPrecision) \
|
||||
((This)->lpVtbl->Base.IsBufferPrecisionSupported((ID2D1DeviceContext *)This, bufferPrecision))
|
||||
|
||||
#define ID2D1DeviceContext1_GetImageLocalBounds(This, image, localBounds) \
|
||||
((This)->lpVtbl->Base.GetImageLocalBounds((ID2D1DeviceContext *)This, image, localBounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetImageWorldBounds(This, image, worldBounds) \
|
||||
((This)->lpVtbl->Base.GetImageWorldBounds((ID2D1DeviceContext *)This, image, worldBounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetGlyphRunWorldBounds(This, baselineOrigin, glyphRun, measuringMode, bounds) \
|
||||
((This)->lpVtbl->Base.GetGlyphRunWorldBounds((ID2D1DeviceContext *)This, baselineOrigin, glyphRun, measuringMode, bounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetDevice(This, device) \
|
||||
((This)->lpVtbl->Base.GetDevice((ID2D1DeviceContext *)This, device))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTarget(This, image) \
|
||||
((This)->lpVtbl->Base.SetTarget((ID2D1DeviceContext *)This, image))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTarget(This, image) \
|
||||
((This)->lpVtbl->Base.GetTarget((ID2D1DeviceContext *)This, image))
|
||||
|
||||
#define ID2D1DeviceContext1_SetRenderingControls(This, renderingControls) \
|
||||
((This)->lpVtbl->Base.SetRenderingControls((ID2D1DeviceContext *)This, renderingControls))
|
||||
|
||||
#define ID2D1DeviceContext1_GetRenderingControls(This, renderingControls) \
|
||||
((This)->lpVtbl->Base.GetRenderingControls((ID2D1DeviceContext *)This, renderingControls))
|
||||
|
||||
#define ID2D1DeviceContext1_SetPrimitiveBlend(This, primitiveBlend) \
|
||||
((This)->lpVtbl->Base.SetPrimitiveBlend((ID2D1DeviceContext *)This, primitiveBlend))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPrimitiveBlend(This) \
|
||||
((This)->lpVtbl->Base.GetPrimitiveBlend((ID2D1DeviceContext *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetUnitMode(This, unitMode) \
|
||||
((This)->lpVtbl->Base.SetUnitMode((ID2D1DeviceContext *)This, unitMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetUnitMode(This) \
|
||||
((This)->lpVtbl->Base.GetUnitMode((ID2D1DeviceContext *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGlyphRun(This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode) \
|
||||
((This)->lpVtbl->Base.DrawGlyphRun((ID2D1DeviceContext *)This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawImage(This, image, targetOffset, imageRectangle, interpolationMode, compositeMode) \
|
||||
((This)->lpVtbl->Base.DrawImage((ID2D1DeviceContext *)This, image, targetOffset, imageRectangle, interpolationMode, compositeMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGdiMetafile(This, gdiMetafile, targetOffset) \
|
||||
((This)->lpVtbl->Base.DrawGdiMetafile((ID2D1DeviceContext *)This, gdiMetafile, targetOffset))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawBitmap(This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform) \
|
||||
((This)->lpVtbl->Base.DrawBitmap((ID2D1DeviceContext *)This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform))
|
||||
|
||||
#define ID2D1DeviceContext1_PushLayer(This, layerParameters, layer) \
|
||||
((This)->lpVtbl->Base.PushLayer((ID2D1DeviceContext *)This, layerParameters, layer))
|
||||
|
||||
#define ID2D1DeviceContext1_InvalidateEffectInputRectangle(This, effect, input, inputRectangle) \
|
||||
((This)->lpVtbl->Base.InvalidateEffectInputRectangle((ID2D1DeviceContext *)This, effect, input, inputRectangle))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectInvalidRectangleCount(This, effect, rectangleCount) \
|
||||
((This)->lpVtbl->Base.GetEffectInvalidRectangleCount((ID2D1DeviceContext *)This, effect, rectangleCount))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectInvalidRectangles(This, effect, rectangles, rectanglesCount) \
|
||||
((This)->lpVtbl->Base.GetEffectInvalidRectangles((ID2D1DeviceContext *)This, effect, rectangles, rectanglesCount))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectRequiredInputRectangles(This, renderEffect, renderImageRectangle, inputDescriptions, requiredInputRects, inputCount) \
|
||||
((This)->lpVtbl->Base.GetEffectRequiredInputRectangles((ID2D1DeviceContext *)This, renderEffect, renderImageRectangle, inputDescriptions, requiredInputRects, inputCount))
|
||||
|
||||
#define ID2D1DeviceContext1_FillOpacityMask(This, opacityMask, brush, destinationRectangle, sourceRectangle) \
|
||||
((This)->lpVtbl->Base.FillOpacityMask((ID2D1DeviceContext *)This, opacityMask, brush, destinationRectangle, sourceRectangle))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateFilledGeometryRealization(This, geometry, flatteningTolerance, geometryRealization) \
|
||||
((This)->lpVtbl->CreateFilledGeometryRealization(This, geometry, flatteningTolerance, geometryRealization))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateStrokedGeometryRealization(This, geometry, flatteningTolerance, strokeWidth, strokeStyle, geometryRealization) \
|
||||
((This)->lpVtbl->CreateStrokedGeometryRealization(This, geometry, flatteningTolerance, strokeWidth, strokeStyle, geometryRealization))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGeometryRealization(This, geometryRealization, brush) \
|
||||
((This)->lpVtbl->DrawGeometryRealization(This, geometryRealization, brush))
|
||||
|
||||
typedef interface ID2D1Device1 ID2D1Device1;
|
||||
|
||||
typedef struct ID2D1Device1Vtbl
|
||||
{
|
||||
|
||||
ID2D1DeviceVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD_(D2D1_RENDERING_PRIORITY, GetRenderingPriority)(
|
||||
ID2D1Device1 *This
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, SetRenderingPriority)(
|
||||
ID2D1Device1 *This,
|
||||
D2D1_RENDERING_PRIORITY renderingPriority
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateDeviceContext)(
|
||||
ID2D1Device1 *This,
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS options,
|
||||
_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
) PURE;
|
||||
} ID2D1Device1Vtbl;
|
||||
|
||||
interface ID2D1Device1
|
||||
{
|
||||
CONST struct ID2D1Device1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1Device1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1Device1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1Device1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1Device1_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
#define ID2D1Device1_CreatePrintControl(This, wicFactory, documentTarget, printControlProperties, printControl) \
|
||||
((This)->lpVtbl->Base.CreatePrintControl((ID2D1Device *)This, wicFactory, documentTarget, printControlProperties, printControl))
|
||||
|
||||
#define ID2D1Device1_SetMaximumTextureMemory(This, maximumInBytes) \
|
||||
((This)->lpVtbl->Base.SetMaximumTextureMemory((ID2D1Device *)This, maximumInBytes))
|
||||
|
||||
#define ID2D1Device1_GetMaximumTextureMemory(This) \
|
||||
((This)->lpVtbl->Base.GetMaximumTextureMemory((ID2D1Device *)This))
|
||||
|
||||
#define ID2D1Device1_ClearResources(This, millisecondsSinceUse) \
|
||||
((This)->lpVtbl->Base.ClearResources((ID2D1Device *)This, millisecondsSinceUse))
|
||||
|
||||
#define ID2D1Device1_GetRenderingPriority(This) \
|
||||
((This)->lpVtbl->GetRenderingPriority(This))
|
||||
|
||||
#define ID2D1Device1_SetRenderingPriority(This, renderingPriority) \
|
||||
((This)->lpVtbl->SetRenderingPriority(This, renderingPriority))
|
||||
|
||||
#define ID2D1Device1_CreateDeviceContext(This, options, deviceContext1) \
|
||||
((This)->lpVtbl->CreateDeviceContext(This, options, deviceContext1))
|
||||
|
||||
typedef interface ID2D1Factory2 ID2D1Factory2;
|
||||
|
||||
typedef struct ID2D1Factory2Vtbl
|
||||
{
|
||||
|
||||
ID2D1Factory1Vtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(CreateDevice)(
|
||||
ID2D1Factory2 *This,
|
||||
_In_ IDXGIDevice *dxgiDevice,
|
||||
_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
) PURE;
|
||||
} ID2D1Factory2Vtbl;
|
||||
|
||||
interface ID2D1Factory2
|
||||
{
|
||||
CONST struct ID2D1Factory2Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1Factory2_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1Factory2_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1Factory2_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1Factory2_ReloadSystemMetrics(This) \
|
||||
((This)->lpVtbl->Base.Base.ReloadSystemMetrics((ID2D1Factory *)This))
|
||||
|
||||
#define ID2D1Factory2_GetDesktopDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.GetDesktopDpi((ID2D1Factory *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1Factory2_CreateRectangleGeometry(This, rectangle, rectangleGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateRectangleGeometry((ID2D1Factory *)This, rectangle, rectangleGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateRoundedRectangleGeometry(This, roundedRectangle, roundedRectangleGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateRoundedRectangleGeometry((ID2D1Factory *)This, roundedRectangle, roundedRectangleGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateEllipseGeometry(This, ellipse, ellipseGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateEllipseGeometry((ID2D1Factory *)This, ellipse, ellipseGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateGeometryGroup(This, fillMode, geometries, geometriesCount, geometryGroup) \
|
||||
((This)->lpVtbl->Base.Base.CreateGeometryGroup((ID2D1Factory *)This, fillMode, geometries, geometriesCount, geometryGroup))
|
||||
|
||||
#define ID2D1Factory2_CreateTransformedGeometry(This, sourceGeometry, transform, transformedGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateTransformedGeometry((ID2D1Factory *)This, sourceGeometry, transform, transformedGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateWicBitmapRenderTarget(This, target, renderTargetProperties, renderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateWicBitmapRenderTarget((ID2D1Factory *)This, target, renderTargetProperties, renderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateHwndRenderTarget(This, renderTargetProperties, hwndRenderTargetProperties, hwndRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateHwndRenderTarget((ID2D1Factory *)This, renderTargetProperties, hwndRenderTargetProperties, hwndRenderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateDxgiSurfaceRenderTarget(This, dxgiSurface, renderTargetProperties, renderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateDxgiSurfaceRenderTarget((ID2D1Factory *)This, dxgiSurface, renderTargetProperties, renderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateDCRenderTarget(This, renderTargetProperties, dcRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateDCRenderTarget((ID2D1Factory *)This, renderTargetProperties, dcRenderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateStrokeStyle(This, strokeStyleProperties, dashes, dashesCount, strokeStyle) \
|
||||
((This)->lpVtbl->Base.CreateStrokeStyle((ID2D1Factory1 *)This, strokeStyleProperties, dashes, dashesCount, strokeStyle))
|
||||
|
||||
#define ID2D1Factory2_CreatePathGeometry(This, pathGeometry) \
|
||||
((This)->lpVtbl->Base.CreatePathGeometry((ID2D1Factory1 *)This, pathGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateDrawingStateBlock(This, drawingStateDescription, textRenderingParams, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.CreateDrawingStateBlock((ID2D1Factory1 *)This, drawingStateDescription, textRenderingParams, drawingStateBlock))
|
||||
|
||||
#define ID2D1Factory2_CreateGdiMetafile(This, metafileStream, metafile) \
|
||||
((This)->lpVtbl->Base.CreateGdiMetafile((ID2D1Factory1 *)This, metafileStream, metafile))
|
||||
|
||||
#define ID2D1Factory2_RegisterEffectFromStream(This, classId, propertyXml, bindings, bindingsCount, effectFactory) \
|
||||
((This)->lpVtbl->Base.RegisterEffectFromStream((ID2D1Factory1 *)This, classId, propertyXml, bindings, bindingsCount, effectFactory))
|
||||
|
||||
#define ID2D1Factory2_RegisterEffectFromString(This, classId, propertyXml, bindings, bindingsCount, effectFactory) \
|
||||
((This)->lpVtbl->Base.RegisterEffectFromString((ID2D1Factory1 *)This, classId, propertyXml, bindings, bindingsCount, effectFactory))
|
||||
|
||||
#define ID2D1Factory2_UnregisterEffect(This, classId) \
|
||||
((This)->lpVtbl->Base.UnregisterEffect((ID2D1Factory1 *)This, classId))
|
||||
|
||||
#define ID2D1Factory2_GetRegisteredEffects(This, effects, effectsCount, effectsReturned, effectsRegistered) \
|
||||
((This)->lpVtbl->Base.GetRegisteredEffects((ID2D1Factory1 *)This, effects, effectsCount, effectsReturned, effectsRegistered))
|
||||
|
||||
#define ID2D1Factory2_GetEffectProperties(This, effectId, properties) \
|
||||
((This)->lpVtbl->Base.GetEffectProperties((ID2D1Factory1 *)This, effectId, properties))
|
||||
|
||||
#define ID2D1Factory2_CreateDevice(This, dxgiDevice, d2dDevice1) \
|
||||
((This)->lpVtbl->CreateDevice(This, dxgiDevice, d2dDevice1))
|
||||
|
||||
typedef interface ID2D1CommandSink1 ID2D1CommandSink1;
|
||||
|
||||
typedef struct ID2D1CommandSink1Vtbl
|
||||
{
|
||||
|
||||
ID2D1CommandSinkVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(SetPrimitiveBlend1)(
|
||||
ID2D1CommandSink1 *This,
|
||||
D2D1_PRIMITIVE_BLEND primitiveBlend
|
||||
) PURE;
|
||||
} ID2D1CommandSink1Vtbl;
|
||||
|
||||
interface ID2D1CommandSink1
|
||||
{
|
||||
CONST struct ID2D1CommandSink1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1CommandSink1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1CommandSink1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1CommandSink1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1CommandSink1_BeginDraw(This) \
|
||||
((This)->lpVtbl->Base.BeginDraw((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_EndDraw(This) \
|
||||
((This)->lpVtbl->Base.EndDraw((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_SetAntialiasMode(This, antialiasMode) \
|
||||
((This)->lpVtbl->Base.SetAntialiasMode((ID2D1CommandSink *)This, antialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_SetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.SetTags((ID2D1CommandSink *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1CommandSink1_SetTextAntialiasMode(This, textAntialiasMode) \
|
||||
((This)->lpVtbl->Base.SetTextAntialiasMode((ID2D1CommandSink *)This, textAntialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_SetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.SetTextRenderingParams((ID2D1CommandSink *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1CommandSink1_SetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.SetTransform((ID2D1CommandSink *)This, transform))
|
||||
|
||||
#define ID2D1CommandSink1_SetPrimitiveBlend(This, primitiveBlend) \
|
||||
((This)->lpVtbl->Base.SetPrimitiveBlend((ID2D1CommandSink *)This, primitiveBlend))
|
||||
|
||||
#define ID2D1CommandSink1_SetUnitMode(This, unitMode) \
|
||||
((This)->lpVtbl->Base.SetUnitMode((ID2D1CommandSink *)This, unitMode))
|
||||
|
||||
#define ID2D1CommandSink1_Clear(This, color) \
|
||||
((This)->lpVtbl->Base.Clear((ID2D1CommandSink *)This, color))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGlyphRun(This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode) \
|
||||
((This)->lpVtbl->Base.DrawGlyphRun((ID2D1CommandSink *)This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode))
|
||||
|
||||
#define ID2D1CommandSink1_DrawLine(This, point0, point1, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawLine((ID2D1CommandSink *)This, point0, point1, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGeometry(This, geometry, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawGeometry((ID2D1CommandSink *)This, geometry, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawRectangle(This, rect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawRectangle((ID2D1CommandSink *)This, rect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawBitmap(This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform) \
|
||||
((This)->lpVtbl->Base.DrawBitmap((ID2D1CommandSink *)This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform))
|
||||
|
||||
#define ID2D1CommandSink1_DrawImage(This, image, targetOffset, imageRectangle, interpolationMode, compositeMode) \
|
||||
((This)->lpVtbl->Base.DrawImage((ID2D1CommandSink *)This, image, targetOffset, imageRectangle, interpolationMode, compositeMode))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGdiMetafile(This, gdiMetafile, targetOffset) \
|
||||
((This)->lpVtbl->Base.DrawGdiMetafile((ID2D1CommandSink *)This, gdiMetafile, targetOffset))
|
||||
|
||||
#define ID2D1CommandSink1_FillMesh(This, mesh, brush) \
|
||||
((This)->lpVtbl->Base.FillMesh((ID2D1CommandSink *)This, mesh, brush))
|
||||
|
||||
#define ID2D1CommandSink1_FillOpacityMask(This, opacityMask, brush, destinationRectangle, sourceRectangle) \
|
||||
((This)->lpVtbl->Base.FillOpacityMask((ID2D1CommandSink *)This, opacityMask, brush, destinationRectangle, sourceRectangle))
|
||||
|
||||
#define ID2D1CommandSink1_FillGeometry(This, geometry, brush, opacityBrush) \
|
||||
((This)->lpVtbl->Base.FillGeometry((ID2D1CommandSink *)This, geometry, brush, opacityBrush))
|
||||
|
||||
#define ID2D1CommandSink1_FillRectangle(This, rect, brush) \
|
||||
((This)->lpVtbl->Base.FillRectangle((ID2D1CommandSink *)This, rect, brush))
|
||||
|
||||
#define ID2D1CommandSink1_PushAxisAlignedClip(This, clipRect, antialiasMode) \
|
||||
((This)->lpVtbl->Base.PushAxisAlignedClip((ID2D1CommandSink *)This, clipRect, antialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_PushLayer(This, layerParameters1, layer) \
|
||||
((This)->lpVtbl->Base.PushLayer((ID2D1CommandSink *)This, layerParameters1, layer))
|
||||
|
||||
#define ID2D1CommandSink1_PopAxisAlignedClip(This) \
|
||||
((This)->lpVtbl->Base.PopAxisAlignedClip((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_PopLayer(This) \
|
||||
((This)->lpVtbl->Base.PopLayer((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_SetPrimitiveBlend1(This, primitiveBlend) \
|
||||
((This)->lpVtbl->SetPrimitiveBlend1(This, primitiveBlend))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Vendored
+853
-1582
File diff suppressed because it is too large
Load Diff
+10
@@ -215,6 +215,16 @@ namespace D2D1
|
||||
|
||||
return inkStyleProperties;
|
||||
}
|
||||
|
||||
COM_DECLSPEC_NOTHROW
|
||||
D2D1FORCEINLINE
|
||||
D2D1_RECT_U
|
||||
InfiniteRectU()
|
||||
{
|
||||
D2D1_RECT_U rect = { 0u, 0u, UINT_MAX, UINT_MAX };
|
||||
|
||||
return rect;
|
||||
}
|
||||
} // namespace D2D1
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
|
||||
+1464
-1865
File diff suppressed because it is too large
Load Diff
+35
-55
@@ -25,73 +25,53 @@
|
||||
// Built in effect CLSIDs
|
||||
DEFINE_GUID(CLSID_D2D1YCbCr, 0x99503cc1, 0x66c7, 0x45c9, 0xa8, 0x75, 0x8a, 0xd8, 0xa7, 0x91, 0x44, 0x01);
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_YCBCR_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the YCbCr effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the YCbCr effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_YCBCR_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "ChromaSubsampling"
|
||||
// Property Type: D2D1_YCBCR_CHROMA_SUBSAMPLING
|
||||
//
|
||||
D2D1_YCBCR_PROP_CHROMA_SUBSAMPLING = 0,
|
||||
|
||||
//
|
||||
// Property Name: "TransformMatrix"
|
||||
// Property Type: D2D1_MATRIX_3X2_F
|
||||
//
|
||||
D2D1_YCBCR_PROP_TRANSFORM_MATRIX = 1,
|
||||
|
||||
//
|
||||
// Property Name: "InterpolationMode"
|
||||
// Property Type: D2D1_YCBCR_INTERPOLATION_MODE
|
||||
//
|
||||
D2D1_YCBCR_PROP_INTERPOLATION_MODE = 2,
|
||||
D2D1_YCBCR_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ChromaSubsampling"
|
||||
/// Property Type: D2D1_YCBCR_CHROMA_SUBSAMPLING
|
||||
/// </summary>
|
||||
D2D1_YCBCR_PROP_CHROMA_SUBSAMPLING = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "TransformMatrix"
|
||||
/// Property Type: D2D1_MATRIX_3X2_F
|
||||
/// </summary>
|
||||
D2D1_YCBCR_PROP_TRANSFORM_MATRIX = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "InterpolationMode"
|
||||
/// Property Type: D2D1_YCBCR_INTERPOLATION_MODE
|
||||
/// </summary>
|
||||
D2D1_YCBCR_PROP_INTERPOLATION_MODE = 2,
|
||||
D2D1_YCBCR_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_YCBCR_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_YCBCR_CHROMA_SUBSAMPLING
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_YCBCR_CHROMA_SUBSAMPLING
|
||||
{
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_AUTO = 0,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_420 = 1,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_422 = 2,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_444 = 3,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_440 = 4,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_FORCE_DWORD = 0xffffffff
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_AUTO = 0,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_420 = 1,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_422 = 2,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_444 = 3,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_440 = 4,
|
||||
D2D1_YCBCR_CHROMA_SUBSAMPLING_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_YCBCR_CHROMA_SUBSAMPLING;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_YCBCR_INTERPOLATION_MODE
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_YCBCR_INTERPOLATION_MODE
|
||||
{
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_NEAREST_NEIGHBOR = 0,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_LINEAR = 1,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_CUBIC = 2,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_MULTI_SAMPLE_LINEAR = 3,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_ANISOTROPIC = 4,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC = 5,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_FORCE_DWORD = 0xffffffff
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_NEAREST_NEIGHBOR = 0,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_LINEAR = 1,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_CUBIC = 2,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_MULTI_SAMPLE_LINEAR = 3,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_ANISOTROPIC = 4,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC = 5,
|
||||
D2D1_YCBCR_INTERPOLATION_MODE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_YCBCR_INTERPOLATION_MODE;
|
||||
|
||||
|
||||
+372
-431
@@ -41,553 +41,494 @@ DEFINE_GUID(CLSID_D2D1EdgeDetection, 0xEFF583CA, 0xCB07, 0x4AA9, 0xAC
|
||||
DEFINE_GUID(CLSID_D2D1HighlightsShadows, 0xCADC8384, 0x323F, 0x4C7E, 0xA3, 0x61, 0x2E, 0x2B, 0x24, 0xDF, 0x6E, 0xE4);
|
||||
DEFINE_GUID(CLSID_D2D1LookupTable3D, 0x349E0EDA, 0x0088, 0x4A79, 0x9C, 0xA3, 0xC7, 0xE3, 0x00, 0x20, 0x20, 0x20);
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_CONTRAST_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Contrast effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
DEFINE_GUID(CLSID_D2D1Opacity, 0x811d79a4, 0xde28, 0x4454, 0x80, 0x94, 0xc6, 0x46, 0x85, 0xf8, 0xbd, 0x4c);
|
||||
DEFINE_GUID(CLSID_D2D1AlphaMask, 0xc80ecff0, 0x3fd5, 0x4f05, 0x83, 0x28, 0xc5, 0xd1, 0x72, 0x4b, 0x4f, 0x0a);
|
||||
DEFINE_GUID(CLSID_D2D1CrossFade, 0x12f575e8, 0x4db1, 0x485f, 0x9a, 0x84, 0x03, 0xa0, 0x7d, 0xd3, 0x82, 0x9f);
|
||||
DEFINE_GUID(CLSID_D2D1Tint, 0x36312b17, 0xf7dd, 0x4014, 0x91, 0x5d, 0xff, 0xca, 0x76, 0x8c, 0xf2, 0x11);
|
||||
|
||||
#endif // #if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Contrast effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_CONTRAST_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Contrast"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_CONTRAST_PROP_CONTRAST = 0,
|
||||
|
||||
//
|
||||
// Property Name: "ClampInput"
|
||||
// Property Type: BOOL
|
||||
//
|
||||
D2D1_CONTRAST_PROP_CLAMP_INPUT = 1,
|
||||
D2D1_CONTRAST_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Contrast"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_CONTRAST_PROP_CONTRAST = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ClampInput"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_CONTRAST_PROP_CLAMP_INPUT = 1,
|
||||
D2D1_CONTRAST_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_CONTRAST_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_RGBTOHUE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the RgbToHue effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the RgbToHue effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_RGBTOHUE_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "OutputColorSpace"
|
||||
// Property Type: D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE
|
||||
//
|
||||
D2D1_RGBTOHUE_PROP_OUTPUT_COLOR_SPACE = 0,
|
||||
D2D1_RGBTOHUE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "OutputColorSpace"
|
||||
/// Property Type: D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE
|
||||
/// </summary>
|
||||
D2D1_RGBTOHUE_PROP_OUTPUT_COLOR_SPACE = 0,
|
||||
D2D1_RGBTOHUE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_RGBTOHUE_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE
|
||||
{
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_HUE_SATURATION_VALUE = 0,
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_HUE_SATURATION_LIGHTNESS = 1,
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_FORCE_DWORD = 0xffffffff
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_HUE_SATURATION_VALUE = 0,
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_HUE_SATURATION_LIGHTNESS = 1,
|
||||
D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HUETORGB_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the HueToRgb effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the HueToRgb effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_HUETORGB_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "InputColorSpace"
|
||||
// Property Type: D2D1_HUETORGB_INPUT_COLOR_SPACE
|
||||
//
|
||||
D2D1_HUETORGB_PROP_INPUT_COLOR_SPACE = 0,
|
||||
D2D1_HUETORGB_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "InputColorSpace"
|
||||
/// Property Type: D2D1_HUETORGB_INPUT_COLOR_SPACE
|
||||
/// </summary>
|
||||
D2D1_HUETORGB_PROP_INPUT_COLOR_SPACE = 0,
|
||||
D2D1_HUETORGB_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_HUETORGB_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HUETORGB_INPUT_COLOR_SPACE
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_HUETORGB_INPUT_COLOR_SPACE
|
||||
{
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_HUE_SATURATION_VALUE = 0,
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_HUE_SATURATION_LIGHTNESS = 1,
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_FORCE_DWORD = 0xffffffff
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_HUE_SATURATION_VALUE = 0,
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_HUE_SATURATION_LIGHTNESS = 1,
|
||||
D2D1_HUETORGB_INPUT_COLOR_SPACE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_HUETORGB_INPUT_COLOR_SPACE;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_CHROMAKEY_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Chroma Key effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Chroma Key effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_CHROMAKEY_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Color"
|
||||
// Property Type: D2D1_VECTOR_3F
|
||||
//
|
||||
D2D1_CHROMAKEY_PROP_COLOR = 0,
|
||||
|
||||
//
|
||||
// Property Name: "Tolerance"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_CHROMAKEY_PROP_TOLERANCE = 1,
|
||||
|
||||
//
|
||||
// Property Name: "InvertAlpha"
|
||||
// Property Type: BOOL
|
||||
//
|
||||
D2D1_CHROMAKEY_PROP_INVERT_ALPHA = 2,
|
||||
|
||||
//
|
||||
// Property Name: "Feather"
|
||||
// Property Type: BOOL
|
||||
//
|
||||
D2D1_CHROMAKEY_PROP_FEATHER = 3,
|
||||
D2D1_CHROMAKEY_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Color"
|
||||
/// Property Type: D2D1_VECTOR_3F
|
||||
/// </summary>
|
||||
D2D1_CHROMAKEY_PROP_COLOR = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Tolerance"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_CHROMAKEY_PROP_TOLERANCE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "InvertAlpha"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_CHROMAKEY_PROP_INVERT_ALPHA = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Feather"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_CHROMAKEY_PROP_FEATHER = 3,
|
||||
D2D1_CHROMAKEY_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_CHROMAKEY_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EMBOSS_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Emboss effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Emboss effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_EMBOSS_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Height"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EMBOSS_PROP_HEIGHT = 0,
|
||||
|
||||
//
|
||||
// Property Name: "Direction"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EMBOSS_PROP_DIRECTION = 1,
|
||||
D2D1_EMBOSS_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Height"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EMBOSS_PROP_HEIGHT = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Direction"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EMBOSS_PROP_DIRECTION = 1,
|
||||
D2D1_EMBOSS_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_EMBOSS_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EXPOSURE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Exposure effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Exposure effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_EXPOSURE_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "ExposureValue"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EXPOSURE_PROP_EXPOSURE_VALUE = 0,
|
||||
D2D1_EXPOSURE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ExposureValue"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EXPOSURE_PROP_EXPOSURE_VALUE = 0,
|
||||
D2D1_EXPOSURE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_EXPOSURE_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_POSTERIZE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Posterize effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Posterize effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_POSTERIZE_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "RedValueCount"
|
||||
// Property Type: UINT32
|
||||
//
|
||||
D2D1_POSTERIZE_PROP_RED_VALUE_COUNT = 0,
|
||||
|
||||
//
|
||||
// Property Name: "GreenValueCount"
|
||||
// Property Type: UINT32
|
||||
//
|
||||
D2D1_POSTERIZE_PROP_GREEN_VALUE_COUNT = 1,
|
||||
|
||||
//
|
||||
// Property Name: "BlueValueCount"
|
||||
// Property Type: UINT32
|
||||
//
|
||||
D2D1_POSTERIZE_PROP_BLUE_VALUE_COUNT = 2,
|
||||
D2D1_POSTERIZE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "RedValueCount"
|
||||
/// Property Type: UINT32
|
||||
/// </summary>
|
||||
D2D1_POSTERIZE_PROP_RED_VALUE_COUNT = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "GreenValueCount"
|
||||
/// Property Type: UINT32
|
||||
/// </summary>
|
||||
D2D1_POSTERIZE_PROP_GREEN_VALUE_COUNT = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "BlueValueCount"
|
||||
/// Property Type: UINT32
|
||||
/// </summary>
|
||||
D2D1_POSTERIZE_PROP_BLUE_VALUE_COUNT = 2,
|
||||
D2D1_POSTERIZE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_POSTERIZE_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_SEPIA_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Sepia effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Sepia effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_SEPIA_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Intensity"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_SEPIA_PROP_INTENSITY = 0,
|
||||
|
||||
//
|
||||
// Property Name: "AlphaMode"
|
||||
// Property Type: D2D1_ALPHA_MODE
|
||||
//
|
||||
D2D1_SEPIA_PROP_ALPHA_MODE = 1,
|
||||
D2D1_SEPIA_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Intensity"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_SEPIA_PROP_INTENSITY = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "AlphaMode"
|
||||
/// Property Type: D2D1_ALPHA_MODE
|
||||
/// </summary>
|
||||
D2D1_SEPIA_PROP_ALPHA_MODE = 1,
|
||||
D2D1_SEPIA_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_SEPIA_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_SHARPEN_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Sharpen effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Sharpen effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_SHARPEN_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Sharpness"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_SHARPEN_PROP_SHARPNESS = 0,
|
||||
|
||||
//
|
||||
// Property Name: "Threshold"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_SHARPEN_PROP_THRESHOLD = 1,
|
||||
D2D1_SHARPEN_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Sharpness"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_SHARPEN_PROP_SHARPNESS = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Threshold"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_SHARPEN_PROP_THRESHOLD = 1,
|
||||
D2D1_SHARPEN_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_SHARPEN_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_STRAIGHTEN_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Straighten effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Straighten effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_STRAIGHTEN_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Angle"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_STRAIGHTEN_PROP_ANGLE = 0,
|
||||
|
||||
//
|
||||
// Property Name: "MaintainSize"
|
||||
// Property Type: BOOL
|
||||
//
|
||||
D2D1_STRAIGHTEN_PROP_MAINTAIN_SIZE = 1,
|
||||
|
||||
//
|
||||
// Property Name: "ScaleMode"
|
||||
// Property Type: D2D1_STRAIGHTEN_SCALE_MODE
|
||||
//
|
||||
D2D1_STRAIGHTEN_PROP_SCALE_MODE = 2,
|
||||
D2D1_STRAIGHTEN_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Angle"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_STRAIGHTEN_PROP_ANGLE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "MaintainSize"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_STRAIGHTEN_PROP_MAINTAIN_SIZE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ScaleMode"
|
||||
/// Property Type: D2D1_STRAIGHTEN_SCALE_MODE
|
||||
/// </summary>
|
||||
D2D1_STRAIGHTEN_PROP_SCALE_MODE = 2,
|
||||
D2D1_STRAIGHTEN_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_STRAIGHTEN_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_STRAIGHTEN_SCALE_MODE
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_STRAIGHTEN_SCALE_MODE
|
||||
{
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_NEAREST_NEIGHBOR = 0,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_LINEAR = 1,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_CUBIC = 2,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_MULTI_SAMPLE_LINEAR = 3,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_ANISOTROPIC = 4,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_FORCE_DWORD = 0xffffffff
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_NEAREST_NEIGHBOR = 0,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_LINEAR = 1,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_CUBIC = 2,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_MULTI_SAMPLE_LINEAR = 3,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_ANISOTROPIC = 4,
|
||||
D2D1_STRAIGHTEN_SCALE_MODE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_STRAIGHTEN_SCALE_MODE;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_TEMPERATUREANDTINT_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Temperature And Tint effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Temperature And Tint effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_TEMPERATUREANDTINT_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Temperature"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_TEMPERATUREANDTINT_PROP_TEMPERATURE = 0,
|
||||
|
||||
//
|
||||
// Property Name: "Tint"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_TEMPERATUREANDTINT_PROP_TINT = 1,
|
||||
D2D1_TEMPERATUREANDTINT_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Temperature"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_TEMPERATUREANDTINT_PROP_TEMPERATURE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Tint"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_TEMPERATUREANDTINT_PROP_TINT = 1,
|
||||
D2D1_TEMPERATUREANDTINT_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_TEMPERATUREANDTINT_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_VIGNETTE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Vignette effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Vignette effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_VIGNETTE_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Color"
|
||||
// Property Type: D2D1_VECTOR_4F
|
||||
//
|
||||
D2D1_VIGNETTE_PROP_COLOR = 0,
|
||||
|
||||
//
|
||||
// Property Name: "TransitionSize"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_VIGNETTE_PROP_TRANSITION_SIZE = 1,
|
||||
|
||||
//
|
||||
// Property Name: "Strength"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_VIGNETTE_PROP_STRENGTH = 2,
|
||||
D2D1_VIGNETTE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Color"
|
||||
/// Property Type: D2D1_VECTOR_4F
|
||||
/// </summary>
|
||||
D2D1_VIGNETTE_PROP_COLOR = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "TransitionSize"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_VIGNETTE_PROP_TRANSITION_SIZE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Strength"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_VIGNETTE_PROP_STRENGTH = 2,
|
||||
D2D1_VIGNETTE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_VIGNETTE_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EDGEDETECTION_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Edge Detection effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Edge Detection effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_EDGEDETECTION_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Strength"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EDGEDETECTION_PROP_STRENGTH = 0,
|
||||
|
||||
//
|
||||
// Property Name: "BlurRadius"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EDGEDETECTION_PROP_BLUR_RADIUS = 1,
|
||||
|
||||
//
|
||||
// Property Name: "Mode"
|
||||
// Property Type: D2D1_EDGEDETECTION_MODE
|
||||
//
|
||||
D2D1_EDGEDETECTION_PROP_MODE = 2,
|
||||
|
||||
//
|
||||
// Property Name: "OverlayEdges"
|
||||
// Property Type: BOOL
|
||||
//
|
||||
D2D1_EDGEDETECTION_PROP_OVERLAY_EDGES = 3,
|
||||
|
||||
//
|
||||
// Property Name: "AlphaMode"
|
||||
// Property Type: D2D1_ALPHA_MODE
|
||||
//
|
||||
D2D1_EDGEDETECTION_PROP_ALPHA_MODE = 4,
|
||||
D2D1_EDGEDETECTION_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Strength"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EDGEDETECTION_PROP_STRENGTH = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "BlurRadius"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EDGEDETECTION_PROP_BLUR_RADIUS = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Mode"
|
||||
/// Property Type: D2D1_EDGEDETECTION_MODE
|
||||
/// </summary>
|
||||
D2D1_EDGEDETECTION_PROP_MODE = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "OverlayEdges"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_EDGEDETECTION_PROP_OVERLAY_EDGES = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "AlphaMode"
|
||||
/// Property Type: D2D1_ALPHA_MODE
|
||||
/// </summary>
|
||||
D2D1_EDGEDETECTION_PROP_ALPHA_MODE = 4,
|
||||
D2D1_EDGEDETECTION_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_EDGEDETECTION_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EDGEDETECTION_MODE
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_EDGEDETECTION_MODE
|
||||
{
|
||||
D2D1_EDGEDETECTION_MODE_SOBEL = 0,
|
||||
D2D1_EDGEDETECTION_MODE_PREWITT = 1,
|
||||
D2D1_EDGEDETECTION_MODE_FORCE_DWORD = 0xffffffff
|
||||
D2D1_EDGEDETECTION_MODE_SOBEL = 0,
|
||||
D2D1_EDGEDETECTION_MODE_PREWITT = 1,
|
||||
D2D1_EDGEDETECTION_MODE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_EDGEDETECTION_MODE;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HIGHLIGHTSANDSHADOWS_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Highlights and Shadows effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Highlights and Shadows effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_HIGHLIGHTSANDSHADOWS_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Highlights"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_HIGHLIGHTS = 0,
|
||||
|
||||
//
|
||||
// Property Name: "Shadows"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_SHADOWS = 1,
|
||||
|
||||
//
|
||||
// Property Name: "Clarity"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_CLARITY = 2,
|
||||
|
||||
//
|
||||
// Property Name: "InputGamma"
|
||||
// Property Type: D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA
|
||||
//
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_INPUT_GAMMA = 3,
|
||||
|
||||
//
|
||||
// Property Name: "MaskBlurRadius"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_MASK_BLUR_RADIUS = 4,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Highlights"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_HIGHLIGHTS = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Shadows"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_SHADOWS = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Clarity"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_CLARITY = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "InputGamma"
|
||||
/// Property Type: D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA
|
||||
/// </summary>
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_INPUT_GAMMA = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "MaskBlurRadius"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_MASK_BLUR_RADIUS = 4,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_HIGHLIGHTSANDSHADOWS_PROP;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA
|
||||
{
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_LINEAR = 0,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_SRGB = 1,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_FORCE_DWORD = 0xffffffff
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_LINEAR = 0,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_SRGB = 1,
|
||||
D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA;
|
||||
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_LOOKUPTABLE3D_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Lookup Table 3D effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The enumeration of the Lookup Table 3D effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_LOOKUPTABLE3D_PROP
|
||||
{
|
||||
|
||||
//
|
||||
// Property Name: "Lut"
|
||||
// Property Type: IUnknown *
|
||||
//
|
||||
D2D1_LOOKUPTABLE3D_PROP_LUT = 0,
|
||||
|
||||
//
|
||||
// Property Name: "AlphaMode"
|
||||
// Property Type: D2D1_ALPHA_MODE
|
||||
//
|
||||
D2D1_LOOKUPTABLE3D_PROP_ALPHA_MODE = 1,
|
||||
D2D1_LOOKUPTABLE3D_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Lut"
|
||||
/// Property Type: IUnknown *
|
||||
/// </summary>
|
||||
D2D1_LOOKUPTABLE3D_PROP_LUT = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "AlphaMode"
|
||||
/// Property Type: D2D1_ALPHA_MODE
|
||||
/// </summary>
|
||||
D2D1_LOOKUPTABLE3D_PROP_ALPHA_MODE = 1,
|
||||
D2D1_LOOKUPTABLE3D_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_LOOKUPTABLE3D_PROP;
|
||||
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Opacity effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_OPACITY_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Opacity"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_OPACITY_PROP_OPACITY = 0,
|
||||
D2D1_OPACITY_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_OPACITY_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Cross Fade effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_CROSSFADE_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Weight"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_CROSSFADE_PROP_WEIGHT = 0,
|
||||
D2D1_CROSSFADE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_CROSSFADE_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Tint effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_TINT_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Color"
|
||||
/// Property Type: D2D1_VECTOR_4F
|
||||
/// </summary>
|
||||
D2D1_TINT_PROP_COLOR = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ClampOutput"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_TINT_PROP_CLAMP_OUTPUT = 1,
|
||||
D2D1_TINT_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_TINT_PROP;
|
||||
|
||||
|
||||
#endif // #if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* 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.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+8
-3
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -7306,7 +7306,8 @@ enum D3D11_FEATURE
|
||||
D3D11_FEATURE_D3D9_OPTIONS1 = ( D3D11_FEATURE_MARKER_SUPPORT + 1 ) ,
|
||||
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_GPU_VIRTUAL_ADDRESS_SUPPORT = ( D3D11_FEATURE_D3D11_OPTIONS3 + 1 ) ,
|
||||
D3D11_FEATURE_D3D11_OPTIONS4 = ( D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT + 1 )
|
||||
} D3D11_FEATURE;
|
||||
|
||||
typedef struct D3D11_FEATURE_DATA_THREADING
|
||||
@@ -9661,6 +9662,9 @@ DEFINE_GUID(D3D11_DECODER_PROFILE_MPEG4PT2_VLD_ADVSIMPLE_NOGMC, 0xed418a9f, 0x0
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_MPEG4PT2_VLD_ADVSIMPLE_GMC, 0xab998b5b, 0x4258,0x44a9,0x9f,0xeb,0x94,0xe5,0x97,0xa6,0xba,0xae);
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_HEVC_VLD_MAIN, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10, 0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, 0x463707f8, 0xa1d0, 0x4585, 0x87, 0x6d, 0x83, 0xaa, 0x6d, 0x60, 0xb8, 0x9e);
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2, 0xa4c749ef, 0x6ecf, 0x48aa, 0x84, 0x48, 0x50, 0xa7, 0xa1, 0x16, 0x5f, 0xf7);
|
||||
DEFINE_GUID(D3D11_DECODER_PROFILE_VP8_VLD, 0x90b899ea, 0x3a62, 0x4705, 0x88, 0xb3, 0x8d, 0xf0, 0x4b, 0x27, 0x44, 0xe7);
|
||||
typedef struct D3D11_VIDEO_DECODER_DESC
|
||||
{
|
||||
GUID Guid;
|
||||
@@ -9929,7 +9933,8 @@ enum D3D11_VIDEO_PROCESSOR_FEATURE_CAPS
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ALPHA_STREAM = 0x80,
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_PIXEL_ASPECT_RATIO = 0x100,
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_MIRROR = 0x200,
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_SHADER_USAGE = 0x400
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_SHADER_USAGE = 0x400,
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_METADATA_HDR10 = 0x800
|
||||
} D3D11_VIDEO_PROCESSOR_FEATURE_CAPS;
|
||||
|
||||
typedef
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* 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.00.0613 */
|
||||
/* 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.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+2233
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+977
-28
File diff suppressed because it is too large
Load Diff
+485
-23
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,20 @@ typedef interface ID3D12Debug ID3D12Debug;
|
||||
#endif /* __ID3D12Debug_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12Debug1_FWD_DEFINED__
|
||||
#define __ID3D12Debug1_FWD_DEFINED__
|
||||
typedef interface ID3D12Debug1 ID3D12Debug1;
|
||||
|
||||
#endif /* __ID3D12Debug1_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugDevice1_FWD_DEFINED__
|
||||
#define __ID3D12DebugDevice1_FWD_DEFINED__
|
||||
typedef interface ID3D12DebugDevice1 ID3D12DebugDevice1;
|
||||
|
||||
#endif /* __ID3D12DebugDevice1_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugDevice_FWD_DEFINED__
|
||||
#define __ID3D12DebugDevice_FWD_DEFINED__
|
||||
typedef interface ID3D12DebugDevice ID3D12DebugDevice;
|
||||
@@ -64,6 +78,13 @@ typedef interface ID3D12DebugCommandQueue ID3D12DebugCommandQueue;
|
||||
#endif /* __ID3D12DebugCommandQueue_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugCommandList1_FWD_DEFINED__
|
||||
#define __ID3D12DebugCommandList1_FWD_DEFINED__
|
||||
typedef interface ID3D12DebugCommandList1 ID3D12DebugCommandList1;
|
||||
|
||||
#endif /* __ID3D12DebugCommandList1_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugCommandList_FWD_DEFINED__
|
||||
#define __ID3D12DebugCommandList_FWD_DEFINED__
|
||||
typedef interface ID3D12DebugCommandList ID3D12DebugCommandList;
|
||||
@@ -176,18 +197,106 @@ EXTERN_C const IID IID_ID3D12Debug;
|
||||
#endif /* __ID3D12Debug_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0001 */
|
||||
#ifndef __ID3D12Debug1_INTERFACE_DEFINED__
|
||||
#define __ID3D12Debug1_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3D12Debug1 */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12Debug1;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("affaa4ca-63fe-4d8e-b8ad-159000af4304")
|
||||
ID3D12Debug1 : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual void STDMETHODCALLTYPE EnableDebugLayer( void) = 0;
|
||||
|
||||
virtual void STDMETHODCALLTYPE SetEnableGPUBasedValidation(
|
||||
BOOL Enable) = 0;
|
||||
|
||||
virtual void STDMETHODCALLTYPE SetEnableSynchronizedCommandQueueValidation(
|
||||
BOOL Enable) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12Debug1Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12Debug1 * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12Debug1 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12Debug1 * This);
|
||||
|
||||
void ( STDMETHODCALLTYPE *EnableDebugLayer )(
|
||||
ID3D12Debug1 * This);
|
||||
|
||||
void ( STDMETHODCALLTYPE *SetEnableGPUBasedValidation )(
|
||||
ID3D12Debug1 * This,
|
||||
BOOL Enable);
|
||||
|
||||
void ( STDMETHODCALLTYPE *SetEnableSynchronizedCommandQueueValidation )(
|
||||
ID3D12Debug1 * This,
|
||||
BOOL Enable);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12Debug1Vtbl;
|
||||
|
||||
interface ID3D12Debug1
|
||||
{
|
||||
CONST_VTBL struct ID3D12Debug1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12Debug1_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12Debug1_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12Debug1_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12Debug1_EnableDebugLayer(This) \
|
||||
( (This)->lpVtbl -> EnableDebugLayer(This) )
|
||||
|
||||
#define ID3D12Debug1_SetEnableGPUBasedValidation(This,Enable) \
|
||||
( (This)->lpVtbl -> SetEnableGPUBasedValidation(This,Enable) )
|
||||
|
||||
#define ID3D12Debug1_SetEnableSynchronizedCommandQueueValidation(This,Enable) \
|
||||
( (This)->lpVtbl -> SetEnableSynchronizedCommandQueueValidation(This,Enable) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12Debug1_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0002 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
enum D3D12_DEBUG_FEATURE
|
||||
{
|
||||
D3D12_DEBUG_FEATURE_NONE = 0,
|
||||
D3D12_DEBUG_FEATURE_TREAT_BUNDLE_AS_DRAW = 0x1,
|
||||
D3D12_DEBUG_FEATURE_TREAT_BUNDLE_AS_DISPATCH = 0x2
|
||||
} D3D12_DEBUG_FEATURE;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS( D3D12_DEBUG_FEATURE );
|
||||
typedef
|
||||
enum D3D12_RLDO_FLAGS
|
||||
{
|
||||
@@ -198,10 +307,163 @@ enum D3D12_RLDO_FLAGS
|
||||
} D3D12_RLDO_FLAGS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(D3D12_RLDO_FLAGS)
|
||||
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_TYPE;
|
||||
|
||||
typedef
|
||||
enum D3D12_DEBUG_FEATURE
|
||||
{
|
||||
D3D12_DEBUG_FEATURE_NONE = 0,
|
||||
D3D12_DEBUG_FEATURE_ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS = 0x1,
|
||||
D3D12_DEBUG_FEATURE_CONSERVATIVE_RESOURCE_STATE_TRACKING = 0x2,
|
||||
D3D12_DEBUG_FEATURE_DISABLE_VIRTUALIZED_BUNDLES_VALIDATION = 0x4,
|
||||
D3D12_DEBUG_FEATURE_VALID_MASK = ( ( D3D12_DEBUG_FEATURE_ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS | D3D12_DEBUG_FEATURE_CONSERVATIVE_RESOURCE_STATE_TRACKING ) | D3D12_DEBUG_FEATURE_DISABLE_VIRTUALIZED_BUNDLES_VALIDATION )
|
||||
} D3D12_DEBUG_FEATURE;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(D3D12_DEBUG_FEATURE)
|
||||
typedef
|
||||
enum D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE
|
||||
{
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_NONE = 0,
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_STATE_TRACKING_ONLY = ( D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_NONE + 1 ) ,
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_UNGUARDED_VALIDATION = ( D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_STATE_TRACKING_ONLY + 1 ) ,
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_GUARDED_VALIDATION = ( D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_UNGUARDED_VALIDATION + 1 ) ,
|
||||
NUM_D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODES = ( D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE_GUARDED_VALIDATION + 1 )
|
||||
} D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE;
|
||||
|
||||
typedef
|
||||
enum D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS
|
||||
{
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_NONE = 0,
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS = 0x1,
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS = 0x2,
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS = 0x4,
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS_VALID_MASK = 0x7
|
||||
} D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS)
|
||||
typedef struct D3D12_DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS
|
||||
{
|
||||
UINT MaxMessagesPerCommandList;
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE DefaultShaderPatchMode;
|
||||
D3D12_GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS PipelineStateCreateFlags;
|
||||
} D3D12_DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS;
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0001_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0001_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__
|
||||
|
||||
/* interface ID3D12DebugDevice1 */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12DebugDevice1;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("a9b71770-d099-4a65-a698-3dee10020f88")
|
||||
ID3D12DebugDevice1 : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE SetDebugParameter(
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_TYPE Type,
|
||||
_In_reads_bytes_(DataSize) const void *pData,
|
||||
UINT DataSize) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDebugParameter(
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_TYPE Type,
|
||||
_Out_writes_bytes_(DataSize) void *pData,
|
||||
UINT DataSize) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ReportLiveDeviceObjects(
|
||||
D3D12_RLDO_FLAGS Flags) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12DebugDevice1Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12DebugDevice1 * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12DebugDevice1 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12DebugDevice1 * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetDebugParameter )(
|
||||
ID3D12DebugDevice1 * This,
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_TYPE Type,
|
||||
_In_reads_bytes_(DataSize) const void *pData,
|
||||
UINT DataSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDebugParameter )(
|
||||
ID3D12DebugDevice1 * This,
|
||||
D3D12_DEBUG_DEVICE_PARAMETER_TYPE Type,
|
||||
_Out_writes_bytes_(DataSize) void *pData,
|
||||
UINT DataSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *ReportLiveDeviceObjects )(
|
||||
ID3D12DebugDevice1 * This,
|
||||
D3D12_RLDO_FLAGS Flags);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12DebugDevice1Vtbl;
|
||||
|
||||
interface ID3D12DebugDevice1
|
||||
{
|
||||
CONST_VTBL struct ID3D12DebugDevice1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12DebugDevice1_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12DebugDevice1_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12DebugDevice1_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12DebugDevice1_SetDebugParameter(This,Type,pData,DataSize) \
|
||||
( (This)->lpVtbl -> SetDebugParameter(This,Type,pData,DataSize) )
|
||||
|
||||
#define ID3D12DebugDevice1_GetDebugParameter(This,Type,pData,DataSize) \
|
||||
( (This)->lpVtbl -> GetDebugParameter(This,Type,pData,DataSize) )
|
||||
|
||||
#define ID3D12DebugDevice1_ReportLiveDeviceObjects(This,Flags) \
|
||||
( (This)->lpVtbl -> ReportLiveDeviceObjects(This,Flags) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12DebugDevice1_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugDevice_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugDevice_INTERFACE_DEFINED__
|
||||
@@ -300,14 +562,14 @@ EXTERN_C const IID IID_ID3D12DebugDevice;
|
||||
#endif /* __ID3D12DebugDevice_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0002 */
|
||||
/* 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_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_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__
|
||||
@@ -392,6 +654,136 @@ EXTERN_C const IID IID_ID3D12DebugCommandQueue;
|
||||
#endif /* __ID3D12DebugCommandQueue_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0005 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
enum D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE
|
||||
{
|
||||
D3D12_DEBUG_COMMAND_LIST_PARAMETER_GPU_BASED_VALIDATION_SETTINGS = 0
|
||||
} D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE;
|
||||
|
||||
typedef struct D3D12_DEBUG_COMMAND_LIST_GPU_BASED_VALIDATION_SETTINGS
|
||||
{
|
||||
D3D12_GPU_BASED_VALIDATION_SHADER_PATCH_MODE ShaderPatchMode;
|
||||
} D3D12_DEBUG_COMMAND_LIST_GPU_BASED_VALIDATION_SETTINGS;
|
||||
|
||||
|
||||
|
||||
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__
|
||||
|
||||
/* interface ID3D12DebugCommandList1 */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3D12DebugCommandList1;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("102ca951-311b-4b01-b11f-ecb83e061b37")
|
||||
ID3D12DebugCommandList1 : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual BOOL STDMETHODCALLTYPE AssertResourceState(
|
||||
_In_ ID3D12Resource *pResource,
|
||||
UINT Subresource,
|
||||
UINT State) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetDebugParameter(
|
||||
D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE Type,
|
||||
_In_reads_bytes_(DataSize) const void *pData,
|
||||
UINT DataSize) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDebugParameter(
|
||||
D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE Type,
|
||||
_Out_writes_bytes_(DataSize) void *pData,
|
||||
UINT DataSize) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3D12DebugCommandList1Vtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3D12DebugCommandList1 * This,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3D12DebugCommandList1 * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3D12DebugCommandList1 * This);
|
||||
|
||||
BOOL ( STDMETHODCALLTYPE *AssertResourceState )(
|
||||
ID3D12DebugCommandList1 * This,
|
||||
_In_ ID3D12Resource *pResource,
|
||||
UINT Subresource,
|
||||
UINT State);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetDebugParameter )(
|
||||
ID3D12DebugCommandList1 * This,
|
||||
D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE Type,
|
||||
_In_reads_bytes_(DataSize) const void *pData,
|
||||
UINT DataSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetDebugParameter )(
|
||||
ID3D12DebugCommandList1 * This,
|
||||
D3D12_DEBUG_COMMAND_LIST_PARAMETER_TYPE Type,
|
||||
_Out_writes_bytes_(DataSize) void *pData,
|
||||
UINT DataSize);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3D12DebugCommandList1Vtbl;
|
||||
|
||||
interface ID3D12DebugCommandList1
|
||||
{
|
||||
CONST_VTBL struct ID3D12DebugCommandList1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3D12DebugCommandList1_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3D12DebugCommandList1_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3D12DebugCommandList1_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3D12DebugCommandList1_AssertResourceState(This,pResource,Subresource,State) \
|
||||
( (This)->lpVtbl -> AssertResourceState(This,pResource,Subresource,State) )
|
||||
|
||||
#define ID3D12DebugCommandList1_SetDebugParameter(This,Type,pData,DataSize) \
|
||||
( (This)->lpVtbl -> SetDebugParameter(This,Type,pData,DataSize) )
|
||||
|
||||
#define ID3D12DebugCommandList1_GetDebugParameter(This,Type,pData,DataSize) \
|
||||
( (This)->lpVtbl -> GetDebugParameter(This,Type,pData,DataSize) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3D12DebugCommandList1_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3D12DebugCommandList_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugCommandList_INTERFACE_DEFINED__
|
||||
|
||||
@@ -493,7 +885,7 @@ EXTERN_C const IID IID_ID3D12DebugCommandList;
|
||||
#endif /* __ID3D12DebugCommandList_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0004 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0007 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
@@ -1459,7 +1851,74 @@ enum D3D12_MESSAGE_ID
|
||||
D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE = ( D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_NO_GRAPHICS_API_SUPPORT = ( D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_NO_COMPUTE_API_SUPPORT = ( D3D12_MESSAGE_ID_NO_GRAPHICS_API_SUPPORT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_NO_COMPUTE_API_SUPPORT + 1 )
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_RESOURCE_FLAGS_NOT_SUPPORTED = ( D3D12_MESSAGE_ID_NO_COMPUTE_API_SUPPORT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_ROOT_ARGUMENT_UNINITIALIZED = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_RESOURCE_FLAGS_NOT_SUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_HEAP_INDEX_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_ROOT_ARGUMENT_UNINITIALIZED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_TABLE_REGISTER_INDEX_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_HEAP_INDEX_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_UNINITIALIZED = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_TABLE_REGISTER_INDEX_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_TYPE_MISMATCH = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_UNINITIALIZED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_SRV_RESOURCE_DIMENSION_MISMATCH = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_DESCRIPTOR_TYPE_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UAV_RESOURCE_DIMENSION_MISMATCH = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_SRV_RESOURCE_DIMENSION_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UAV_RESOURCE_DIMENSION_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COPYRESOURCE_NULLDST = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COPYRESOURCE_INVALIDDSTRESOURCE = ( D3D12_MESSAGE_ID_COPYRESOURCE_NULLDST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COPYRESOURCE_NULLSRC = ( D3D12_MESSAGE_ID_COPYRESOURCE_INVALIDDSTRESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COPYRESOURCE_INVALIDSRCRESOURCE = ( D3D12_MESSAGE_ID_COPYRESOURCE_NULLSRC + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_NULLDST = ( D3D12_MESSAGE_ID_COPYRESOURCE_INVALIDSRCRESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_INVALIDDSTRESOURCE = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_NULLDST + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_NULLSRC = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_INVALIDDSTRESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_INVALIDSRCRESOURCE = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_NULLSRC + 1 ) ,
|
||||
D3D12_MESSAGE_ID_PIPELINE_STATE_TYPE_MISMATCH = ( D3D12_MESSAGE_ID_RESOLVESUBRESOURCE_INVALIDSRCRESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_DISPATCH_ROOT_SIGNATURE_NOT_SET = ( D3D12_MESSAGE_ID_PIPELINE_STATE_TYPE_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_DISPATCH_ROOT_SIGNATURE_MISMATCH = ( D3D12_MESSAGE_ID_COMMAND_LIST_DISPATCH_ROOT_SIGNATURE_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOURCE_BARRIER_ZERO_BARRIERS = ( D3D12_MESSAGE_ID_COMMAND_LIST_DISPATCH_ROOT_SIGNATURE_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_BEGIN_END_EVENT_MISMATCH = ( D3D12_MESSAGE_ID_RESOURCE_BARRIER_ZERO_BARRIERS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOURCE_BARRIER_POSSIBLE_BEFORE_AFTER_MISMATCH = ( D3D12_MESSAGE_ID_BEGIN_END_EVENT_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_BEGIN_END = ( D3D12_MESSAGE_ID_RESOURCE_BARRIER_POSSIBLE_BEFORE_AFTER_MISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_INVALID_RESOURCE = ( D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_BEGIN_END + 1 ) ,
|
||||
D3D12_MESSAGE_ID_USE_OF_ZERO_REFCOUNT_OBJECT = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_INVALID_RESOURCE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_OBJECT_EVICTED_WHILE_STILL_IN_USE = ( D3D12_MESSAGE_ID_USE_OF_ZERO_REFCOUNT_OBJECT + 1 ) ,
|
||||
D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_ROOT_DESCRIPTOR_ACCESS_OUT_OF_BOUNDS = ( D3D12_MESSAGE_ID_OBJECT_EVICTED_WHILE_STILL_IN_USE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_INVALIDLIBRARYBLOB = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_ROOT_DESCRIPTOR_ACCESS_OUT_OF_BOUNDS + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_DRIVERVERSIONMISMATCH = ( D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_INVALIDLIBRARYBLOB + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_ADAPTERVERSIONMISMATCH = ( D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_DRIVERVERSIONMISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_UNSUPPORTED = ( D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_ADAPTERVERSIONMISMATCH + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATE_PIPELINELIBRARY = ( D3D12_MESSAGE_ID_CREATEPIPELINELIBRARY_UNSUPPORTED + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LIVE_PIPELINELIBRARY = ( D3D12_MESSAGE_ID_CREATE_PIPELINELIBRARY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DESTROY_PIPELINELIBRARY = ( D3D12_MESSAGE_ID_LIVE_PIPELINELIBRARY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_STOREPIPELINE_NONAME = ( D3D12_MESSAGE_ID_DESTROY_PIPELINELIBRARY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_STOREPIPELINE_DUPLICATENAME = ( D3D12_MESSAGE_ID_STOREPIPELINE_NONAME + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LOADPIPELINE_NAMENOTFOUND = ( D3D12_MESSAGE_ID_STOREPIPELINE_DUPLICATENAME + 1 ) ,
|
||||
D3D12_MESSAGE_ID_LOADPIPELINE_INVALIDDESC = ( D3D12_MESSAGE_ID_LOADPIPELINE_NAMENOTFOUND + 1 ) ,
|
||||
D3D12_MESSAGE_ID_PIPELINELIBRARY_SERIALIZE_NOTENOUGHMEMORY = ( D3D12_MESSAGE_ID_LOADPIPELINE_INVALIDDESC + 1 ) ,
|
||||
D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_PS_OUTPUT_RT_OUTPUT_MISMATCH = ( D3D12_MESSAGE_ID_PIPELINELIBRARY_SERIALIZE_NOTENOUGHMEMORY + 1 ) ,
|
||||
D3D12_MESSAGE_ID_SETEVENTONMULTIPLEFENCECOMPLETION_INVALIDFLAGS = ( D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_PS_OUTPUT_RT_OUTPUT_MISMATCH + 1 ) ,
|
||||
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_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_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_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 ) ,
|
||||
D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE = ( D3D12_MESSAGE_ID_DEPRECATED_API + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_DESCRIPTOR_TABLE_NOT_SET = ( D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_CONSTANT_BUFFER_VIEW_NOT_SET = ( D3D12_MESSAGE_ID_COMMAND_LIST_DESCRIPTOR_TABLE_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_SHADER_RESOURCE_VIEW_NOT_SET = ( D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_CONSTANT_BUFFER_VIEW_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_UNORDERED_ACCESS_VIEW_NOT_SET = ( D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_SHADER_RESOURCE_VIEW_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DISCARD_INVALID_SUBRESOURCE_RANGE = ( D3D12_MESSAGE_ID_COMMAND_LIST_ROOT_UNORDERED_ACCESS_VIEW_NOT_SET + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DISCARD_ONE_SUBRESOURCE_FOR_MIPS_WITH_RECTS = ( D3D12_MESSAGE_ID_DISCARD_INVALID_SUBRESOURCE_RANGE + 1 ) ,
|
||||
D3D12_MESSAGE_ID_DISCARD_NO_RECTS_FOR_NON_TEXTURE2D = ( D3D12_MESSAGE_ID_DISCARD_ONE_SUBRESOURCE_FOR_MIPS_WITH_RECTS + 1 ) ,
|
||||
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_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_GPU_BASED_VALIDATION_UNSUPPORTED + 1 )
|
||||
} D3D12_MESSAGE_ID;
|
||||
|
||||
typedef struct D3D12_MESSAGE
|
||||
@@ -1490,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_0004_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0004_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__
|
||||
@@ -1898,20 +2357,23 @@ EXTERN_C const IID IID_ID3D12InfoQueue;
|
||||
#endif /* __ID3D12InfoQueue_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0005 */
|
||||
/* 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_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);
|
||||
DEFINE_GUID(IID_ID3D12DebugCommandList1,0x102ca951,0x311b,0x4b01,0xb1,0x1f,0xec,0xb8,0x3e,0x06,0x1b,0x37);
|
||||
DEFINE_GUID(IID_ID3D12DebugCommandList,0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0xae,0xea,0xb6,0x05,0x3f);
|
||||
DEFINE_GUID(IID_ID3D12InfoQueue,0x0742a90b,0xc387,0x483f,0xb9,0x46,0x30,0xa7,0xe4,0xe6,0x14,0x58);
|
||||
|
||||
|
||||
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_0008_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
+123
-3
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -46,6 +46,13 @@ typedef interface ID3D10Blob ID3D10Blob;
|
||||
#endif /* __ID3D10Blob_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ID3DDestructionNotifier_FWD_DEFINED__
|
||||
#define __ID3DDestructionNotifier_FWD_DEFINED__
|
||||
typedef interface ID3DDestructionNotifier ID3DDestructionNotifier;
|
||||
|
||||
#endif /* __ID3DDestructionNotifier_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "oaidl.h"
|
||||
#include "ocidl.h"
|
||||
@@ -442,6 +449,119 @@ typedef ID3D10Blob ID3DBlob;
|
||||
|
||||
typedef ID3DBlob* LPD3DBLOB;
|
||||
#define IID_ID3DBlob IID_ID3D10Blob
|
||||
typedef void ( __stdcall *PFN_DESTRUCTION_CALLBACK )(
|
||||
void *pData);
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0001_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0001_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3DDestructionNotifier_INTERFACE_DEFINED__
|
||||
#define __ID3DDestructionNotifier_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ID3DDestructionNotifier */
|
||||
/* [unique][local][object][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ID3DDestructionNotifier;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("a06eb39a-50da-425b-8c31-4eecd6c270f3")
|
||||
ID3DDestructionNotifier : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE RegisterDestructionCallback(
|
||||
/* [annotation] */
|
||||
_In_ PFN_DESTRUCTION_CALLBACK callbackFn,
|
||||
/* [annotation] */
|
||||
_In_ void *pData,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pCallbackID) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE UnregisterDestructionCallback(
|
||||
/* [annotation] */
|
||||
_In_ UINT callbackID) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ID3DDestructionNotifierVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ID3DDestructionNotifier * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [annotation][iid_is][out] */
|
||||
_COM_Outptr_ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ID3DDestructionNotifier * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ID3DDestructionNotifier * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *RegisterDestructionCallback )(
|
||||
ID3DDestructionNotifier * This,
|
||||
/* [annotation] */
|
||||
_In_ PFN_DESTRUCTION_CALLBACK callbackFn,
|
||||
/* [annotation] */
|
||||
_In_ void *pData,
|
||||
/* [annotation] */
|
||||
_Out_ UINT *pCallbackID);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *UnregisterDestructionCallback )(
|
||||
ID3DDestructionNotifier * This,
|
||||
/* [annotation] */
|
||||
_In_ UINT callbackID);
|
||||
|
||||
END_INTERFACE
|
||||
} ID3DDestructionNotifierVtbl;
|
||||
|
||||
interface ID3DDestructionNotifier
|
||||
{
|
||||
CONST_VTBL struct ID3DDestructionNotifierVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ID3DDestructionNotifier_QueryInterface(This,riid,ppvObject) \
|
||||
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
|
||||
|
||||
#define ID3DDestructionNotifier_AddRef(This) \
|
||||
( (This)->lpVtbl -> AddRef(This) )
|
||||
|
||||
#define ID3DDestructionNotifier_Release(This) \
|
||||
( (This)->lpVtbl -> Release(This) )
|
||||
|
||||
|
||||
#define ID3DDestructionNotifier_RegisterDestructionCallback(This,callbackFn,pData,pCallbackID) \
|
||||
( (This)->lpVtbl -> RegisterDestructionCallback(This,callbackFn,pData,pCallbackID) )
|
||||
|
||||
#define ID3DDestructionNotifier_UnregisterDestructionCallback(This,callbackID) \
|
||||
( (This)->lpVtbl -> UnregisterDestructionCallback(This,callbackID) )
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __ID3DDestructionNotifier_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3dcommon_0000_0002 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
enum _D3D_INCLUDE_TYPE
|
||||
{
|
||||
@@ -866,8 +986,8 @@ DEFINE_GUID(WKPDID_CommentStringW,0xd0149dc0,0x90e8,0x4ec8,0x81, 0x44, 0xe9, 0x0
|
||||
#define D3D_COMPONENT_MASK_W 8
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0001_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0001_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
Vendored
+277
-48
@@ -3,7 +3,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Abstract:
|
||||
// Public API definitions for DWrite, D2D and DImage.
|
||||
// Public API definitions shared by DWrite, D2D, and DImage.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#pragma once
|
||||
@@ -21,84 +21,72 @@
|
||||
#define CHECKMETHOD(method) virtual DECLSPEC_NOTHROW _Must_inspect_result_ HRESULT STDMETHODCALLTYPE method
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4201) // anonymous unions warning
|
||||
|
||||
//
|
||||
// Forward declarations
|
||||
//
|
||||
interface IDXGISurface;
|
||||
struct IDXGISurface;
|
||||
|
||||
//+----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// DWRITE_MEASURING_MODE
|
||||
//
|
||||
// Synopsis:
|
||||
// The measuring method used for text layout.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// The measuring method used for text layout.
|
||||
/// </summary>
|
||||
typedef enum DWRITE_MEASURING_MODE
|
||||
{
|
||||
//
|
||||
// Text is measured using glyph ideal metrics whose values are independent to the current display resolution.
|
||||
//
|
||||
/// <summary>
|
||||
/// Text is measured using glyph ideal metrics whose values are independent to the current display resolution.
|
||||
/// </summary>
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
|
||||
//
|
||||
// Text is measured using glyph display compatible metrics whose values tuned for the current display resolution.
|
||||
//
|
||||
/// <summary>
|
||||
/// Text is measured using glyph display compatible metrics whose values tuned for the current display resolution.
|
||||
/// </summary>
|
||||
DWRITE_MEASURING_MODE_GDI_CLASSIC,
|
||||
|
||||
//
|
||||
/// <summary>
|
||||
// Text is measured using the same glyph display metrics as text measured by GDI using a font
|
||||
// created with CLEARTYPE_NATURAL_QUALITY.
|
||||
//
|
||||
/// </summary>
|
||||
DWRITE_MEASURING_MODE_GDI_NATURAL
|
||||
|
||||
} DWRITE_MEASURING_MODE;
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_ALPHA_MODE
|
||||
//
|
||||
// Synopsis:
|
||||
// Qualifies how alpha is to be treated in a bitmap or render target containing
|
||||
// alpha.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Qualifies how alpha is to be treated in a bitmap or render target containing
|
||||
/// alpha.
|
||||
/// </summary>
|
||||
typedef enum D2D1_ALPHA_MODE
|
||||
{
|
||||
|
||||
//
|
||||
// Alpha mode should be determined implicitly. Some target surfaces do not supply
|
||||
// or imply this information in which case alpha must be specified.
|
||||
//
|
||||
/// <summary>
|
||||
/// Alpha mode should be determined implicitly. Some target surfaces do not supply
|
||||
/// or imply this information in which case alpha must be specified.
|
||||
/// </summary>
|
||||
D2D1_ALPHA_MODE_UNKNOWN = 0,
|
||||
|
||||
//
|
||||
// Treat the alpha as premultipled.
|
||||
//
|
||||
/// <summary>
|
||||
/// Treat the alpha as premultipled.
|
||||
/// </summary>
|
||||
D2D1_ALPHA_MODE_PREMULTIPLIED = 1,
|
||||
|
||||
//
|
||||
// Opacity is in the 'A' component only.
|
||||
//
|
||||
/// <summary>
|
||||
/// Opacity is in the 'A' component only.
|
||||
/// </summary>
|
||||
D2D1_ALPHA_MODE_STRAIGHT = 2,
|
||||
|
||||
//
|
||||
// Ignore any alpha channel information.
|
||||
//
|
||||
/// <summary>
|
||||
/// Ignore any alpha channel information.
|
||||
/// </summary>
|
||||
D2D1_ALPHA_MODE_IGNORE = 3,
|
||||
|
||||
D2D1_ALPHA_MODE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_ALPHA_MODE;
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Struct:
|
||||
// D2D1_PIXEL_FORMAT
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Description of a pixel format.
|
||||
/// </summary>
|
||||
typedef struct D2D1_PIXEL_FORMAT
|
||||
{
|
||||
DXGI_FORMAT format;
|
||||
@@ -106,4 +94,245 @@ typedef struct D2D1_PIXEL_FORMAT
|
||||
|
||||
} D2D1_PIXEL_FORMAT;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an x-coordinate and y-coordinate pair in two-dimensional space.
|
||||
/// </summary>
|
||||
typedef struct D2D_POINT_2U
|
||||
{
|
||||
UINT32 x;
|
||||
UINT32 y;
|
||||
|
||||
} D2D_POINT_2U;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an x-coordinate and y-coordinate pair in two-dimensional space.
|
||||
/// </summary>
|
||||
typedef struct D2D_POINT_2F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
|
||||
} D2D_POINT_2F;
|
||||
|
||||
typedef POINT D2D_POINT_2L;
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 2 FLOAT values (x, y).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_2F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
|
||||
} D2D_VECTOR_2F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 3 FLOAT values (x, y, z).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_3F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
FLOAT z;
|
||||
|
||||
} D2D_VECTOR_3F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 4 FLOAT values (x, y, z, w).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_4F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
FLOAT z;
|
||||
FLOAT w;
|
||||
|
||||
} D2D_VECTOR_4F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle defined by the coordinates of the upper-left corner
|
||||
/// (left, top) and the coordinates of the lower-right corner (right, bottom).
|
||||
/// </summary>
|
||||
typedef struct D2D_RECT_F
|
||||
{
|
||||
FLOAT left;
|
||||
FLOAT top;
|
||||
FLOAT right;
|
||||
FLOAT bottom;
|
||||
|
||||
} D2D_RECT_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle defined by the coordinates of the upper-left corner
|
||||
/// (left, top) and the coordinates of the lower-right corner (right, bottom).
|
||||
/// </summary>
|
||||
typedef struct D2D_RECT_U
|
||||
{
|
||||
UINT32 left;
|
||||
UINT32 top;
|
||||
UINT32 right;
|
||||
UINT32 bottom;
|
||||
|
||||
} D2D_RECT_U;
|
||||
|
||||
typedef RECT D2D_RECT_L;
|
||||
|
||||
/// <summary>
|
||||
/// Stores an ordered pair of floats, typically the width and height of a rectangle.
|
||||
/// </summary>
|
||||
typedef struct D2D_SIZE_F
|
||||
{
|
||||
FLOAT width;
|
||||
FLOAT height;
|
||||
|
||||
} D2D_SIZE_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stores an ordered pair of integers, typically the width and height of a
|
||||
/// rectangle.
|
||||
/// </summary>
|
||||
typedef struct D2D_SIZE_U
|
||||
{
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
|
||||
} D2D_SIZE_U;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 3-by-2 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_3X2_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Horizontal scaling / cosine of rotation
|
||||
/// </summary>
|
||||
FLOAT m11;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical shear / sine of rotation
|
||||
/// </summary>
|
||||
FLOAT m12;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal shear / negative sine of rotation
|
||||
/// </summary>
|
||||
FLOAT m21;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical scaling / cosine of rotation
|
||||
/// </summary>
|
||||
FLOAT m22;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal shift (always orthogonal regardless of rotation)
|
||||
/// </summary>
|
||||
FLOAT dx;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical shift (always orthogonal regardless of rotation)
|
||||
/// </summary>
|
||||
FLOAT dy;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12;
|
||||
FLOAT _21, _22;
|
||||
FLOAT _31, _32;
|
||||
};
|
||||
|
||||
FLOAT m[3][2];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_3X2_F;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 4-by-3 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_4X3_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13;
|
||||
FLOAT _21, _22, _23;
|
||||
FLOAT _31, _32, _33;
|
||||
FLOAT _41, _42, _43;
|
||||
};
|
||||
|
||||
FLOAT m[4][3];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_4X3_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 4-by-4 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_4X4_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13, _14;
|
||||
FLOAT _21, _22, _23, _24;
|
||||
FLOAT _31, _32, _33, _34;
|
||||
FLOAT _41, _42, _43, _44;
|
||||
};
|
||||
|
||||
FLOAT m[4][4];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_4X4_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 5-by-4 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_5X4_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13, _14;
|
||||
FLOAT _21, _22, _23, _24;
|
||||
FLOAT _31, _32, _33, _34;
|
||||
FLOAT _41, _42, _43, _44;
|
||||
FLOAT _51, _52, _53, _54;
|
||||
};
|
||||
|
||||
FLOAT m[5][4];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_5X4_F;
|
||||
|
||||
|
||||
typedef D2D_POINT_2F D2D1_POINT_2F;
|
||||
typedef D2D_POINT_2U D2D1_POINT_2U;
|
||||
typedef D2D_POINT_2L D2D1_POINT_2L;
|
||||
typedef D2D_RECT_F D2D1_RECT_F;
|
||||
typedef D2D_RECT_U D2D1_RECT_U;
|
||||
typedef D2D_RECT_L D2D1_RECT_L;
|
||||
typedef D2D_SIZE_F D2D1_SIZE_F;
|
||||
typedef D2D_SIZE_U D2D1_SIZE_U;
|
||||
typedef D2D_MATRIX_3X2_F D2D1_MATRIX_3X2_F;
|
||||
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif /* DCOMMON_H_INCLUDED */
|
||||
|
||||
Vendored
+15
-11
@@ -10,9 +10,7 @@
|
||||
#ifndef DWRITE_H_INCLUDED
|
||||
#define DWRITE_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef DWRITE_NO_WINDOWS_H
|
||||
|
||||
@@ -56,7 +54,7 @@ enum DWRITE_FONT_FILE_TYPE
|
||||
/// <summary>
|
||||
/// OpenType font that contains a TrueType collection.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION,
|
||||
DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION,
|
||||
|
||||
/// <summary>
|
||||
/// Type 1 PFM font.
|
||||
@@ -76,7 +74,10 @@ enum DWRITE_FONT_FILE_TYPE
|
||||
/// <summary>
|
||||
/// Bitmap .FON font.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FILE_TYPE_BITMAP
|
||||
DWRITE_FONT_FILE_TYPE_BITMAP,
|
||||
|
||||
// The following name is obsolete, but kept as an alias to avoid breaking existing code.
|
||||
DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION = DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -97,9 +98,9 @@ enum DWRITE_FONT_FACE_TYPE
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE,
|
||||
|
||||
/// <summary>
|
||||
/// OpenType font face that is a part of a TrueType collection.
|
||||
/// OpenType font face that is a part of a TrueType or CFF collection.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION,
|
||||
DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION,
|
||||
|
||||
/// <summary>
|
||||
/// A Type 1 font face.
|
||||
@@ -127,7 +128,10 @@ enum DWRITE_FONT_FACE_TYPE
|
||||
/// font file loaders) and the resulting font face object supports only the
|
||||
/// minimum functionality necessary to render glyphs.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FACE_TYPE_RAW_CFF
|
||||
DWRITE_FONT_FACE_TYPE_RAW_CFF,
|
||||
|
||||
// The following name is obsolete, but kept as an alias to avoid breaking existing code.
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION = DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -2446,7 +2450,7 @@ enum DWRITE_NUMBER_SUBSTITUTION_METHOD
|
||||
/// <summary>
|
||||
/// Holds the appropriate digits and numeric punctuation for a given locale.
|
||||
/// </summary>
|
||||
interface DECLSPEC_UUID("14885CC9-BAB0-4f90-B6ED-5C366A2CD03D") DECLSPEC_NOVTABLE IDWriteNumberSubstitution : public IUnknown
|
||||
interface DWRITE_DECLARE_INTERFACE("14885CC9-BAB0-4f90-B6ED-5C366A2CD03D") IDWriteNumberSubstitution : public IUnknown
|
||||
{
|
||||
};
|
||||
|
||||
@@ -2511,7 +2515,7 @@ struct DWRITE_SHAPING_GLYPH_PROPERTIES
|
||||
/// stop prematurely and return a callback error. Rather than return E_NOTIMPL,
|
||||
/// an application should stub the method and return a constant/null and S_OK.
|
||||
/// </summary>
|
||||
interface DECLSPEC_UUID("688e1a58-5094-47c8-adc8-fbcea60ae92b") DECLSPEC_NOVTABLE IDWriteTextAnalysisSource : public IUnknown
|
||||
interface DWRITE_DECLARE_INTERFACE("688e1a58-5094-47c8-adc8-fbcea60ae92b") IDWriteTextAnalysisSource : public IUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a block of text starting at the specified text position.
|
||||
@@ -2620,7 +2624,7 @@ interface DECLSPEC_UUID("688e1a58-5094-47c8-adc8-fbcea60ae92b") DECLSPEC_NOVTABL
|
||||
/// state of the analysis sink, therefore a Set method call on a range
|
||||
/// overwrites the previously set analysis result of the same range.
|
||||
/// </summary>
|
||||
interface DECLSPEC_UUID("5810cd44-0ca0-4701-b3fa-bec5182ae4f6") DECLSPEC_NOVTABLE IDWriteTextAnalysisSink : public IUnknown
|
||||
interface DWRITE_DECLARE_INTERFACE("5810cd44-0ca0-4701-b3fa-bec5182ae4f6") IDWriteTextAnalysisSink : public IUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// Report script analysis for the text range.
|
||||
@@ -2918,7 +2922,7 @@ interface DWRITE_DECLARE_INTERFACE("b7e6163e-7f46-43b4-84b3-e4e6249c365d") IDWri
|
||||
_In_reads_(glyphCount) UINT16 const* glyphIndices,
|
||||
_In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProps,
|
||||
UINT32 glyphCount,
|
||||
_In_ IDWriteFontFace * fontFace,
|
||||
_In_ IDWriteFontFace* fontFace,
|
||||
FLOAT fontEmSize,
|
||||
BOOL isSideways,
|
||||
BOOL isRightToLeft,
|
||||
|
||||
Vendored
+6
-2
@@ -1101,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,
|
||||
@@ -1355,6 +1357,8 @@ interface DWRITE_DECLARE_INTERFACE("acd16696-8c14-4f5d-877e-fe3fc1d32738") IDWri
|
||||
_Out_ DWRITE_FONT_METRICS1* fontMetrics
|
||||
) PURE;
|
||||
|
||||
using IDWriteFont::GetMetrics;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the PANOSE values from the font, used for font selection and
|
||||
/// matching.
|
||||
@@ -1714,7 +1718,7 @@ interface DWRITE_DECLARE_INTERFACE("80DAD800-E21F-4E83-96CE-BFCCE500DB7C") IDWri
|
||||
/// If any of these callbacks returns an error, the analysis functions will
|
||||
/// stop prematurely and return a callback error.
|
||||
/// </summary>
|
||||
interface DECLSPEC_UUID("{639CFAD8-0FB4-4B21-A58A-067920120009}") DECLSPEC_NOVTABLE IDWriteTextAnalysisSource1 : public IDWriteTextAnalysisSource
|
||||
interface DWRITE_DECLARE_INTERFACE("639CFAD8-0FB4-4B21-A58A-067920120009") IDWriteTextAnalysisSource1 : public IDWriteTextAnalysisSource
|
||||
{
|
||||
/// <summary>
|
||||
/// The text analyzer calls back to this to get the desired glyph
|
||||
@@ -1753,7 +1757,7 @@ interface DECLSPEC_UUID("{639CFAD8-0FB4-4B21-A58A-067920120009}") DECLSPEC_NOVTA
|
||||
/// The interface implemented by the client to receive the
|
||||
/// output of the text analyzers.
|
||||
/// </summary>
|
||||
interface DECLSPEC_UUID("B0D941A0-85E7-4D8B-9FD3-5CED9934482A") DECLSPEC_NOVTABLE IDWriteTextAnalysisSink1 : public IDWriteTextAnalysisSink
|
||||
interface DWRITE_DECLARE_INTERFACE("B0D941A0-85E7-4D8B-9FD3-5CED9934482A") IDWriteTextAnalysisSink1 : public IDWriteTextAnalysisSink
|
||||
{
|
||||
/// <summary>
|
||||
/// The text analyzer calls back to this to report the actual orientation
|
||||
|
||||
Vendored
+10
-6
@@ -554,8 +554,8 @@ interface DWRITE_DECLARE_INTERFACE("EFA008F9-F7A1-48BF-B05C-F224713CC0FF") IDWri
|
||||
DWRITE_FONT_WEIGHT baseWeight,
|
||||
DWRITE_FONT_STYLE baseStyle,
|
||||
DWRITE_FONT_STRETCH baseStretch,
|
||||
_Deref_out_range_(0, textLength) UINT32* mappedLength,
|
||||
_COM_Outptr_ IDWriteFont** mappedFont,
|
||||
_Out_range_(0, textLength) UINT32* mappedLength,
|
||||
_COM_Outptr_result_maybenull_ IDWriteFont** mappedFont,
|
||||
_Out_ FLOAT* scale
|
||||
) PURE;
|
||||
};
|
||||
@@ -653,8 +653,10 @@ typedef D3DCOLORVALUE DWRITE_COLOR_F;
|
||||
interface DWRITE_DECLARE_INTERFACE("29748ed6-8c9c-4a6a-be0b-d912e8538944") IDWriteFont2 : public IDWriteFont1
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns TRUE if the font contains color information (COLR and CPAL tables),
|
||||
/// or FALSE if not.
|
||||
/// Returns TRUE if the font contains tables that can provide color information
|
||||
/// (including COLR, CPAL, SVG, CBDT, sbix tables), or FALSE if not. Note that
|
||||
/// TRUE is returned even in the case when the font tables contain only grayscale
|
||||
/// images.
|
||||
/// </summary>
|
||||
STDMETHOD_(BOOL, IsColorFont)() PURE;
|
||||
};
|
||||
@@ -667,8 +669,10 @@ interface DWRITE_DECLARE_INTERFACE("29748ed6-8c9c-4a6a-be0b-d912e8538944") IDWri
|
||||
interface DWRITE_DECLARE_INTERFACE("d8b768ff-64bc-4e66-982b-ec8e87f693f7") IDWriteFontFace2 : public IDWriteFontFace1
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns TRUE if the font contains color information (COLR and CPAL tables),
|
||||
/// or FALSE if not.
|
||||
/// Returns TRUE if the font contains tables that can provide color information
|
||||
/// (including COLR, CPAL, SVG, CBDT, sbix tables), or FALSE if not. Note that
|
||||
/// TRUE is returned even in the case when the font tables contain only grayscale
|
||||
/// images.
|
||||
/// </summary>
|
||||
STDMETHOD_(BOOL, IsColorFont)() PURE;
|
||||
|
||||
|
||||
Vendored
+319
-3
@@ -10,9 +10,7 @@
|
||||
#ifndef DWRITE_3_H_INCLUDED
|
||||
#define DWRITE_3_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <DWrite_2.h>
|
||||
|
||||
@@ -1247,6 +1245,8 @@ interface DWRITE_DECLARE_INTERFACE("D37D7598-09BE-4222-A236-2081341CC1F2") IDWri
|
||||
_Out_ DWRITE_GRID_FIT_MODE* gridFitMode
|
||||
) PURE;
|
||||
|
||||
using IDWriteFontFace2::GetRecommendedRenderingMode;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the character is locally downloaded from the font.
|
||||
/// </summary>
|
||||
@@ -1740,4 +1740,320 @@ interface DWRITE_DECLARE_INTERFACE("07DDCD52-020E-4DE8-AC33-6C953D83F92D") IDWri
|
||||
) PURE;
|
||||
};
|
||||
|
||||
#endif /* DWRITE_3_H_INCLUDED */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fonts may contain multiple drawable data formats for glyphs. These flags specify which formats
|
||||
/// are supported in the font, either at a font-wide level or per glyph, and the app may use them
|
||||
/// to tell DWrite which formats to return when splitting a color glyph run.
|
||||
/// </summary>
|
||||
enum DWRITE_GLYPH_IMAGE_FORMATS
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates no data is available for this glyph.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_NONE = 0x00000000,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has TrueType outlines.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has CFF outlines.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_CFF = 0x00000002,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has multilayered COLR data.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_COLR = 0x00000004,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has SVG outlines as standard XML.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Fonts may store the content gzip'd rather than plain text,
|
||||
/// indicated by the first two bytes as gzip header {0x1F 0x8B}.
|
||||
/// </remarks>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_SVG = 0x00000008,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has PNG image data, with standard PNG IHDR.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PNG = 0x00000010,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has JPEG image data, with standard JIFF SOI header.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_JPEG = 0x00000020,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has TIFF image data.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TIFF = 0x00000040,
|
||||
|
||||
/// <summary>
|
||||
/// The glyph has raw 32-bit premultiplied BGRA data.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8 = 0x00000080,
|
||||
};
|
||||
|
||||
#ifdef DEFINE_ENUM_FLAG_OPERATORS
|
||||
DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a color glyph run. The IDWriteFactory4::TranslateColorGlyphRun
|
||||
/// method returns an ordered collection of color glyph runs of varying types
|
||||
/// depending on what the font supports.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// For runs without any specific color, such as PNG data, the runColor field will be zero.
|
||||
/// </summary>
|
||||
struct DWRITE_COLOR_GLYPH_RUN1 : DWRITE_COLOR_GLYPH_RUN
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of glyph image format for this color run. Exactly one type will be set since
|
||||
/// TranslateColorGlyphRun has already broken down the run into separate parts.
|
||||
/// </summary>
|
||||
DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat;
|
||||
|
||||
/// <summary>
|
||||
/// Measuring mode to use for this glyph run.
|
||||
/// </summary>
|
||||
DWRITE_MEASURING_MODE measuringMode;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Data for a single glyph from GetGlyphImageData.
|
||||
/// </summary>
|
||||
struct DWRITE_GLYPH_IMAGE_DATA
|
||||
{
|
||||
/// <summary>
|
||||
/// Pointer to the glyph data, be it SVG, PNG, JPEG, TIFF.
|
||||
/// </summary>
|
||||
_Field_size_bytes_(imageDataSize) void const* imageData;
|
||||
|
||||
/// <summary>
|
||||
/// Size of glyph data in bytes.
|
||||
/// </summary>
|
||||
UINT32 imageDataSize;
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier for the glyph data. Clients may use this to cache a parsed/decompressed
|
||||
/// version and tell whether a repeated call to the same font returns the same data.
|
||||
/// </summary>
|
||||
UINT32 uniqueDataId;
|
||||
|
||||
/// <summary>
|
||||
/// Pixels per em of the returned data. For non-scalable raster data (PNG/TIFF/JPG), this can be larger
|
||||
/// or smaller than requested from GetGlyphImageData when there isn't an exact match.
|
||||
/// For scaling intermediate sizes, use: desired pixels per em * font em size / actual pixels per em.
|
||||
/// </summary>
|
||||
UINT32 pixelsPerEm;
|
||||
|
||||
/// <summary>
|
||||
/// Size of image when the format is pixel data.
|
||||
/// </summary>
|
||||
D2D1_SIZE_U pixelSize;
|
||||
|
||||
/// <summary>
|
||||
/// Left origin along the horizontal Roman baseline.
|
||||
/// </summary>
|
||||
D2D1_POINT_2L horizontalLeftOrigin;
|
||||
|
||||
/// <summary>
|
||||
/// Right origin along the horizontal Roman baseline.
|
||||
/// </summary>
|
||||
D2D1_POINT_2L horizontalRightOrigin;
|
||||
|
||||
/// <summary>
|
||||
/// Top origin along the vertical central baseline.
|
||||
/// </summary>
|
||||
D2D1_POINT_2L verticalTopOrigin;
|
||||
|
||||
/// <summary>
|
||||
/// Bottom origin along vertical central baseline.
|
||||
/// </summary>
|
||||
D2D1_POINT_2L verticalBottomOrigin;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enumerator for an ordered collection of color glyph runs.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("7C5F86DA-C7A1-4F05-B8E1-55A179FE5A35") IDWriteColorGlyphRunEnumerator1 : public IDWriteColorGlyphRunEnumerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the current color glyph run.
|
||||
/// </summary>
|
||||
/// <param name="colorGlyphRun">Receives a pointer to the color
|
||||
/// glyph run. The pointer remains valid until the next call to
|
||||
/// MoveNext or until the interface is released.</param>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code. An error is returned if there is
|
||||
/// no current glyph run, i.e., if MoveNext has not yet been called
|
||||
/// or if the end of the sequence has been reached.
|
||||
/// </returns>
|
||||
STDMETHOD(GetCurrentRun)(
|
||||
_Outptr_ DWRITE_COLOR_GLYPH_RUN1 const** colorGlyphRun
|
||||
) PURE;
|
||||
|
||||
using IDWriteColorGlyphRunEnumerator::GetCurrentRun;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The interface that represents an absolute reference to a font face.
|
||||
/// It contains font face type, appropriate file references and face identification data.
|
||||
/// Various font data such as metrics, names and glyph outlines is obtained from IDWriteFontFace.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("27F2A904-4EB8-441D-9678-0563F53E3E2F") IDWriteFontFace4 : public IDWriteFontFace3
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all the glyph image formats supported by the entire font (SVG, PNG, JPEG, ...).
|
||||
/// </summary>
|
||||
STDMETHOD_(DWRITE_GLYPH_IMAGE_FORMATS, GetGlyphImageFormats)() PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available image formats of a specific glyph and ppem. Glyphs often have at least TrueType
|
||||
/// or CFF outlines, but they may also have SVG outlines, or they may have only bitmaps
|
||||
/// with no TrueType/CFF outlines. Some image formats, notably the PNG/JPEG ones, are size
|
||||
/// specific and will return no match when there isn't an entry in that size range.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Glyph ids beyond the glyph count return DWRITE_GLYPH_IMAGE_FORMATS_NONE.
|
||||
/// </remarks>
|
||||
STDMETHOD(GetGlyphImageFormats)(
|
||||
UINT16 glyphId,
|
||||
UINT32 pixelsPerEmFirst,
|
||||
UINT32 pixelsPerEmLast,
|
||||
_Out_ DWRITE_GLYPH_IMAGE_FORMATS* glyphImageFormats
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the glyph data based on the desired image format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The glyphDataContext must be released via ReleaseGlyphImageData when done if the data is not empty,
|
||||
/// similar to IDWriteFontFileStream::ReadFileFragment and IDWriteFontFileStream::ReleaseFileFragment.
|
||||
/// The data pointer is valid so long as the IDWriteFontFace exists and ReleaseGlyphImageData has not
|
||||
/// been called.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// The DWRITE_GLYPH_IMAGE_DATA::uniqueDataId is valuable for caching purposes so that if the same
|
||||
/// resource is returned more than once, an existing resource can be quickly retrieved rather than
|
||||
/// needing to reparse or decompress the data.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// The function only returns SVG or raster data - requesting TrueType/CFF/COLR data returns
|
||||
/// DWRITE_E_INVALIDARG. Those must be drawn via DrawGlyphRun or queried using GetGlyphOutline instead.
|
||||
/// Exactly one format may be requested or else the function returns DWRITE_E_INVALIDARG.
|
||||
/// If the glyph does not have that format, the call is not an error, but the function returns empty data.
|
||||
/// </remarks>
|
||||
STDMETHOD(GetGlyphImageData)(
|
||||
_In_ UINT16 glyphId,
|
||||
UINT32 pixelsPerEm,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat,
|
||||
_Out_ DWRITE_GLYPH_IMAGE_DATA* glyphData,
|
||||
_Outptr_result_maybenull_ void** glyphDataContext
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Releases the table data obtained earlier from ReadGlyphData.
|
||||
/// </summary>
|
||||
/// <param name="glyphDataContext">Opaque context from ReadGlyphData.</param>
|
||||
STDMETHOD_(void, ReleaseGlyphImageData)(
|
||||
void* glyphDataContext
|
||||
) PURE;
|
||||
};
|
||||
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("4B0B5BD3-0797-4549-8AC5-FE915CC53856") IDWriteFactory4 : public IDWriteFactory3
|
||||
{
|
||||
/// <summary>
|
||||
/// Translates a glyph run to a sequence of color glyph runs, which can be
|
||||
/// rendered to produce a color representation of the original "base" run.
|
||||
/// </summary>
|
||||
/// <param name="baselineOriginX">Horizontal and vertical origin of the base glyph run in
|
||||
/// pre-transform coordinates.</param>
|
||||
/// <param name="glyphRun">Pointer to the original "base" glyph run.</param>
|
||||
/// <param name="glyphRunDescription">Optional glyph run description.</param>
|
||||
/// <param name="glyphImageFormats">Which data formats TranslateColorGlyphRun
|
||||
/// should split the runs into.</param>
|
||||
/// <param name="measuringMode">Measuring mode, needed to compute the origins
|
||||
/// of each glyph.</param>
|
||||
/// <param name="worldToDeviceTransform">Matrix converting from the client's
|
||||
/// coordinate space to device coordinates (pixels), i.e., the world transform
|
||||
/// multiplied by any DPI scaling.</param>
|
||||
/// <param name="colorPaletteIndex">Zero-based index of the color palette to use.
|
||||
/// Valid indices are less than the number of palettes in the font, as returned
|
||||
/// by IDWriteFontFace2::GetColorPaletteCount.</param>
|
||||
/// <param name="colorLayers">If the function succeeds, receives a pointer
|
||||
/// to an enumerator object that can be used to obtain the color glyph runs.
|
||||
/// If the base run has no color glyphs, then the output pointer is NULL
|
||||
/// and the method returns DWRITE_E_NOCOLOR.</param>
|
||||
/// <returns>
|
||||
/// Returns DWRITE_E_NOCOLOR if the font has no color information, the glyph run
|
||||
/// does not contain any color glyphs, or the specified color palette index
|
||||
/// is out of range. In this case, the client should render the original glyph
|
||||
/// run. Otherwise, returns a standard HRESULT error code.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The old IDWriteFactory2::TranslateColorGlyphRun is equivalent to passing
|
||||
/// DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE|CFF|COLR.
|
||||
/// </remarks>
|
||||
STDMETHOD(TranslateColorGlyphRun)(
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
_In_ DWRITE_GLYPH_RUN const* glyphRun,
|
||||
_In_opt_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS desiredGlyphImageFormats,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
_In_opt_ DWRITE_MATRIX const* worldAndDpiTransform,
|
||||
UINT32 colorPaletteIndex,
|
||||
_COM_Outptr_ IDWriteColorGlyphRunEnumerator1** colorLayers
|
||||
) PURE;
|
||||
|
||||
using IDWriteFactory2::TranslateColorGlyphRun;
|
||||
|
||||
/// <summary>
|
||||
/// Converts glyph run placements to glyph origins.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Standard HRESULT error code.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The transform and DPI have no affect on the origin scaling.
|
||||
/// They are solely used to compute glyph advances when not supplied
|
||||
/// and align glyphs in pixel aligned measuring modes.
|
||||
/// </remarks>
|
||||
STDMETHOD(ComputeGlyphOrigins)(
|
||||
DWRITE_GLYPH_RUN const* glyphRun,
|
||||
DWRITE_MEASURING_MODE measuringMode,
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
_In_opt_ DWRITE_MATRIX const* worldAndDpiTransform,
|
||||
_Out_writes_(glyphRun->glyphCount) D2D1_POINT_2F* glyphOrigins
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Converts glyph run placements to glyph origins. This overload is for natural metrics, which
|
||||
/// includes SVG, TrueType natural modes, and bitmap placement.
|
||||
/// </summary>
|
||||
STDMETHOD(ComputeGlyphOrigins)(
|
||||
DWRITE_GLYPH_RUN const* glyphRun,
|
||||
D2D1_POINT_2F baselineOrigin,
|
||||
_Out_writes_(glyphRun->glyphCount) D2D1_POINT_2F* glyphOrigins
|
||||
) PURE;
|
||||
};
|
||||
|
||||
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
#endif // DWRITE_3_H_INCLUDED
|
||||
|
||||
Vendored
+4
-2
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -273,7 +273,8 @@ enum DXGI_SWAP_CHAIN_FLAG
|
||||
DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER = 128,
|
||||
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_HW_PROTECTED = 1024,
|
||||
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING = 2048
|
||||
} DXGI_SWAP_CHAIN_FLAG;
|
||||
|
||||
typedef struct DXGI_SWAP_CHAIN_DESC
|
||||
@@ -1684,6 +1685,7 @@ EXTERN_C const IID IID_IDXGIOutput;
|
||||
#define DXGI_PRESENT_STEREO_TEMPORARY_MONO 0x00000020UL
|
||||
#define DXGI_PRESENT_RESTRICT_TO_OUTPUT 0x00000040UL
|
||||
#define DXGI_PRESENT_USE_DURATION 0x00000100UL
|
||||
#define DXGI_PRESENT_ALLOW_TEARING 0x00000200UL
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi_0000_0008_v0_0_c_ifspec;
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1533
File diff suppressed because it is too large
Load Diff
Vendored
+6
@@ -119,6 +119,12 @@ typedef enum DXGI_COLOR_SPACE_TYPE
|
||||
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;
|
||||
|
||||
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
sdkddkver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Master include file for versioning windows SDK/DDK.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_SDKDDKVER
|
||||
#define _INC_SDKDDKVER
|
||||
|
||||
#if (_MSC_VER >= 800)
|
||||
#if (_MSC_VER >= 1200)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4668) /* #if not_defined treated as #if 0 */
|
||||
#endif
|
||||
#pragma warning(disable:4001) /* nonstandard extension : single line comment */
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// _WIN32_WINNT version constants
|
||||
//
|
||||
#define _WIN32_WINNT_NT4 0x0400
|
||||
#define _WIN32_WINNT_WIN2K 0x0500
|
||||
#define _WIN32_WINNT_WINXP 0x0501
|
||||
#define _WIN32_WINNT_WS03 0x0502
|
||||
#define _WIN32_WINNT_WIN6 0x0600
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#define _WIN32_WINNT_WS08 0x0600
|
||||
#define _WIN32_WINNT_LONGHORN 0x0600
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||
#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* ABRACADABRA_THRESHOLD*/
|
||||
#define _WIN32_WINNT_WIN10 0x0A00 /* ABRACADABRA_THRESHOLD*/
|
||||
|
||||
//
|
||||
// _WIN32_IE_ version constants
|
||||
//
|
||||
#define _WIN32_IE_IE20 0x0200
|
||||
#define _WIN32_IE_IE30 0x0300
|
||||
#define _WIN32_IE_IE302 0x0302
|
||||
#define _WIN32_IE_IE40 0x0400
|
||||
#define _WIN32_IE_IE401 0x0401
|
||||
#define _WIN32_IE_IE50 0x0500
|
||||
#define _WIN32_IE_IE501 0x0501
|
||||
#define _WIN32_IE_IE55 0x0550
|
||||
#define _WIN32_IE_IE60 0x0600
|
||||
#define _WIN32_IE_IE60SP1 0x0601
|
||||
#define _WIN32_IE_IE60SP2 0x0603
|
||||
#define _WIN32_IE_IE70 0x0700
|
||||
#define _WIN32_IE_IE80 0x0800
|
||||
#define _WIN32_IE_IE90 0x0900
|
||||
#define _WIN32_IE_IE100 0x0A00
|
||||
#define _WIN32_IE_IE110 0x0A00 /* ABRACADABRA_THRESHOLD */
|
||||
|
||||
//
|
||||
// IE <-> OS version mapping
|
||||
//
|
||||
// NT4 supports IE versions 2.0 -> 6.0 SP1
|
||||
#define _WIN32_IE_NT4 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP1 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP2 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP3 _WIN32_IE_IE302
|
||||
#define _WIN32_IE_NT4SP4 _WIN32_IE_IE401
|
||||
#define _WIN32_IE_NT4SP5 _WIN32_IE_IE401
|
||||
#define _WIN32_IE_NT4SP6 _WIN32_IE_IE50
|
||||
// Win98 supports IE versions 4.01 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN98 _WIN32_IE_IE401
|
||||
// Win98SE supports IE versions 5.0 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN98SE _WIN32_IE_IE50
|
||||
// WinME supports IE versions 5.5 -> 6.0 SP1
|
||||
#define _WIN32_IE_WINME _WIN32_IE_IE55
|
||||
// Win2k supports IE versions 5.01 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN2K _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP1 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP2 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP3 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP4 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_XP _WIN32_IE_IE60
|
||||
#define _WIN32_IE_XPSP1 _WIN32_IE_IE60SP1
|
||||
#define _WIN32_IE_XPSP2 _WIN32_IE_IE60SP2
|
||||
#define _WIN32_IE_WS03 0x0602
|
||||
#define _WIN32_IE_WS03SP1 _WIN32_IE_IE60SP2
|
||||
#define _WIN32_IE_WIN6 _WIN32_IE_IE70
|
||||
#define _WIN32_IE_LONGHORN _WIN32_IE_IE70
|
||||
#define _WIN32_IE_WIN7 _WIN32_IE_IE80
|
||||
#define _WIN32_IE_WIN8 _WIN32_IE_IE100
|
||||
#define _WIN32_IE_WINBLUE _WIN32_IE_IE100
|
||||
#define _WIN32_IE_WINTHRESHOLD _WIN32_IE_IE110 /* ABRACADABRA_THRESHOLD */
|
||||
#define _WIN32_IE_WIN10 _WIN32_IE_IE110 /* ABRACADABRA_THRESHOLD */
|
||||
|
||||
|
||||
//
|
||||
// NTDDI version constants
|
||||
//
|
||||
#define NTDDI_WIN2K 0x05000000
|
||||
#define NTDDI_WIN2KSP1 0x05000100
|
||||
#define NTDDI_WIN2KSP2 0x05000200
|
||||
#define NTDDI_WIN2KSP3 0x05000300
|
||||
#define NTDDI_WIN2KSP4 0x05000400
|
||||
|
||||
#define NTDDI_WINXP 0x05010000
|
||||
#define NTDDI_WINXPSP1 0x05010100
|
||||
#define NTDDI_WINXPSP2 0x05010200
|
||||
#define NTDDI_WINXPSP3 0x05010300
|
||||
#define NTDDI_WINXPSP4 0x05010400
|
||||
|
||||
#define NTDDI_WS03 0x05020000
|
||||
#define NTDDI_WS03SP1 0x05020100
|
||||
#define NTDDI_WS03SP2 0x05020200
|
||||
#define NTDDI_WS03SP3 0x05020300
|
||||
#define NTDDI_WS03SP4 0x05020400
|
||||
|
||||
#define NTDDI_WIN6 0x06000000
|
||||
#define NTDDI_WIN6SP1 0x06000100
|
||||
#define NTDDI_WIN6SP2 0x06000200
|
||||
#define NTDDI_WIN6SP3 0x06000300
|
||||
#define NTDDI_WIN6SP4 0x06000400
|
||||
|
||||
#define NTDDI_VISTA NTDDI_WIN6
|
||||
#define NTDDI_VISTASP1 NTDDI_WIN6SP1
|
||||
#define NTDDI_VISTASP2 NTDDI_WIN6SP2
|
||||
#define NTDDI_VISTASP3 NTDDI_WIN6SP3
|
||||
#define NTDDI_VISTASP4 NTDDI_WIN6SP4
|
||||
|
||||
#define NTDDI_LONGHORN NTDDI_VISTA
|
||||
|
||||
#define NTDDI_WS08 NTDDI_WIN6SP1
|
||||
#define NTDDI_WS08SP2 NTDDI_WIN6SP2
|
||||
#define NTDDI_WS08SP3 NTDDI_WIN6SP3
|
||||
#define NTDDI_WS08SP4 NTDDI_WIN6SP4
|
||||
|
||||
#define NTDDI_WIN7 0x06010000
|
||||
#define NTDDI_WIN8 0x06020000
|
||||
#define NTDDI_WINBLUE 0x06030000
|
||||
#define NTDDI_WINTHRESHOLD 0x0A000000 /* ABRACADABRA_THRESHOLD */
|
||||
#define NTDDI_WIN10 0x0A000000 /* ABRACADABRA_THRESHOLD */
|
||||
#define NTDDI_WIN10_TH2 0x0A000001 /* ABRACADABRA_WIN10_TH2 */
|
||||
#define NTDDI_WIN10_RS1 0x0A000002 /* ABRACADABRA_WIN10_RS1 */
|
||||
|
||||
//
|
||||
// masks for version macros
|
||||
//
|
||||
#define OSVERSION_MASK 0xFFFF0000
|
||||
#define SPVERSION_MASK 0x0000FF00
|
||||
#define SUBVERSION_MASK 0x000000FF
|
||||
|
||||
|
||||
//
|
||||
// macros to extract various version fields from the NTDDI version
|
||||
//
|
||||
#define OSVER(Version) ((Version) & OSVERSION_MASK)
|
||||
#define SPVER(Version) (((Version) & SPVERSION_MASK) >> 8)
|
||||
#define SUBVER(Version) (((Version) & SUBVERSION_MASK) )
|
||||
|
||||
|
||||
#if defined(DECLSPEC_DEPRECATED_DDK)
|
||||
|
||||
// deprecate in 2k or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN2K)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2K DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2K
|
||||
#endif
|
||||
|
||||
// deprecate in XP or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WINXP)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WINXP DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WINXP
|
||||
#endif
|
||||
|
||||
// deprecate in WS03 or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WS03)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2003 DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2003
|
||||
#endif
|
||||
|
||||
// deprecate in WIN6 or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN6)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN6 DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN6
|
||||
#endif
|
||||
|
||||
#define DECLSPEC_DEPRECATED_DDK_LONGHORN DECLSPEC_DEPRECATED_DDK_WIN6
|
||||
|
||||
#endif // defined(DECLSPEC_DEPRECATED_DDK)
|
||||
|
||||
|
||||
//
|
||||
// if versions aren't already defined, default to most current
|
||||
//
|
||||
|
||||
#define NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
|
||||
#define NTDDI_VERSION_FROM_WIN32_WINNT(ver) NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
|
||||
|
||||
#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
|
||||
#define _WIN32_WINNT 0x0A00
|
||||
#endif
|
||||
|
||||
#ifndef NTDDI_VERSION
|
||||
#ifdef _WIN32_WINNT
|
||||
// set NTDDI_VERSION based on _WIN32_WINNT
|
||||
#define NTDDI_VERSION NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
|
||||
#else
|
||||
#define NTDDI_VERSION 0x0A000002
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
#ifdef _WIN32_WINNT
|
||||
// set WINVER based on _WIN32_WINNT
|
||||
#define WINVER _WIN32_WINNT
|
||||
#else
|
||||
#define WINVER 0x0A00
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE
|
||||
#ifdef _WIN32_WINNT
|
||||
// set _WIN32_IE based on _WIN32_WINNT
|
||||
#if (_WIN32_WINNT <= _WIN32_WINNT_NT4)
|
||||
#define _WIN32_IE _WIN32_IE_IE50
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
|
||||
#define _WIN32_IE _WIN32_IE_IE501
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WINXP)
|
||||
#define _WIN32_IE _WIN32_IE_IE60
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WS03)
|
||||
#define _WIN32_IE _WIN32_IE_WS03
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_VISTA)
|
||||
#define _WIN32_IE _WIN32_IE_LONGHORN
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN7)
|
||||
#define _WIN32_IE _WIN32_IE_WIN7
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN8)
|
||||
#define _WIN32_IE _WIN32_IE_WIN8
|
||||
#else
|
||||
#define _WIN32_IE 0x0A00
|
||||
#endif
|
||||
#else
|
||||
#define _WIN32_IE 0x0A00
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Sanity check for compatible versions
|
||||
//
|
||||
#if defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(RC_INVOKED)
|
||||
|
||||
#if (defined(WINVER) && (WINVER < 0x0400) && (_WIN32_WINNT > 0x0400))
|
||||
#error WINVER setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WIN2K) && (_WIN32_WINNT != _WIN32_WINNT_WIN2K))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WINXP) && (_WIN32_WINNT != _WIN32_WINNT_WINXP))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WS03) && (_WIN32_WINNT != _WIN32_WINNT_WS03))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_VISTA) && (_WIN32_WINNT != _WIN32_WINNT_VISTA))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if ((_WIN32_WINNT < _WIN32_WINNT_WIN2K) && (_WIN32_IE > _WIN32_IE_IE60SP1))
|
||||
#error _WIN32_WINNT settings conflicts with _WIN32_IE setting
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(_WINRESRC_)
|
||||
|
||||
#if (_MSC_VER >= 800)
|
||||
#if (_MSC_VER >= 1200)
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#pragma warning(default:4001) /* nonstandard extension : single line comment */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_SDKDDKVER */
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+1
-1
Submodule 3rdparty/pugixml updated: 257fbb4e1b...f205aaf6e1
Vendored
-1
Submodule 3rdparty/zlib deleted from cacf7f1d4e
+8
-27
@@ -1,11 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
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,104 +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 2015](https://www.visualstudio.com/vs/older-downloads/)
|
||||
__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+](https://www.cmake.org/download/) (required; add to PATH)
|
||||
* [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.8+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.8\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.7+](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 libpulse-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 glew glew-devel libatomic libudev-devel openal-devel qt5-devel vulkan-devel`
|
||||
* OpenSUSE: `sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libevdev-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.8\msvc2015_64\` </br>
|
||||
|
||||
|
||||
Open `rpcs3.sln`
|
||||
|
||||
|
||||
*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.8\msvc2015_64`. </br>
|
||||
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
### Building the projects
|
||||
You may want to download precompiled [LLVM lib](https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8) and extract to root rpcs3 folder (which contains `rpcs3.sln`), as well as download and extract [additional libs](https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U) to `lib\%CONFIGURATION%-x64\` to speed up compilation time (unoptimised/debug libs are currently not available precompiled).
|
||||
|
||||
If you're not using precompiled libs, build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*. </br></br>
|
||||
|
||||
`Build > Build 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) `cd ../ && mkdir rpcs3_build && cd rpcs3_build`
|
||||
4) `cmake ../rpcs3/ && make GitVersion && make` </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);
|
||||
};
|
||||
}
|
||||
+1
-11
@@ -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));
|
||||
@@ -470,7 +460,7 @@ struct se_storage<T, 16, 16>
|
||||
|
||||
static inline v128 swap(const v128& src)
|
||||
{
|
||||
return v128::from64(se_storage<u64>::swap(src._u64[1]), se_storage<u64>::swap(src._u64[0]));
|
||||
return v128::fromV(_mm_shuffle_epi8(src.vi, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)));
|
||||
}
|
||||
|
||||
static inline v128 to(const T& src)
|
||||
|
||||
+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
+51
-125
@@ -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,28 +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;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out << rhs.to_string();
|
||||
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())
|
||||
{
|
||||
@@ -226,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
|
||||
{
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,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;
|
||||
@@ -290,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()
|
||||
{
|
||||
@@ -312,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;
|
||||
}
|
||||
|
||||
+232
-90
@@ -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,61 +117,163 @@ 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:
|
||||
bool def;
|
||||
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;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void set(const bool& value)
|
||||
// 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
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_value = value;
|
||||
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>
|
||||
class _enum final : public _base
|
||||
template<typename T, bool External = false>
|
||||
class enum_entry final : public entry_base
|
||||
{
|
||||
T m_value;
|
||||
// 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)
|
||||
{
|
||||
@@ -175,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
|
||||
@@ -211,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:
|
||||
int_type def;
|
||||
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)
|
||||
{
|
||||
@@ -233,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
|
||||
@@ -243,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
|
||||
@@ -257,34 +380,25 @@ namespace cfg
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void set(const s64& value)
|
||||
{
|
||||
m_value = static_cast<int_type>(value);
|
||||
}
|
||||
|
||||
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:
|
||||
std::string def;
|
||||
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)
|
||||
{
|
||||
@@ -292,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); }
|
||||
|
||||
+113
-314
@@ -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,46 +69,17 @@ static time_t to_time(const FILETIME& ft)
|
||||
return to_time(v);
|
||||
}
|
||||
|
||||
static FILETIME from_time(s64 _time)
|
||||
{
|
||||
FILETIME result;
|
||||
|
||||
if (_time <= -11644473600ll)
|
||||
{
|
||||
result.dwLowDateTime = 0;
|
||||
result.dwHighDateTime = 0;
|
||||
}
|
||||
else if (_time > INT64_MAX / 10000000ll - 11644473600ll)
|
||||
{
|
||||
result.dwLowDateTime = 0xffffffff;
|
||||
result.dwHighDateTime = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ullong wtime = (_time + 11644473600ull) * 10000000ull;
|
||||
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;
|
||||
case ERROR_NOT_READY: return fs::error::noent;
|
||||
//case ERROR_INVALID_PARAMETER: return fs::error::inval;
|
||||
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
@@ -122,21 +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 <sys/file.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
|
||||
|
||||
@@ -147,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);
|
||||
}
|
||||
}
|
||||
@@ -176,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)
|
||||
@@ -428,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))
|
||||
@@ -531,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);
|
||||
|
||||
@@ -546,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);
|
||||
@@ -631,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;
|
||||
@@ -696,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);
|
||||
@@ -726,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");
|
||||
@@ -778,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
|
||||
@@ -808,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;
|
||||
|
||||
@@ -859,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;
|
||||
}
|
||||
|
||||
@@ -911,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;
|
||||
}
|
||||
@@ -927,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);
|
||||
@@ -952,17 +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;
|
||||
}
|
||||
|
||||
if (test(mode & fs::unshare) && ::flock(fd, LOCK_EX | LOCK_NB) != 0)
|
||||
{
|
||||
g_tls_error = errno == EWOULDBLOCK ? fs::error::acces : to_error(errno);
|
||||
::close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
class unix_file final : public file_base, public get_native_handle
|
||||
class unix_file final : public file_base
|
||||
{
|
||||
const int m_fd;
|
||||
|
||||
@@ -993,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)
|
||||
@@ -1034,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;
|
||||
}
|
||||
@@ -1051,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)
|
||||
@@ -1078,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
|
||||
@@ -1131,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");
|
||||
@@ -1258,12 +1025,7 @@ bool fs::dir::open(const std::string& path)
|
||||
}
|
||||
|
||||
struct ::stat file_info;
|
||||
|
||||
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
|
||||
{
|
||||
//failed metadata (broken symlink?), ignore and skip to next file
|
||||
return read(info);
|
||||
}
|
||||
verify("dir::read" HERE), ::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) == 0;
|
||||
|
||||
info.name = found->d_name;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -1293,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"))
|
||||
@@ -1321,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;
|
||||
}();
|
||||
|
||||
@@ -1334,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))
|
||||
{
|
||||
@@ -1363,7 +1164,7 @@ std::string fs::get_data_dir(const std::string& prefix, const std::string& locat
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
buf.push_back(c);
|
||||
}
|
||||
|
||||
@@ -1481,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;
|
||||
|
||||
+22
-182
@@ -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
|
||||
@@ -422,7 +377,7 @@ namespace fs
|
||||
|
||||
class iterator
|
||||
{
|
||||
const dir* m_parent;
|
||||
dir* m_parent;
|
||||
dir_entry m_entry;
|
||||
|
||||
public:
|
||||
@@ -432,7 +387,7 @@ namespace fs
|
||||
from_current
|
||||
};
|
||||
|
||||
iterator(const dir* parent, mode mode_ = mode::from_first)
|
||||
iterator(dir* parent, mode mode_ = mode::from_first)
|
||||
: m_parent(parent)
|
||||
{
|
||||
if (!m_parent)
|
||||
@@ -458,7 +413,7 @@ namespace fs
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
*this = {m_parent, mode::from_current};
|
||||
*this = { m_parent, mode::from_current };
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -468,20 +423,23 @@ namespace fs
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin() const
|
||||
iterator begin()
|
||||
{
|
||||
return {m_dir ? this : nullptr};
|
||||
return{ m_dir ? this : nullptr };
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
iterator end()
|
||||
{
|
||||
return {nullptr};
|
||||
return{ nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
+199
-386
@@ -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,7 +19,6 @@
|
||||
#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
|
||||
@@ -32,12 +27,16 @@
|
||||
#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;
|
||||
@@ -45,92 +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();
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
auto ptr = ::mmap(nullptr, s_memory_size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, 0);
|
||||
if (ptr != MAP_FAILED)
|
||||
return ptr;
|
||||
#else
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
#else
|
||||
static std::deque<std::tuple<u8*, u64, std::size_t>> s_unfire;
|
||||
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
|
||||
struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
{
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} mem;
|
||||
|
||||
for (auto&& t : s_unfire)
|
||||
{
|
||||
mem.deregisterEHFrames(std::get<0>(t), std::get<1>(t), std::get<2>(t));
|
||||
}
|
||||
|
||||
s_unfire.clear();
|
||||
#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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -139,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;
|
||||
}
|
||||
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
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)
|
||||
{
|
||||
@@ -210,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);
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
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)
|
||||
{
|
||||
@@ -236,297 +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);
|
||||
}
|
||||
|
||||
bool finalizeMemory(std::string* = nullptr) override
|
||||
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;
|
||||
}
|
||||
|
||||
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
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));
|
||||
}
|
||||
#else
|
||||
s_unfire.push_front(std::make_tuple(addr, load_addr, size));
|
||||
#endif
|
||||
s_unwind_info = addr;
|
||||
s_unwind_size = size;
|
||||
|
||||
return RTDyldMemoryManager::registerEHFrames(addr, load_addr, size);
|
||||
}
|
||||
|
||||
void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
virtual void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
}
|
||||
};
|
||||
LOG_ERROR(GENERAL, "deregisterEHFrames() called"); // Not expected
|
||||
|
||||
// Helper class
|
||||
struct EventListener : llvm::JITEventListener
|
||||
{
|
||||
MemoryManager& m_mem;
|
||||
|
||||
EventListener(MemoryManager& mem)
|
||||
: m_mem(mem)
|
||||
{
|
||||
return RTDyldMemoryManager::deregisterEHFrames(addr, load_addr, size);
|
||||
}
|
||||
|
||||
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(_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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -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
|
||||
+36
-490
@@ -1,34 +1,12 @@
|
||||
#include "Log.h"
|
||||
#include "File.h"
|
||||
#include "StrFmt.h"
|
||||
#include "sema.h"
|
||||
|
||||
#include "Utilities/sysinfo.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "rpcs3_version.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#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)
|
||||
@@ -45,7 +23,6 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
case logs::level::warning: return "Warning";
|
||||
case logs::level::notice: return "Notice";
|
||||
case logs::level::trace: return "Trace";
|
||||
case logs::level::_uninit: return unknown;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
@@ -54,168 +31,49 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
|
||||
namespace logs
|
||||
{
|
||||
// Memory-mapped buffer size
|
||||
constexpr u64 s_log_size = 32 * 1024 * 1024;
|
||||
|
||||
class file_writer
|
||||
{
|
||||
// Could be memory-mapped file
|
||||
fs::file m_file;
|
||||
std::string m_name;
|
||||
std::thread m_writer;
|
||||
fs::file m_fout;
|
||||
fs::file m_fout2;
|
||||
u64 m_max_size;
|
||||
|
||||
#ifdef _WIN32
|
||||
::HANDLE m_fmap;
|
||||
#endif
|
||||
uchar* m_fptr{};
|
||||
z_stream m_zs{};
|
||||
semaphore<> m_m;
|
||||
|
||||
alignas(128) atomic_t<u64> m_buf{0}; // MSB (40 bit): push begin, LSB (24 bis): push size
|
||||
alignas(128) atomic_t<u64> m_out{0}; // Amount of bytes written to file
|
||||
|
||||
uchar m_zout[65536];
|
||||
|
||||
// Write buffered logs immediately
|
||||
bool flush(u64 bufv);
|
||||
|
||||
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()
|
||||
{
|
||||
// Use magic static
|
||||
static file_listener logger("RPCS3");
|
||||
static file_listener logger("RPCS3.log");
|
||||
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)
|
||||
@@ -223,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;
|
||||
}
|
||||
}
|
||||
@@ -303,280 +107,28 @@ 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)
|
||||
{
|
||||
const std::string log_name = fs::get_config_dir() + name + ".log";
|
||||
const std::string buf_name = fs::get_config_dir() + name + ".buf";
|
||||
|
||||
try
|
||||
{
|
||||
if (!m_file.open(buf_name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
|
||||
{
|
||||
if (fs::g_tls_error == fs::error::acces)
|
||||
{
|
||||
if (fs::exists(buf_name))
|
||||
{
|
||||
fmt::throw_exception("Another instance of %s is running. Close it or kill its process, if necessary.", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Cannot create %s.log (access denied)."
|
||||
#ifdef _WIN32
|
||||
"\nNote that %s cannot be installed in Program Files or similar directory with limited permissions."
|
||||
#else
|
||||
"\nPlease, check %s permissions in '~/.config/'."
|
||||
#endif
|
||||
, name, name);
|
||||
}
|
||||
}
|
||||
|
||||
fmt::throw_exception("Cannot create %s.log (error %s)", name, fs::g_tls_error);
|
||||
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
|
||||
}
|
||||
|
||||
// Check free space
|
||||
fs::device_stat stats{};
|
||||
if (!fs::statfs(fs::get_config_dir(), stats) || stats.avail_free < s_log_size * 8)
|
||||
{
|
||||
fmt::throw_exception("Not enough free space (%f KB)", stats.avail_free / 1000000.);
|
||||
}
|
||||
|
||||
// Limit log size to ~25% of free space
|
||||
m_max_size = stats.avail_free / 4;
|
||||
|
||||
// Initialize memory mapped file
|
||||
#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;
|
||||
|
||||
// Rotate backups (TODO)
|
||||
fs::remove_file(fs::get_config_dir() + name + "1.log.gz");
|
||||
fs::create_dir(fs::get_config_dir() + "old_logs");
|
||||
fs::rename(fs::get_config_dir() + m_name + ".log.gz", fs::get_config_dir() + "old_logs/" + m_name + ".log.gz", true);
|
||||
|
||||
// Actual log file (allowed to fail)
|
||||
m_fout.open(log_name, fs::rewrite);
|
||||
|
||||
// Compressed log
|
||||
if (!m_fout2.open(log_name + ".gz", fs::rewrite) || deflateInit2(&m_zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
{
|
||||
m_fout2.close();
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::thread([text = std::string{e.what()}]{ report_fatal_error(text); }).detach();
|
||||
return;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::thread([]{ report_fatal_error("Unknown error" HERE); }).detach();
|
||||
return;
|
||||
}
|
||||
|
||||
m_writer = std::thread([this]()
|
||||
{
|
||||
thread_ctrl::set_native_priority(-1);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const u64 bufv = m_buf;
|
||||
|
||||
if (bufv & 0xffffff)
|
||||
{
|
||||
// Wait if threads are writing logs
|
||||
std::this_thread::yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flush(bufv))
|
||||
{
|
||||
if (m_out == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logs::file_writer::~file_writer()
|
||||
{
|
||||
if (!m_fptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop writer thread
|
||||
while (m_out << 24 < m_buf)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
m_out = -1;
|
||||
m_writer.join();
|
||||
|
||||
if (m_fout2)
|
||||
{
|
||||
m_zs.avail_in = 0;
|
||||
m_zs.next_in = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
m_zs.avail_out = sizeof(m_zout);
|
||||
m_zs.next_out = m_zout;
|
||||
|
||||
if (deflate(&m_zs, Z_FINISH) == Z_STREAM_ERROR || m_fout2.write(m_zout, sizeof(m_zout) - m_zs.avail_out) != sizeof(m_zout) - m_zs.avail_out)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (m_zs.avail_out == 0);
|
||||
|
||||
deflateEnd(&m_zs);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile(m_fptr);
|
||||
CloseHandle(m_fmap);
|
||||
#else
|
||||
::munmap(m_fptr, s_log_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool logs::file_writer::flush(u64 bufv)
|
||||
{
|
||||
semaphore_lock lock(m_m);
|
||||
|
||||
const u64 st = +m_out;
|
||||
const u64 end = std::min<u64>((st + s_log_size) & ~(s_log_size - 1), bufv >> 24);
|
||||
|
||||
if (end > st)
|
||||
{
|
||||
// Avoid writing too big fragments
|
||||
const u64 size = std::min<u64>(end - st, sizeof(m_zout) / 2);
|
||||
|
||||
// Write uncompressed
|
||||
if (m_fout && st < m_max_size && m_fout.write(m_fptr + st % s_log_size, size) != size)
|
||||
{
|
||||
m_fout.close();
|
||||
}
|
||||
|
||||
// Write compressed
|
||||
if (m_fout2 && st < m_max_size)
|
||||
{
|
||||
m_zs.avail_in = size;
|
||||
m_zs.next_in = m_fptr + st % s_log_size;
|
||||
|
||||
do
|
||||
{
|
||||
m_zs.avail_out = sizeof(m_zout);
|
||||
m_zs.next_out = m_zout;
|
||||
|
||||
if (deflate(&m_zs, Z_NO_FLUSH) == Z_STREAM_ERROR || m_fout2.write(m_zout, sizeof(m_zout) - m_zs.avail_out) != sizeof(m_zout) - m_zs.avail_out)
|
||||
{
|
||||
deflateEnd(&m_zs);
|
||||
m_fout2.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (m_zs.avail_out == 0);
|
||||
}
|
||||
|
||||
m_out += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
|
||||
{
|
||||
if (!m_fptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: write bigger fragment directly in blocking manner
|
||||
while (size && size <= 0xffffff)
|
||||
{
|
||||
u64 bufv;
|
||||
|
||||
const auto pos = m_buf.atomic_op([&](u64& v) -> uchar*
|
||||
{
|
||||
const u64 v1 = v >> 24;
|
||||
const u64 v2 = v & 0xffffff;
|
||||
|
||||
if (UNLIKELY(v2 + size > 0xffffff || v1 + v2 + size >= m_out + s_log_size))
|
||||
{
|
||||
bufv = v;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v += size;
|
||||
return m_fptr + (v1 + v2) % s_log_size;
|
||||
});
|
||||
|
||||
if (UNLIKELY(!pos))
|
||||
{
|
||||
if ((bufv & 0xffffff) + size > 0xffffff || bufv & 0xffffff)
|
||||
{
|
||||
// Concurrency limit reached
|
||||
std::this_thread::yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Queue is full, need to write out
|
||||
flush(bufv);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pos + size > m_fptr + s_log_size)
|
||||
{
|
||||
const auto frag = m_fptr + s_log_size - pos;
|
||||
std::memcpy(pos, text, frag);
|
||||
std::memcpy(m_fptr, text + frag, size - frag);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(pos, text, size);
|
||||
}
|
||||
|
||||
m_buf += (u64{size} << 24) - size;
|
||||
break;
|
||||
catch_all_exceptions();
|
||||
}
|
||||
}
|
||||
|
||||
logs::file_listener::file_listener(const std::string& name)
|
||||
: file_writer(name)
|
||||
, listener()
|
||||
void logs::file_writer::log(const char* text, std::size_t size)
|
||||
{
|
||||
// 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));
|
||||
m_file.write(text, size);
|
||||
}
|
||||
|
||||
void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::string& prefix, const std::string& _text)
|
||||
void logs::file_listener::log(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)
|
||||
@@ -589,15 +141,9 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
case level::warning: text = u8"·W "; break;
|
||||
case level::notice: text = u8"·! "; break;
|
||||
case level::trace: text = u8"·T "; break;
|
||||
case level::_uninit: text = u8"· "; 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)
|
||||
{
|
||||
@@ -605,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: " : ": ";
|
||||
@@ -615,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>
|
||||
{
|
||||
|
||||
@@ -24,12 +24,6 @@ inline void strcpy_trunc(char (&dst)[N], const char (&src)[N2])
|
||||
dst[count] = '\0';
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
inline bool ends_with(const std::string& src, const char (&end)[N])
|
||||
{
|
||||
return src.size() >= N - 1 && src.compare(src.size() - (N - 1), N - 1, end, N - 1) == 0;
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
|
||||
|
||||
+851
-558
File diff suppressed because it is too large
Load Diff
+258
-108
@@ -7,32 +7,9 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "sema.h"
|
||||
#include "cond.h"
|
||||
|
||||
// Report error and call std::abort(), defined in main.cpp
|
||||
[[noreturn]] void report_fatal_error(const std::string&);
|
||||
|
||||
// Will report exception and call std::abort() if put in catch(...)
|
||||
[[noreturn]] void catch_all_exceptions();
|
||||
|
||||
// Hardware core layout
|
||||
enum class native_core_arrangement : u32
|
||||
{
|
||||
undefined,
|
||||
generic,
|
||||
intel_ht,
|
||||
amd_ccx
|
||||
};
|
||||
|
||||
enum class thread_class : u32
|
||||
{
|
||||
general,
|
||||
rsx,
|
||||
spu,
|
||||
ppu
|
||||
};
|
||||
|
||||
// Simple list of void() functors
|
||||
class task_stack
|
||||
{
|
||||
@@ -40,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;
|
||||
|
||||
@@ -61,10 +38,10 @@ class task_stack
|
||||
{
|
||||
}
|
||||
|
||||
void invoke() final override
|
||||
void exec() override
|
||||
{
|
||||
func();
|
||||
task_base::invoke();
|
||||
task_base::exec();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,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)))
|
||||
{
|
||||
@@ -93,11 +70,11 @@ public:
|
||||
m_stack.reset();
|
||||
}
|
||||
|
||||
void invoke() const
|
||||
void exec() const
|
||||
{
|
||||
if (m_stack)
|
||||
{
|
||||
m_stack->invoke();
|
||||
m_stack->exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -105,35 +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;
|
||||
|
||||
// Target cpu core layout
|
||||
static atomic_t<native_core_arrangement> g_native_core_layout;
|
||||
// Thread handle storage
|
||||
std::aligned_storage_t<16> m_thread;
|
||||
|
||||
// Self pointer
|
||||
std::shared_ptr<thread_ctrl> m_self;
|
||||
// Thread join contention counter
|
||||
atomic_t<u32> m_joining{};
|
||||
|
||||
// Thread handle (platform-specific)
|
||||
atomic_t<std::uintptr_t> m_thread{0};
|
||||
// Thread interrupt guard counter
|
||||
volatile u32 m_guard = 0x80000000;
|
||||
|
||||
// Thread mutex
|
||||
mutable semaphore<> m_mutex;
|
||||
|
||||
// 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;
|
||||
@@ -145,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);
|
||||
@@ -172,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()
|
||||
{
|
||||
@@ -233,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));
|
||||
}
|
||||
@@ -253,18 +340,6 @@ public:
|
||||
|
||||
thread_ctrl::start(out, std::forward<F>(func));
|
||||
}
|
||||
|
||||
// Detect layout
|
||||
static void detect_cpu_layout();
|
||||
|
||||
// Returns a core affinity mask. Set whether to generate the high priority set or not
|
||||
static u16 get_affinity_mask(thread_class group);
|
||||
|
||||
// Sets the native thread priority
|
||||
static void set_native_priority(int priority);
|
||||
|
||||
// Sets the preferred affinity mask for this thread
|
||||
static void set_thread_affinity_mask(u16 mask);
|
||||
};
|
||||
|
||||
class named_thread
|
||||
@@ -293,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)
|
||||
@@ -310,7 +382,7 @@ public:
|
||||
}
|
||||
|
||||
// Access thread_ctrl
|
||||
thread_ctrl* get() const
|
||||
thread_ctrl* operator->() const
|
||||
{
|
||||
return m_thread.get();
|
||||
}
|
||||
@@ -320,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
|
||||
{
|
||||
@@ -348,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,175 +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})
|
||||
{
|
||||
YAML::Node root;
|
||||
|
||||
try
|
||||
{
|
||||
root = YAML::Load(f.to_string());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_FATAL(GENERAL, "Failed to load patch file %s\n%s thrown: %s", patch, typeid(e).name(), e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
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,108 +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
|
||||
const bool is_inf = _timeout > max_timeout;
|
||||
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = _timeout * -10;
|
||||
|
||||
if (HRESULT rc = NtWaitForKeyedEvent(nullptr, &m_value, false, is_inf ? 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, is_inf ? nullptr : &timeout, nullptr, 0) == 0
|
||||
? 0
|
||||
: errno;
|
||||
|
||||
// Normal or timeout wakeup
|
||||
if (!err || (!is_inf && 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,52 +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);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr u64 max_timeout = u64{UINT32_MAX} / 1000 * 1000000;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
Copyright (C) 2011-2012 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0
|
||||
(see accompanying file LICENSE_1_0.txt or a copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
The idea and interface is based on Boost.Optional library
|
||||
authored by Fernando Luis Cacciola Carballal
|
||||
|
||||
Home at https://github.com/akrzemi1/Optional
|
||||
@@ -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>
|
||||
|
||||
@@ -13,10 +13,9 @@ rem // A copy of the GPL 2.0 should have been included with the program.
|
||||
rem // If not, see http://www.gnu.org/licenses/
|
||||
|
||||
rem // Official git repository and contact information can be found at
|
||||
rem // https://github.com/RPCS3/rpcs3 and https://rpcs3.net/.
|
||||
rem // https://github.com/RPCS3/rpcs3 and http://rpcs3.net/.
|
||||
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
setlocal ENABLEEXTENSIONS
|
||||
|
||||
set GIT_VERSION_FILE=%~p0..\rpcs3\git-version.h
|
||||
if not defined GIT (
|
||||
@@ -48,40 +47,14 @@ 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%"
|
||||
goto done
|
||||
)
|
||||
|
||||
rem // Get commit count from (unshallowed) HEAD
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set COMMIT_COUNT=%%I
|
||||
|
||||
rem // If we're in AppVeyor, building a non-master, pull request artifact
|
||||
if defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
|
||||
|
||||
if "%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"=="master" (
|
||||
rem // If pull request comes from a master branch, GIT_BRANCH = username/branch in order to distinguish from upstream/master
|
||||
for /f "tokens=1* delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set user=%%a
|
||||
set "GIT_BRANCH=!user!/%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"
|
||||
) else (
|
||||
rem // Otherwise, GIT_BRANCH=branch
|
||||
set GIT_BRANCH=%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%
|
||||
)
|
||||
|
||||
rem // Make GIT_VERSION the last commit (shortened); Don't include commit count on non-master builds
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%%I
|
||||
|
||||
) else (
|
||||
rem // Get last commit (shortened) and concat after commit count in GIT_VERSION
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%COMMIT_COUNT%-%%I
|
||||
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
)
|
||||
|
||||
rem // Echo obtained GIT_VERSION for debug purposes if needed
|
||||
echo %GIT_VERSION%
|
||||
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
|
||||
|
||||
rem // Don't modify the file if it already has the current version.
|
||||
if exist "%GIT_VERSION_FILE%" (
|
||||
@@ -94,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();
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
+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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user