Compare commits

..

246 Commits

Author SHA1 Message Date
Zangetsu38 d819878aba Debug 2016-10-19 00:08:56 +02:00
Zangetsu38 6ab39ae75d d3d12: Update minidx12 SDK on build 14.393. 2016-10-18 19:57:00 +02:00
Zangetsu38 9c25dfc499 d3d12: Fix typo and little clean up in D3D12Formats.
rsx: add value for Kung Fu Rider.
PPU: register Unknown functions in cellSysmodule.
PPU: register Unknown functions in sceNp.
PPU: register Unknown functions in cellSysutil.
2016-10-18 19:56:59 +02:00
Zangetsu38 2d942545b4 Update LLVM submodule with Release 3.9 2016-10-18 19:56:59 +02:00
Zangetsu38 9f17b1e953 Some Change in Gui. 2016-10-18 19:56:25 +02:00
kd-11 2c803dbe66 gl/vk: Bug fixes and improvements (#2206)
* gl: Only bind attrib textures on thread startup

* gl: Persistent mapped buffers

* gl: Fix emulated primitives in an inlined array

* gl: Do not re-update program information every draw call

* gl/vk: s1 type is signed normalized not unsigned normalized

* gl/rsx: Allow disabling of persistent buffers for debugging

gl: Large heap size is more practical

gl: Fix a bug with legacy opengl buffers

* gl/rsx: Allow emulation of unsupported attribute formats

* gl: Fix typos and remove dprints

gl: cleanup debug prints

* ui: Move the GL legacy buffer toggle to the left pane

* vk/gl: Fix cmp type, its range is [-1,1] not [0,1] SNORM_INT
2016-10-18 15:57:28 +08:00
kd-11 8454949eea gl/vk/rsx: Add a cross-platform overlay text; Minor perf improvements and rsx bugfixes (#2196)
* gl/rsx: Implement platform-agnostic text overlays

gl: Restore performance metrics using new text out helper

gl/rsx: Refactor text generation class

* vk: Enable text overlay

gl/vk: Polish overlay counters implementation

gl: Better resource shutdown for text writer

* gl: Optimization, do not rebind TIUs every frame. Speedup

* gl: Optimizations and improvements to vertex upload code

* gl/vk: Texture format swizzles

vk: Texture format fix

vk: Fix YX format swizzles

* rsx: Decode vertex texture index
2016-10-11 08:55:42 +08:00
kd-11 7a9841bb2a gl/vk/dx12: Fix depth reconstruction bug; Fix sampler parameters (#2188)
vulkan: Fix duplicated code bug

fix rebase
2016-10-04 21:51:40 +08:00
Melissa Goad 22b1400018 Revamp PFIFO command submission emulation (#2179) 2016-10-01 22:13:15 +03:00
raven02 44b8556dc6 Vulkan: fix G8B8 texture swizzle (#2181) 2016-10-01 17:02:10 +08:00
Ivan a342107021 Paypal link removed 2016-10-01 01:21:43 +03:00
kd-11 1c9718389f gl/vk: Vertex attribute uploading and texture swizzle fixes (#2174)
* gl/vk: Properly upload vertex attributes

* vk: Fix cmp type

* vk: Remap all texture formats
2016-09-29 15:16:00 +08:00
kd-11 5430e1d310 rsx/gl/vk/dx12: Add emulated texture fetch for depth read (#2173)
* rsx/gl/vk/dx12: Add emulated texture fetch for depth read

gl/vk/dx12: Simplify reinterpretation equation

* gl: Remove unnecessary re-swizzle

* glsl: explicitly cast uint to float
2016-09-29 14:54:32 +08:00
kd-11 9abb908226 vk: Add a subpass dependancy (#2172) 2016-09-28 22:12:52 +08:00
kd-11 38562155d4 gl/vk: Flip wpos if origin != top 2016-09-28 07:22:45 +08:00
kd-11 4f74cbe510 gl: Reverse cull face when origin == top (#2161) 2016-09-27 15:34:01 +08:00
raven02 528b2d6c7b GL/Vulkan: not discard fragment when hits NEVER comparsion (#2156)
GL/Vulkan: return no operation when comparison is never
2016-09-26 21:59:38 +08:00
kd-11 7884356e90 gl/vk: Bug fixes and improvements (#2155)
* gl: Fix broken buffer reserve computation

* gl: Texture format fixes

* gl: Two sided lighting

* gl: Always update glsl output registers

* gl: Simplify vertex input declaration

* vk: Always write output registers

* vk/gl: swizzle component read on depth textures

* gl/vk: Use proper MVP matrix

gl: fix broken mvp when window_origin=top

* vk/gl: Move fragment operations block into the proxy function
2016-09-26 20:21:17 +08:00
raven02 38f35df7b6 DX12: enable alpha kill (#2158) 2016-09-26 18:38:52 +08:00
raven02 fcb853792d Typo fix (#2153) 2016-09-25 16:53:57 +08:00
Oil b72f6da853 Porting of DH's user clip implementation in gl (#2139)
* Porting of DH's user clip implementation in gl

* Tweak clang-format

* rsx: Move inline array to draw_clause structure.

* rsx: Use variant based draw commands.

* rsx: Dump DRAW_ARRAYS and DRAW_INDEX_ARRAYS.

* GL: old recompiler clean up (#2142)

* RSX texture refactor (#2144)

* gl/vk: Enable vertex texture fetch (#2127)

* gl: Enable vertex textures

* rsx: use textureLod instead of generic texture sample

* rsx: handle uploading of W32_X32_Y32_Z32

* gl: Re-enable proper shader logging

remove old logging method that overwrites single file

* gl: Declare texture_coord_scale for vertex samplers

* gl: texture remap fixes; enable remap for vertex textures

* gl: offset texture indices to base layer 16

* rsx: Fix W32_Z32_Y32_X32_FLOAT subresource layout

* vk: Enable vertex textures

* rsx: define special calls for vertex texture fetch

* gl: improved vertex texture fetch setup

* vk: Fix texture formats and component mapping

* vk: Implement vertex texture fetch functions properly

* vk/gl: proper fix for primitive restart index

revert inadvertent decompiler update

* gl: Disable filtering for vertex textures

* Hopefully fix appveyor build (#2148)

* GL/Vulkan: Bug fixes and improvements; alphakill for vulkan (#2146)

* vk: Zero-initialize some more structs

* gl: Clean up fragment program generation code

* vk: Enable alpha kill

* vk: Fix surface clear; redirect output for surface_type:b

* vk: Tie renderpass to program object to avoid incompatible passes

* vk: Properly compute descriptor pool size (#2150)

* rsx: Set default attribute format to float.

* rsx: vertex attribute size is 1 again for CMP, let backend handles this formats properties.

* rsx: Move printing function in a separate header/cpp

* Porting of DH's user clip implementation in gl
2016-09-24 18:21:41 +08:00
vlj 623ddd966c Merge pull request #2140 from vlj/rsx-refactor
Rsx refactor
2016-09-22 16:25:33 +02:00
vlj 9ff52cf063 rsx: Move printing function in a separate header/cpp 2016-09-22 15:44:59 +02:00
vlj 8f5e94c155 rsx: Set default attribute format to float. 2016-09-22 15:44:59 +02:00
vlj 6b7ce37374 rsx: vertex attribute size is 1 again for CMP, let backend handles this formats properties. 2016-09-22 15:44:59 +02:00
kd-11 66e57ae19b vk: Properly compute descriptor pool size (#2150) 2016-09-22 16:06:57 +08:00
kd-11 0d207a6c0d GL/Vulkan: Bug fixes and improvements; alphakill for vulkan (#2146)
* vk: Zero-initialize some more structs

* gl: Clean up fragment program generation code

* vk: Enable alpha kill

* vk: Fix surface clear; redirect output for surface_type:b

* vk: Tie renderpass to program object to avoid incompatible passes
2016-09-21 21:41:29 +08:00
Danila Malyutin 0b080aeefc Hopefully fix appveyor build (#2148) 2016-09-21 17:34:38 +08:00
kd-11 867e9210d7 gl/vk: Enable vertex texture fetch (#2127)
* gl: Enable vertex textures

* rsx: use textureLod instead of generic texture sample

* rsx: handle uploading of W32_X32_Y32_Z32

* gl: Re-enable proper shader logging

remove old logging method that overwrites single file

* gl: Declare texture_coord_scale for vertex samplers

* gl: texture remap fixes; enable remap for vertex textures

* gl: offset texture indices to base layer 16

* rsx: Fix W32_Z32_Y32_X32_FLOAT subresource layout

* vk: Enable vertex textures

* rsx: define special calls for vertex texture fetch

* gl: improved vertex texture fetch setup

* vk: Fix texture formats and component mapping

* vk: Implement vertex texture fetch functions properly

* vk/gl: proper fix for primitive restart index

revert inadvertent decompiler update

* gl: Disable filtering for vertex textures
2016-09-20 22:23:56 +08:00
raven02 77f8ce503d RSX texture refactor (#2144) 2016-09-19 09:25:49 +08:00
raven02 530ea688e4 GL: old recompiler clean up (#2142) 2016-09-18 13:19:26 +08:00
vlj 11a442272d Merge pull request #2112 from vlj/rsx-refactor
Rsx refactor: Use variant for draw commands.
2016-09-17 23:53:59 +02:00
vlj f87e396958 rsx: Dump DRAW_ARRAYS and DRAW_INDEX_ARRAYS. 2016-09-17 23:37:52 +02:00
vlj 8d54bcbc0d rsx: Use variant based draw commands. 2016-09-17 23:37:52 +02:00
vlj 03c86ae43b rsx: Move inline array to draw_clause structure. 2016-09-17 23:37:52 +02:00
vlj ce21db2ce3 Tweak clang-format 2016-09-17 23:37:52 +02:00
Oil 153a2d2b40 Fixed fog and alphakill implementation in glsl (based on DH's old commits) (#2137)
* Fixed NV4097_SET_COLOR_CLEAR_VALUE

* Fixed fog and alphakill implementation in glsl (based on DH's old commits)
2016-09-14 22:47:53 +08:00
Oil e73fce2d60 Fixed NV4097_SET_COLOR_CLEAR_VALUE (#2135) 2016-09-13 02:28:34 +03:00
vlj d43edb19d2 Merge pull request #2134 from vlj/dx12-fix
Dx12 fixes
2016-09-12 20:38:56 +02:00
vlj 14205d3d1c d3d12: CMP vertex format has 4 members.
Fix 1878
2016-09-12 00:20:11 +02:00
vlj 30b804e0bc d3d12: Fix a potential race condition. 2016-09-12 00:20:10 +02:00
vlj 153f1cc50a d3d12: Always set transform constant when debug output is enabled. 2016-09-12 00:20:10 +02:00
raven02 fc3179b698 DX12: temporary disable vertex base index check (#2128) 2016-09-07 09:26:01 +08:00
raven02 d4a55f4b06 Vulkan: enable cull face again (#2124)
* Vulkan: enable cull face again

* minor fix
2016-09-06 09:43:27 +08:00
raven02 03a5b5be1a DX12: Align to multiple of 4 block for DXTC format (#2125) 2016-09-05 08:47:45 +08:00
raven02 ad39615141 Revert "RSX: fix unknown vertex base type" (#2122) 2016-09-04 18:29:21 +08:00
raven02 691d87978b RSX: fix wrong format 0x9b (#2121) 2016-09-04 15:23:43 +08:00
raven02 ebf54d6acd RSX: fix unknown vertex base type (#2120) 2016-09-04 14:36:37 +08:00
Nekotekina 5f15c661c6 .clang-format restored 2016-08-28 12:35:56 +03:00
vlj c0ab0dee6b Merge pull request #2101 from vlj/rsx-refactor
Rsx refactor: Some cleanups
2016-08-27 18:21:16 +02:00
vlj 73e50b970d Remove settings UI change that accidently slipped in. 2016-08-27 15:40:41 +02:00
vlj 11858dce1a rsx: Vertex array attributes don't need to be stored outside of regs. 2016-08-27 15:40:41 +02:00
vlj a64053fd68 rsx: Remove some unused code. 2016-08-27 15:40:41 +02:00
vlj 1ede5cbc4c Add a git pre-commit hook running clang-format 2016-08-27 15:40:41 +02:00
raven02 bb66b97251 GL: minor fixes (#2105)
* Minor fixes

* temporary disable 2-sided lighting

* Disable user clip planes until they are properly handled
2016-08-27 14:12:44 +08:00
raven02 6e07e07cd0 GL: enable 2-sided lighting (#2103) 2016-08-27 00:26:23 +08:00
raven02 a270ac7f02 GL: re-use common fp/vp decompiler (#2100) 2016-08-26 22:23:23 +08:00
vlj 7f3cb4d3c9 Merge pull request #2084 from vlj/rsx-refactor
RSX: Puts vertex buffer in array and in register in a variant type.
2016-08-25 21:14:51 +02:00
Vincent Lejeune 42b518cf7e rsx: use range for vertex buffer attribute. 2016-08-24 21:58:59 +02:00
Vincent Lejeune c24fba89e8 Add variant.hpp from mapbox 2016-08-24 21:58:59 +02:00
raven02 5b225ad59f GL: ignore texture upload if invalid dimension found (#2097) 2016-08-24 21:19:16 +08:00
kd-11 8ebe9d7dc2 gl: Dont use hard assertions on error, driver reporting is so much better (#2094) 2016-08-24 17:31:27 +08:00
kd-11 9beb2d8ae0 vk/rsx: Bug fixes (#2092)
* vk: fix separate front and back lighting

* vk: Inlined arrays can have emulated primitives too!

* vk: Use float input attribs for better compatibility

* vk: Free resources during shutdown
2016-08-24 08:50:07 +08:00
raven02 12099b3144 RSX: fix invalid format (0x1) (#2088) 2016-08-24 02:08:05 +08:00
raven02 2aa2c1811f Vulkan : add structure type for color blend state (#2091) 2016-08-23 19:07:51 +08:00
raven02 af1ff4439d RSX: fix wrong format 0x9c (#2087) 2016-08-23 16:18:58 +08:00
raven02 51bdf1e3ed DX12: fix invalid dimension (#2086)
DX12: workaround invalid texture dimension
2016-08-23 11:06:01 +08:00
raven02 d7a899f984 Vulkan : refine 2-sided lighting approach (#2083) 2016-08-23 08:24:22 +08:00
raven02 707523c679 Vulkan: set ColorBlendState info (used by logicOp) (#2080)
* Vulkan: set ColorBlendState info (used by logicOp)

* fix attachmentCount
2016-08-22 23:14:32 +08:00
raven02 e04de77f82 Vulkan : Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE (#2081) 2016-08-21 18:18:26 +08:00
raven02 be9cebbc8f Workaround id_min/max (#2079) 2016-08-20 21:27:50 +08:00
Nekotekina e3bc2273d3 fs::dir improved
FindFirstFileExW used
Immediate directory read
2016-08-18 15:14:08 +03:00
Nekotekina c20756136a Minor diagnostic added 2016-08-18 13:29:53 +03:00
Nekotekina 066e3006bf cellGameCreateGameData fixed
cellGameDataCheck fixed
PARAM.SFO creation fixed
2016-08-17 21:59:42 +03:00
Nekotekina bbb0effe23 Minor fixes
cellSyncMutexTryLock fixed
2016-08-17 19:50:20 +03:00
Nekotekina ad174eb12c error_code implemented
Reports based on formatting system
ppu_error_code removed
arm_error_code removed
2016-08-16 18:57:44 +03:00
Nekotekina 1c33c012ad ERROR_CODE macro removed 2016-08-15 19:18:05 +03:00
Nekotekina 3c82e1a58d Silly macro removed-3 2016-08-15 18:30:33 +03:00
Nekotekina dbcb5df172 WRAP_EXPR macro removed 2016-08-15 17:11:45 +03:00
Nekotekina dafb6b5c92 %p fmt fix 2016-08-15 16:57:51 +03:00
Nekotekina 84d0d396ed EXPECTS usage removed 2016-08-15 16:29:38 +03:00
Nekotekina 56b9b38c9c verify() fix 2016-08-15 14:59:19 +03:00
Nekotekina 05fb57baff VERIFY macro removed 2016-08-15 03:13:31 +03:00
Nekotekina cc46f2d7e6 LOG macro improved 2016-08-15 00:04:42 +03:00
Nekotekina 1f3433464c ENSURES usage removed 2016-08-14 22:41:01 +03:00
Nekotekina b0f5796c90 New narrow() implementation 2016-08-14 20:28:56 +03:00
Nekotekina 0f87c4485d Silly macro removed-2 2016-08-14 18:19:42 +03:00
Nekotekina 5e0489dcc0 cpu_init removed 2016-08-14 18:07:34 +03:00
Nekotekina 949200cd3e Type hacks removed 2016-08-14 18:07:32 +03:00
Nekotekina 2d512121f1 XAudio2.8+ fix 2016-08-12 23:45:02 +03:00
Nekotekina 7a2802a5e0 Silly macro removed 2016-08-12 19:31:28 +03:00
Nekotekina f0459e3891 .editorconfig added 2016-08-12 17:13:25 +03:00
Nekotekina 1fd8c50d95 .clang-format added 2016-08-12 14:32:57 +03:00
vlj 65fe9b0927 Merge pull request #2037 from vlj/rsx-refactor
Rsx: Remove vertex_draw_count (WIP)
2016-08-11 20:20:07 +02:00
Vincent Lejeune 619d605a9e rsx: remove vertex_draw_count 2016-08-11 19:47:14 +02:00
Vincent Lejeune b8721b6475 gl: Refactor vertex_buffer.cpp 2016-08-11 19:47:14 +02:00
Vincent Lejeune a94b9d38b0 vk: refactor VKVertexBuffers. 2016-08-11 19:47:14 +02:00
Vincent Lejeune c382ce5260 Add optional files. 2016-08-11 19:47:14 +02:00
Nekotekina fc56e70172 vm::ptr<char> formatting 2016-08-11 16:47:20 +03:00
Nekotekina 8c8242345e bts/btr/btc support improved 2016-08-10 16:12:34 +03:00
Nekotekina 130f7905ba Error report fix 2016-08-10 14:17:07 +03:00
Nekotekina 912072e60c LLVM: minor fixes (JIT.cpp) 2016-08-10 13:09:11 +03:00
Nekotekina bdeccd889f cpu_type removed, system_type added
cpu_state -> cpu_flag
vm::stack_allocator template improved
ppu_cmd type changed to enum, cmd64 type added
2016-08-09 17:14:41 +03:00
raven02 009ac37a7d XAudio : reorder versioning 2.9>2.7>2.8 (#2048) 2016-08-09 15:55:11 +08:00
kd-11 44ae306e6b vk: delay texture removal when cache is clobbered (#2045) 2016-08-09 08:47:42 +08:00
Nekotekina a7e808b35b EXCEPTION macro removed
fmt::throw_exception<> implemented
::narrow improved
Minor fixes
2016-08-08 19:19:32 +03:00
Nekotekina 46735d6b3d New bitsets (experimental) 2016-08-08 16:29:37 +03:00
Nekotekina 71441819e5 multicast<> rewritten 2016-08-07 17:06:37 +03:00
Nekotekina 1a7ea2d235 fmt_unveil<> fix 2016-08-07 17:05:35 +03:00
Nekotekina 4438163da1 Gui log bugfix 2016-08-07 14:39:29 +03:00
Nekotekina b7eda71673 XAudio2.7 bug workaround 2016-08-06 18:19:38 +03:00
Nekotekina 0fcbd43db9 Specify XAudio sample rate and ch num 2016-08-06 16:21:29 +03:00
Nekotekina 4de513eb01 Increase XAudio thread priority 2016-08-06 15:40:51 +03:00
Nekotekina 9245308ff2 Improve fatal error report 2016-08-06 15:09:44 +03:00
Nekotekina 7be259217a Error loading image fix 2016-08-06 13:39:05 +03:00
Nekotekina c9a789bf76 PPU LLVM fix 2016-08-06 13:39:03 +03:00
Nekotekina 3cd2f735a7 Fmt fix 2016-08-06 13:39:01 +03:00
vlj b61ac15c47 Merge pull request #2034 from vlj/rsx-refactor
rsx: Returns u32 instead of size_t for get_index_count/type_size
2016-08-06 00:51:23 +02:00
Vincent Lejeune fb47945930 rsx: Returns u32 instead of size_t for get_index_count/type_size 2016-08-06 00:25:23 +02:00
vlj 247c776a1b Merge pull request #2033 from vlj/rsx-refactor
rsx: Use a "draw clause" object in rsx_state.
2016-08-05 23:48:48 +02:00
Vincent Lejeune eb1d4811de rsx: Use a "draw clause" object in rsx_state. 2016-08-05 23:33:40 +02:00
Nekotekina d646fbb94f Fmt/Log fixes 2016-08-05 20:59:25 +03:00
vlj 98f09e4f27 Merge pull request #2021 from vlj/rsx-refactor
rsx: Move index pointer generation in rsx::thread
2016-08-05 18:08:03 +02:00
Vincent Lejeune 7a6f5b6ee5 rsx: Move index pointer generation in rsx::thread. 2016-08-05 17:54:44 +02:00
raven02 8ff155a2c9 Regression fix #2029 (#2030) 2016-08-05 14:38:58 +08:00
Nekotekina f7dcaa4a68 cellSysutilCheckCallback fix 2016-08-04 22:36:41 +03:00
DHrpcs3 dcd2bbaa3d Added DHrpcs3 to mention-bot ignore list (#2026) 2016-08-04 22:36:10 +03:00
Nekotekina 5a36c57c57 Formatting system improved
`unveil<>` renamed to `fmt_unveil<>`, now packs args to u64 imitating va_args
`bijective...` removed, `cfg::enum_entry` now uses formatting system
`fmt_class_string<>` added, providing type-specific "%s" handler function
Added `fmt::append`, removed `fmt::narrow` (too obscure)
Utilities/cfmt.h: C-style format template function (WIP)
Minor formatting fixes and cleanup
2016-08-04 21:34:00 +03:00
vlj 662fce38bd Merge pull request #2023 from raven02/texture
Ignore texture upload if texture width > pitch
2016-08-04 17:39:27 +02:00
raven02 4dd67cdd54 texture: ignore when texture width > pitch 2016-08-04 17:54:34 +08:00
kd-11 47a9c8d731 vk/gl: bug fixes (#2018)
* vk: use null sampler for invalid/broken texture configurations

* gl: Do not consider 32_BIT_EXPORTS flag for depth writes
2016-08-04 03:33:52 +08:00
raven02 9a081369c8 update submodule rsx_program_decompiler (#2020) 2016-08-03 09:45:10 +08:00
raven02 208f4c3e27 vk: front_diff_color typo fix (#2016)
* vk: typo fix

* continue in for loop
2016-08-02 23:54:49 +08:00
raven02 c618e02695 update submodule rsx_program_decompiler (#2015) 2016-08-02 10:45:08 +08:00
raven02 61c6f82f74 Regression fix #1995 (#2014) 2016-08-01 19:47:14 +08:00
Nekotekina e6bd91ada0 id_manager: embedded RTTI 2016-08-01 12:51:47 +03:00
Nekotekina e585939ac2 id_manager::id_key implemented 2016-08-01 01:35:53 +03:00
Nekotekina 3576e13e9a emucore.vcxproj fix 2016-08-01 01:35:37 +03:00
vlj 470ed777c2 Merge pull request #2011 from vlj/rsx-dbg2
rsx-debug: Add a separate qt app
2016-07-31 22:44:03 +02:00
Vincent Lejeune 7195b2e907 rsx-debug: Add a separate qt app 2016-07-31 22:27:00 +02:00
vlj 32a03344b3 Merge pull request #2010 from vlj/rsx-refactor
rsx: Fix warning because of unused arguments
2016-07-31 19:32:30 +02:00
Vincent Lejeune 9e7902455d rsx: Fix warning because of unused arguments 2016-07-31 19:19:21 +02:00
Nekotekina 68cf570b58 Implemented rsx::invalid_method 2016-07-31 18:16:51 +03:00
Nekotekina 1c69eb2b73 rsx_method_t extended
rsx_methods.cpp cleanup
2016-07-31 18:16:49 +03:00
Nekotekina 6a9f3040e1 rsx_methods.cpp fix 2016-07-31 18:16:48 +03:00
vlj 190fc4301e Merge pull request #2008 from vlj/rsx-refactor
Rsx: Inline some rsx_state member and split some headers.
2016-07-31 17:16:04 +02:00
Vincent Lejeune 22a89a272e Move all gcm enums into separate header/cpp. 2016-07-31 17:04:30 +02:00
Vincent Lejeune 4c46bde315 rsx: Inline rsx_state and texture constructors. 2016-07-31 16:48:09 +02:00
Nekotekina 0578430fd0 XAudio2 version priority 2016-07-30 20:25:46 +03:00
vlj 33e13aa7e7 Merge pull request #1994 from vlj/rsx-refactor
Rsx refactor: Implement serialisation of debug data
2016-07-30 18:52:39 +02:00
Vincent Lejeune b9f4c15ec0 vm: Add missing headers.
vm.h relies on memory (std::shared_ptr) and functionnal (std::function).
2016-07-30 18:39:26 +02:00
Vincent Lejeune 15500d4ee9 rsx: implement serialization of rsx states. 2016-07-30 18:39:26 +02:00
Vincent Lejeune 2528fc4555 Add cereal dependency 2016-07-30 18:39:26 +02:00
Nekotekina f8719c1230 PPUThread refactoring
`CallbackManager` removed, added _gcm_intr_thread for cellGcmSys
`PPUThread` renamed to `ppu_thread`, inheritance allowed
Added lightweight command queue for `ppu_thread`
Implemented call stack dump for PPU
`get_current_thread_mutex` removed
`thread_ctrl::spawn`: minor initialization fix
`thread_ctrl::wait_for` added
`named_thread`: some methods added
`cpu_thread::run` added
Some bugs fixes, including SPU channels
2016-07-30 16:35:02 +03:00
kd-11 33c59fa51b vk: optionally center/offset images when scaling (#1998) 2016-07-30 10:07:39 +08:00
vlj 2b6f8a075e Merge pull request #1993 from vlj/rsx-refactor
rsx: Copy state in capture frame call
2016-07-27 22:54:16 +02:00
Vincent Lejeune ac771f951d rsx: Copy state in capture frame call 2016-07-27 20:20:35 +02:00
vlj e297984e59 Merge pull request #1982 from vlj/rsx-refactor
rsx: Use bitfield template to decode values.
2016-07-27 19:12:59 +02:00
Vincent Lejeune 8b12379eb3 rsx: Use bitfield template to decode values. 2016-07-27 18:38:36 +02:00
jypem 2064f1cb80 Handle error when loading game icon (#1687) 2016-07-26 14:39:12 +03:00
Lena e377199e41 Ensure the 'shaderlog' directory exists (#1986)
Should fix #1984
2016-07-26 00:15:14 +03:00
Nekotekina a8f977ed9e XAudio 2.8 test fix 2016-07-25 19:30:21 +03:00
Nekotekina 44bee7d0ba LLVM: Use small code model
Global variables modified:
__mptr: pointer to memory base addr
__cptr: pointer to function map addr

Use 32 bit pointers in function map
2016-07-25 18:26:02 +03:00
Benjamin Hodgetts c100328a6f Clarify working GCC versions (#1851)
GCC 6.1 cannot compile RPCS3 due to a regression within GCC itself, so note that here as it's the current version that a lot of people are likely to be using, with a link to the bug that contains further information.
2016-07-25 17:48:25 +03:00
raven02 1672c93a2d Revert "Audio : allow XAudio2 to run its own thread" (#1988) 2016-07-25 09:09:14 +08:00
raven02 2a3029a62c PPU: register undocumented functions in cellSysmodule (#1987) 2016-07-25 08:43:02 +08:00
raven02 53b2e19d96 Audio : allow XAudio2 to run its own thread (#1980) 2016-07-25 08:25:02 +08:00
Danila Malyutin 132093c80e update rsx_program_decompiler submodule (#1983) 2016-07-25 07:39:09 +08:00
Nekotekina 5c9f83c3a8 PPU LLVM: New "stack" strategy
Minor pessimization: all memory accesses are volatile
Special handling of prologues and epilogues
Minor optimizing assumption for SP
2016-07-24 21:47:45 +03:00
Nekotekina 712c04b2ad PPU Analyser update
WIP, nothing changed
2016-07-24 21:06:10 +03:00
Nekotekina 39dadad534 PPU executable memory protection
Experimental commit, not improved for PRX
Also fixed minor bug in PRX loader
2016-07-24 21:06:09 +03:00
Nekotekina a026d35c97 sys_interrupt_thread_eoi fixed
thread_ctrl::interrupt improved
BIND_FUNC improved: preparations
2016-07-24 21:06:07 +03:00
Nekotekina 7ccdea7822 Removed std::enable_shared_from_this
Minor ID manager refactoring
2016-07-24 21:06:05 +03:00
kd-11 09ae45c566 vk: Conform to current spec (#1981)
* vk: define rtt images with transfer_dst set

* vk: Bind a buffer view for attribs with undefined data

* vk: Properly define renderpass clip region to fit the framebuffer

* vk: respect type bits from returned memory requirements
2016-07-25 00:28:49 +08:00
Nekotekina deeb4acbe5 Partial revert of 6ae54ae27b 2016-07-22 19:26:58 +03:00
Nekotekina 5eb98b745f cellVdec fixed (requires LLE dmux)
Basic MPEG2 support
2016-07-22 18:29:05 +03:00
kd-11 74fec275c7 gl: Clear depth surfaces before use; Vulkan cleanup (#1957)
* vk: Clean up a few trap messages

vk: silence a few compile errors

* gl: Clear new depth surfaces to max_depth

gl: use glClear to clear depth buffers
2016-07-22 07:31:58 +08:00
Nekotekina a0c0df6e9d Dynamic XAudio version detection 2016-07-21 17:46:46 +03:00
raven02 0ae8cc4467 D3D12: revert heap size back to 896M (#1960)
* D3D12: revert heap size back to 896M

* Update D3D12GSRender.h
2016-07-21 14:50:06 +08:00
raven02 f36f478281 vk: refactor compare_op (#1959) 2016-07-21 13:35:06 +08:00
Nekotekina 0227c03366 GUI logging improved
logs::listener resurrected
rpcs3 version: constexpr
2016-07-21 01:54:39 +03:00
raven02 8157e7cac8 Obsolete 3D monitor (#1955) 2016-07-20 23:45:26 +08:00
Nekotekina ae634bb87e RSX exception fix
VBlank thread management fix
2016-07-20 15:16:19 +03:00
vlj 2af86e363c Merge pull request #1941 from vlj/rsx-refactor
rsx: Use register_decoder for vertex attributes.
2016-07-19 22:12:20 +02:00
Vincent Lejeune e9bee80f4b rsx: Use register_decoder for vertex attributes. 2016-07-19 20:28:32 +02:00
vlj cc30e1aa47 Merge pull request #1940 from kd-11/master
dx12: Constant color/alpha blending
2016-07-19 20:27:55 +02:00
kd-11 854bc1db60 dx12: simplify constant color blend equation/algorithm checks 2016-07-19 19:20:57 +03:00
kd-11 d3837de571 dx12: Constant color/alpha blending 2016-07-19 19:20:57 +03:00
raven02 e1ff3f4674 rsx: use fragment_textures_count (#1948)
* rsx:  use fragment_textures_count

* Typo: unknow -> unknown
2016-07-19 22:50:40 +08:00
Nekotekina ceb4cb59ac Typo fix: comparaison->comparison 2016-07-19 14:17:25 +03:00
Nekotekina fc9fdca3f6 Make TLS great again
And clean System.h a bit
2016-07-19 14:06:39 +03:00
raven02 6296453ef3 D3D12: inline stencil test as GL and Vulkan backend (#1945) 2016-07-19 16:52:14 +08:00
Nekotekina 04926374f7 PKG installer fix 2016-07-18 21:28:58 +03:00
Nekotekina a186af32ec Fixed thread interrupt and accvio 2016-07-18 17:54:31 +03:00
raven02 7ac9d3b679 D3D12/Vulkan : swizzle texture format G8B8 (#1931)
* D3D12: swizzle texture format G8B8

* Vulkan: swizzle texture format G8B8
2016-07-18 20:16:11 +08:00
kd-11 2e5b01faca vk: Fix vertex winding (#1934)
* vk: do not flip face winding based on shader origin

* vk: disable face culling
2016-07-17 22:55:59 +03:00
kd-11 2337bf204c vk/dx12: Enable/fix separate back and front lighting (#1927)
* vk: separate specular color

rsx: separate front color output from back color output

re-enable front-back diffuse lighting

vk: fix front face selection and actually enable face culling

* dx12: Hide constant-key blended visuals (by common use of factor, 1-factor)

* dx12: Fix 2 sided lighting when the shader does not compute both outputs

* vk/dx12: confirm that src register exists before copying for 2-sided lighting
2016-07-18 00:57:50 +08:00
vlj b2a7dac11b Merge pull request #1916 from vlj/rsx-refactor
rsx: Gather most rsx commands pretty printing and state modification …
2016-07-17 17:56:36 +02:00
Vincent Lejeune c6ed5a8e6b gl: Fix direct call to rsx::method_registers array. 2016-07-17 17:31:53 +02:00
Vincent Lejeune d97cdb9fbf rsx: Gather most rsx commands pretty printing and state modification function in a single file.
rsx_decode.h implements a "rsx_decoders" template class that is specialized for most GCM command
found in rsx command buffer. 3 static members are defined : a "decode" function that turns command
value into a more meaninfull type if applicable (for instance bool for _enabled* command, surface
formats for set_surface_format command...), a "commit_rsx_state" that modifies a given rsx_state
structure when the command is parsed, and a "dump" function used in rsx_debugger for pretty printing.
Hopefully having the 3 functions in a single place for every command will act as a self documenting
list of rsx command buffer opcode.

rsx_state is also expanded into several explicit variables instead of being stored into a u32 array.
This should makes debugging easier (Visual Studio will display the exact value of these member for instance)
as well as preparing rsx_state for serialisation/deserialisation.

The vertex array and textures opcode are not concerned atm for bisecting purpose.
2016-07-17 17:31:53 +02:00
Nekotekina 692d9dd4ae NV0039_OFFSET_IN fix 2016-07-17 15:03:13 +03:00
Ivan 260865de6d Merge pull request #1925 from Nekotekina/master
Commit collection
2016-07-17 03:44:28 +03:00
Nekotekina 438e057dc8 Partial commit: sys_fs 2016-07-17 02:27:52 +03:00
Nekotekina 59433bfcd5 Implemented thread_ctrl::interrupt 2016-07-17 02:23:45 +03:00
Nekotekina 96728a83f6 Partial commit: sys_memory, sys_mmapper 2016-07-16 14:46:01 +03:00
Nekotekina f5e65e4ad9 Partial commit: sys_tty 2016-07-16 14:45:59 +03:00
Nekotekina c95f6c8c56 Partial commit: sys_vm 2016-07-16 14:45:58 +03:00
Nekotekina 73c2115968 BEType: explicit alignment specifier 2016-07-16 14:45:57 +03:00
Ivan 5d6aecc599 Update donation link 2016-07-16 02:20:58 +03:00
raven02 2085d318bb rsx: typo fix (#1921) 2016-07-15 20:19:15 +03:00
Nekotekina c77dec6d6a PPU Analyser improved
Fix for old homebrews
2016-07-15 13:42:22 +03:00
AnnieL dc34d5b350 cell: add several error (return) codes and definitions (#1914)
* cellHttp: add error codes

Adds error codes for cellHttp and cellHttps

* libDaisy: adds error codes and definitions

Adds error codes, assertations and definitions for cellDaisy.

* cellHttpUtil: add error codes

Adds error codes for cellHttpUtil.

* cellCelp8Enc: moves error codes, adds definitions

Moves error codes to cellCelp8Enc.h, adds some definitions.

* cellCelpEnc: moves error codes, adds definitions

* cellJpgEnc: adds error codes and definitions

Moves the existant error codes to cellJpgEnc.h and adds more error codes
/ definitions.

* cellVoice: moves error codes, adds definitions

Moves error codes to cellVoice.h, adds most cellVoice definitions

* Fix typos
2016-07-15 00:02:07 +03:00
AnnieL ca835ba68a cellGame: unknown category temporary fix (hack) (#1909)
All the games I've been trying to load from outside RPCS3's bin directory are returning me empty directories
```
{PPU[0x3] Thread (main_thread) [0x011223d8]} class fmt::exception thrown: cellGameBootCheck(): Unknown CATEGORY: 
```

This is a hack for when the category is empty or unknown. 
We assume it's a disk game and proceed with the emulation.
2016-07-14 23:12:26 +03:00
kd-11 ce56351554 gl: Fix fragment constants streaming (#1907) 2016-07-15 02:25:38 +08:00
raven02 d60b292ef1 Modules: savedata fix (#1910) 2016-07-15 00:28:26 +08:00
Nekotekina eb377f425c PPU LLVM: Analyser fix
ppu_branch_target removed
2016-07-14 16:27:14 +03:00
Ivan 4c4e4fc772 Merge pull request #1902 from kd-11/master
gl: bug fixes
2016-07-14 00:01:22 +03:00
kd-11 6401eefb26 gl: reset texture scaling factor during bind
reset vertex textures as well
2016-07-13 21:01:16 +03:00
kd-11 ea6f3ff5ed gl: Properly determine front face winding 2016-07-13 21:01:16 +03:00
kd-11 97581d8635 gl: Fix primitive type checks 2016-07-13 21:01:16 +03:00
Nekotekina 6bac4a535b Vulkan: glslang workaround 2016-07-13 18:10:35 +03:00
Nekotekina 0a5b518aea PPU Analyser fix 2016-07-13 02:54:34 +03:00
Nekotekina 94da0dbd4d PPU LLVM improvements
Removed interpreter dependencies
Reciprocal instructions improved
2016-07-12 17:33:13 +03:00
raven02 87e38118a5 Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE (#1898) 2016-07-12 21:52:11 +08:00
Nekotekina ba8fd825ec fs::get_data_dir implemented 2016-07-11 22:12:39 +03:00
kd-11 2c981cf940 rsx: mark register access with divider op enabled and frequency 1 (#1892) 2016-07-12 02:53:52 +08:00
Nekotekina 11f7b167ae Update Vulkan submodules
Temporarily disabled Vulkan build for Linux
2016-07-11 19:27:50 +03:00
Nekotekina 06c6c8212d Minor fixes
elf_object
Loader fix
Analyser fix
2016-07-11 16:30:11 +03:00
raven02 b89961f01d rsx: set frame limiter before rsx->flip() (#1885) 2016-07-11 21:00:04 +08:00
kd-11 59df7e7104 glsl: not all shaders write to col0 (#1884)
fix typo
2016-07-11 09:05:13 +08:00
kd-11 bbf7e6332c glsl; dump shaderlog (#1883)
fix typo
2016-07-11 01:16:31 +08:00
Lena 8c3b3f7ab4 CMake: improve compiler checks (#1847)
Moves the compiler check out of rpcs3/CMakeLists.txt and adds them
into rpcs3/cmake_modules/ConfigureCompiler.cmake
Add better compiler checks and eliminate a TODO
2016-07-10 16:15:56 +08:00
raven02 47987efb75 rsx: add default case for to_front_face() (#1879) 2016-07-10 08:33:20 +08:00
raven02 ed8ebda804 vk: add missing compare func not_equal (#1876) 2016-07-10 04:32:09 +08:00
raven02 d4da0e052d sys_net: add few socket options (#1874) 2016-07-10 02:30:56 +08:00
kd-11 6705a6ecc9 rsx: properly check for inlined array before discarding draw (#1877) 2016-07-09 22:54:44 +08:00
raven02 dfa968863a DX12: get_scissor() fix (#1868) 2016-07-09 01:00:15 +08:00
raven02 70885ada67 RSX: throw exception removal for user_command() (#1872) 2016-07-09 00:22:10 +08:00
vlj 71b21fe793 Merge pull request #1869 from raven02/vertex
RSX: check vertex_draw_count
2016-07-08 15:54:33 +02:00
raven02 1f4ebf1501 RSX: check vertex_draw_count 2016-07-08 16:56:12 +08:00
vlj dcb3169f56 Merge pull request #1865 from vlj/rsx-refactor
Factorize rsx state
2016-07-07 22:49:23 +02:00
Vincent Lejeune 772706ca4c Factorize rsx state 2016-07-07 21:38:57 +02:00
Ivan 77594dc66c PPU LLVM: New analyser (#1858)
Minor fixes
VEX prefix support
2016-07-07 21:42:39 +03:00
Ivan 0dc00b8104 Merge pull request #1866 from GhettoGirl/gui-fixes
GUI: improve prx library selection
2016-07-06 23:22:21 +03:00
GhettoGirl 758897a929 GUI: add prx library search functionality in settings dialog
Add the possibility too lookup specific libraries in the settings dialog.
2016-07-05 20:46:51 +02:00
GhettoGirl 5c4af45bf5 GUI: improve prx library selection
Sorts the libraries in the settings dialog alphabetically, so they are easier to find.
Sorts selected and unselected modules alphabetically seperatly.
2016-07-05 00:00:46 +02:00
470 changed files with 49802 additions and 35457 deletions
+33
View File
@@ -0,0 +1,33 @@
Standard: Cpp11
UseTab: ForIndentation
TabWidth: 1
IndentWidth: 1
AccessModifierOffset: -1
PointerAlignment: Left
NamespaceIndentation: All
ColumnLimit: 100
BreakBeforeBraces: Allman
BreakConstructorInitializersBeforeComma: true
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: false
AlwaysBreakTemplateDeclarations: true
AllowShortIfStatementsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AllowShortLoopsOnASingleLine: true
Cpp11BracedListStyle: true
IndentCaseLabels: false
SortIncludes: false
ReflowComments: true
AlignConsecutiveAssignments: true
AlignTrailingComments: true
AlignAfterOpenBracket: DontAlign
ConstructorInitializerAllOnOneLineOrOnePerLine: false
BinPackArguments: true
BinPackParameters: true
AlwaysBreakAfterReturnType: None
KeepEmptyLinesAtTheStartOfBlocks: true
IndentWrappedFunctionNames: false
#SpaceAfterTemplateKeyword: false
+7
View File
@@ -0,0 +1,7 @@
root = true
[*.{h,cpp,hpp}]
charset = utf-8
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
+7 -1
View File
@@ -12,7 +12,7 @@
[submodule "llvm"]
path = llvm
url = https://github.com/llvm-mirror/llvm
branch = release_36
branch = release_39
[submodule "rsx_program_decompiler"]
path = rsx_program_decompiler
url = https://github.com/RPCS3/rsx_program_decompiler
@@ -35,3 +35,9 @@
[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 "rsx-debugger"]
path = rsx-debugger
url = https://github.com/RPCS3/rsx-debugger.git
+1 -1
View File
@@ -1,3 +1,3 @@
{
"userBlacklist": ["AlexAltea", "tambry"]
"userBlacklist": ["AlexAltea", "tambry", "DHrpcs3"]
}
+1 -1
View File
@@ -46,7 +46,7 @@ before_install:
fi;
before_script:
- git submodule update --init rsx_program_decompiler asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
- 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/llvm36/lib/llvm-3.6/share/llvm/cmake; fi
Vendored Submodule
+1
Submodule 3rdparty/cereal added at 42a45b6e15
+1156 -4571
View File
File diff suppressed because it is too large Load Diff
+777 -3138
View File
File diff suppressed because it is too large Load Diff
+46 -651
View File
@@ -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
+853 -1582
View File
File diff suppressed because it is too large Load Diff
+10
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+35 -55
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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( ) */
+1 -1
View File
@@ -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( ) */
+8 -3
View File
@@ -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
+1 -1
View File
@@ -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( ) */
+1 -1
View File
@@ -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( ) */
+1 -1
View File
@@ -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( ) */
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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 */
+977 -28
View File
File diff suppressed because it is too large Load Diff
+485 -23
View File
@@ -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
View File
@@ -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 */
+277 -48
View File
@@ -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 */
+15 -11
View File
@@ -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,
+6 -2
View File
@@ -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
+10 -6
View File
@@ -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;
+319 -3
View File
@@ -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
+4 -2
View File
@@ -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;
+1 -1
View File
@@ -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( ) */
+1 -1
View File
@@ -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( ) */
+1 -1
View File
@@ -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( ) */
File diff suppressed because it is too large Load Diff
+6
View File
@@ -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
View File
@@ -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 */
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+2
View File
@@ -22,6 +22,8 @@ if (NOT USE_SYSTEM_LIBPNG)
add_subdirectory( 3rdparty/libpng )
endif()
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")
+1 -4
View File
@@ -25,7 +25,7 @@ __Windows__
* [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
__Linux__
* GCC 5.1+ or Clang 3.5.0+
* 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 libopenal-dev libwxgtk3.0-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev`
* Arch: `sudo pacman -S glew openal wxgtk cmake llvm`
@@ -55,6 +55,3 @@ Build against the shared libpng instead of using the builtin one. libpng 1.6+ hi
- ```-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.
### Support
* [Donate by PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MPJ3S9XQXCE3G)
+96 -41
View File
@@ -1,7 +1,6 @@
#pragma once
#include "types.h"
#include "Platform.h"
// Helper class, provides access to compiler-specific atomic intrinsics
template<typename T, std::size_t Size>
@@ -143,26 +142,38 @@ struct atomic_storage
return atomic_storage<T>::sub_fetch(dest, 1);
}
static inline bool test_and_set(T& dest, T mask)
{
return (atomic_storage<T>::fetch_or(dest, mask) & mask) != 0;
}
static inline bool test_and_reset(T& dest, T mask)
{
return (atomic_storage<T>::fetch_and(dest, ~mask) & mask) != 0;
}
static inline bool test_and_complement(T& dest, T mask)
{
return (atomic_storage<T>::fetch_xor(dest, mask) & mask) != 0;
}
static inline bool bts(T& dest, uint bit)
{
const T mask = static_cast<T>(1) << bit;
return (atomic_storage<T>::fetch_or(dest, mask) & mask) != 0;
return atomic_storage<T>::test_and_set(dest, static_cast<T>(1) << bit);
}
static inline bool btr(T& dest, uint bit)
{
const T mask = static_cast<T>(1) << bit;
return (atomic_storage<T>::fetch_and(dest, ~mask) & mask) != 0;
return atomic_storage<T>::test_and_reset(dest, static_cast<T>(1) << bit);
}
static inline bool btc(T& dest, uint bit)
{
const T mask = static_cast<T>(1) << bit;
return (atomic_storage<T>::fetch_xor(dest, mask) & mask) != 0;
return atomic_storage<T>::test_and_complement(dest, static_cast<T>(1) << bit);
}
};
/* The rest: ugly MSVC intrinsics + possibly __asm__ implementations (TODO) */
/* The rest: ugly MSVC intrinsics + inline asm implementations */
template<typename T>
struct atomic_storage<T, 1> : atomic_storage<T, 0>
@@ -285,6 +296,27 @@ struct atomic_storage<T, 2> : atomic_storage<T, 0>
short r = _InterlockedDecrement16((volatile short*)&dest);
return (T&)r;
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
__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;
__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;
__asm__("lock btcw %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
return result;
}
#endif
};
@@ -363,6 +395,27 @@ struct atomic_storage<T, 4> : atomic_storage<T, 0>
{
return _interlockedbittestandreset((volatile long*)&dest, bit) != 0;
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
__asm__("lock btsl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
return result;
}
static inline bool btr(T& dest, uint bit)
{
bool result;
__asm__("lock btrl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
return result;
}
static inline bool btc(T& dest, uint bit)
{
bool result;
__asm__("lock btcl %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
return result;
}
#endif
};
@@ -441,6 +494,27 @@ struct atomic_storage<T, 8> : atomic_storage<T, 0>
{
return _interlockedbittestandreset64((volatile llong*)&dest, bit) != 0;
}
#else
static inline bool bts(T& dest, uint bit)
{
bool result;
__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;
__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;
__asm__("lock btcq %2, %0\n" "setc %1" : "+m" (dest), "=r" (result) : "Ir" (bit) : "cc");
return result;
}
#endif
};
@@ -478,6 +552,8 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
return *(T*)+cmp;
}
#endif
// TODO
};
template<typename T1, typename T2, typename>
@@ -630,21 +706,16 @@ struct atomic_test_and_set
{
bool operator()(T1& lhs, const T2& rhs) const
{
return lhs.test_and_set(rhs);
return test_and_set(lhs, rhs);
}
};
template<typename T1, typename T2>
struct atomic_test_and_set<T1, T2, std::enable_if_t<std::is_integral<T1>::value && std::is_convertible<T2, T1>::value>>
{
static inline bool op(T1& lhs, const T2& rhs)
{
return (atomic_storage<T1>::fetch_or(lhs, rhs) & rhs) != 0;
}
static constexpr auto fetch_op = &op;
static constexpr auto op_fetch = &op;
static constexpr auto atomic_op = &op;
static constexpr auto fetch_op = &atomic_storage<T1>::test_and_set;
static constexpr auto op_fetch = &atomic_storage<T1>::test_and_set;
static constexpr auto atomic_op = &atomic_storage<T1>::test_and_set;
};
template<typename T1, typename T2, typename>
@@ -652,21 +723,16 @@ struct atomic_test_and_reset
{
bool operator()(T1& lhs, const T2& rhs) const
{
return lhs.test_and_reset(rhs);
return test_and_reset(lhs, rhs);
}
};
template<typename T1, typename T2>
struct atomic_test_and_reset<T1, T2, std::enable_if_t<std::is_integral<T1>::value && std::is_convertible<T2, T1>::value>>
{
static inline bool op(T1& lhs, const T2& rhs)
{
return (atomic_storage<T1>::fetch_and(lhs, ~rhs) & rhs) != 0;
}
static constexpr auto fetch_op = &op;
static constexpr auto op_fetch = &op;
static constexpr auto atomic_op = &op;
static constexpr auto fetch_op = &atomic_storage<T1>::test_and_reset;
static constexpr auto op_fetch = &atomic_storage<T1>::test_and_reset;
static constexpr auto atomic_op = &atomic_storage<T1>::test_and_reset;
};
template<typename T1, typename T2, typename>
@@ -674,21 +740,16 @@ struct atomic_test_and_complement
{
bool operator()(T1& lhs, const T2& rhs) const
{
return lhs.test_and_complement(rhs);
return test_and_complement(lhs, rhs);
}
};
template<typename T1, typename T2>
struct atomic_test_and_complement<T1, T2, std::enable_if_t<std::is_integral<T1>::value && std::is_convertible<T2, T1>::value>>
{
static inline bool op(T1& lhs, const T2& rhs)
{
return (atomic_storage<T1>::fetch_xor(lhs, rhs) & rhs) != 0;
}
static constexpr auto fetch_op = &op;
static constexpr auto op_fetch = &op;
static constexpr auto atomic_op = &op;
static constexpr auto fetch_op = &atomic_storage<T1>::test_and_complement;
static constexpr auto op_fetch = &atomic_storage<T1>::test_and_complement;
static constexpr auto atomic_op = &atomic_storage<T1>::test_and_complement;
};
// Atomic type with lock-free and standard layout guarantees (and appropriate limitations)
@@ -954,12 +1015,6 @@ public:
return atomic_op(atomic_post_dec<type>{});
}
template<typename T2 = T>
auto test(const T2& rhs) const
{
return load().test(rhs);
}
template<typename T2 = T>
auto test_and_set(const T2& rhs)
{
+2 -2
View File
@@ -3,8 +3,8 @@
#include "Emu/System.h"
#include "AutoPause.h"
cfg::bool_entry g_cfg_debug_autopause_syscall(cfg::root.misc, "Auto Pause at System Call");
cfg::bool_entry g_cfg_debug_autopause_func_call(cfg::root.misc, "Auto Pause at Function Call");
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()
{
+235 -360
View File
@@ -1,56 +1,58 @@
#pragma once
#include "types.h"
#include "Platform.h"
// 128-bit vector type and also se_storage<> storage type
union alignas(16) v128
{
char _bytes[16];
template<typename T, std::size_t N, std::size_t M>
template <typename T, std::size_t N, std::size_t M>
struct masked_array_t // array type accessed as (index ^ M)
{
T m_data[N];
public:
T& operator [](std::size_t index)
T& operator[](std::size_t index)
{
return m_data[index ^ M];
}
const T& operator [](std::size_t index) const
const T& operator[](std::size_t index) const
{
return m_data[index ^ M];
}
};
#if IS_LE_MACHINE == 1
template<typename T, std::size_t N = 16 / sizeof(T)> using normal_array_t = masked_array_t<T, N, 0>;
template<typename T, std::size_t N = 16 / sizeof(T)> using reversed_array_t = masked_array_t<T, N, N - 1>;
template <typename T, std::size_t N = 16 / sizeof(T)>
using normal_array_t = masked_array_t<T, N, 0>;
template <typename T, std::size_t N = 16 / sizeof(T)>
using reversed_array_t = masked_array_t<T, N, N - 1>;
#endif
normal_array_t<u64> _u64;
normal_array_t<s64> _s64;
normal_array_t<u64> _u64;
normal_array_t<s64> _s64;
reversed_array_t<u64> u64r;
reversed_array_t<s64> s64r;
normal_array_t<u32> _u32;
normal_array_t<s32> _s32;
normal_array_t<u32> _u32;
normal_array_t<s32> _s32;
reversed_array_t<u32> u32r;
reversed_array_t<s32> s32r;
normal_array_t<u16> _u16;
normal_array_t<s16> _s16;
normal_array_t<u16> _u16;
normal_array_t<s16> _s16;
reversed_array_t<u16> u16r;
reversed_array_t<s16> s16r;
normal_array_t<u8> _u8;
normal_array_t<s8> _s8;
reversed_array_t<u8> u8r;
reversed_array_t<s8> s8r;
normal_array_t<u8> _u8;
normal_array_t<s8> _s8;
reversed_array_t<u8> u8r;
reversed_array_t<s8> s8r;
normal_array_t<f32> _f;
normal_array_t<f64> _d;
normal_array_t<f32> _f;
normal_array_t<f64> _d;
reversed_array_t<f32> fr;
reversed_array_t<f64> dr;
@@ -80,7 +82,7 @@ union alignas(16) v128
return (data & mask) != 0;
}
bit_element& operator =(const bool right)
bit_element& operator=(const bool right)
{
if (right)
{
@@ -93,7 +95,7 @@ union alignas(16) v128
return *this;
}
bit_element& operator =(const bit_element& right)
bit_element& operator=(const bit_element& right)
{
if (right)
{
@@ -108,7 +110,7 @@ union alignas(16) v128
};
// Index 0 returns the MSB and index 127 returns the LSB
bit_element operator [](u32 index)
bit_element operator[](u32 index)
{
#if IS_LE_MACHINE == 1
return bit_element(m_data[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F));
@@ -116,14 +118,13 @@ union alignas(16) v128
}
// Index 0 returns the MSB and index 127 returns the LSB
bool operator [](u32 index) const
bool operator[](u32 index) const
{
#if IS_LE_MACHINE == 1
return (m_data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
#endif
}
}
_bit;
} _bit;
static v128 from64(u64 _0, u64 _1 = 0)
{
@@ -277,12 +278,12 @@ union alignas(16) v128
return fromV(_mm_cmpeq_epi32(left.vi, right.vi));
}
bool operator ==(const v128& right) const
bool operator==(const v128& right) const
{
return _u64[0] == right._u64[0] && _u64[1] == right._u64[1];
}
bool operator !=(const v128& right) const
bool operator!=(const v128& right) const
{
return _u64[0] != right._u64[0] || _u64[1] != right._u64[1];
}
@@ -298,43 +299,69 @@ union alignas(16) v128
_u64[0] = 0;
_u64[1] = 0;
}
std::string to_hex() const;
std::string to_xyzw() const;
};
inline v128 operator |(const v128& left, const v128& right)
inline v128 operator|(const v128& left, const v128& right)
{
return v128::fromV(_mm_or_si128(left.vi, right.vi));
}
inline v128 operator &(const v128& left, const v128& right)
inline v128 operator&(const v128& left, const v128& right)
{
return v128::fromV(_mm_and_si128(left.vi, right.vi));
}
inline v128 operator ^(const v128& left, const v128& right)
inline v128 operator^(const v128& left, const v128& right)
{
return v128::fromV(_mm_xor_si128(left.vi, right.vi));
}
inline v128 operator ~(const v128& other)
inline v128 operator~(const v128& other)
{
return v128::from64(~other._u64[0], ~other._u64[1]);
}
#define IS_INTEGER(t) (std::is_integral<t>::value || std::is_enum<t>::value)
#define IS_BINARY_COMPARABLE(t1, t2) (IS_INTEGER(t1) && IS_INTEGER(t2) && sizeof(t1) == sizeof(t2))
template<typename T, std::size_t Size = sizeof(T)>
template <typename T, std::size_t Align, std::size_t Size>
struct se_storage
{
static_assert(!Size, "Bad se_storage<> type");
using type = std::aligned_storage_t<Size, Align>;
// Unoptimized generic byteswap for unaligned data
static void reverse(u8* dst, const u8* src)
{
for (std::size_t i = 0; i < Size; i++)
{
dst[i] = src[Size - 1 - i];
}
}
static type to(const T& src)
{
type result;
reverse(reinterpret_cast<u8*>(&result), reinterpret_cast<const u8*>(&src));
return result;
}
static T from(const type& src)
{
T result;
reverse(reinterpret_cast<u8*>(&result), reinterpret_cast<const u8*>(&src));
return result;
}
static type copy(const type& src)
{
type result;
for (std::size_t i = 0; i < Size; i++)
{
reinterpret_cast<u8*>(&result)[i] = reinterpret_cast<const u8*>(&src)[i];
}
return result;
}
};
template<typename T>
struct se_storage<T, 2>
template <typename T>
struct se_storage<T, 2, 2>
{
using type = u16;
@@ -357,10 +384,15 @@ struct se_storage<T, 2>
const u16 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 4>
template <typename T>
struct se_storage<T, 4, 4>
{
using type = u32;
@@ -383,10 +415,15 @@ struct se_storage<T, 4>
const u32 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 8>
template <typename T>
struct se_storage<T, 8, 8>
{
using type = u64;
@@ -409,10 +446,15 @@ struct se_storage<T, 8>
const u64 result = swap(src);
return reinterpret_cast<const T&>(result);
}
static inline T copy(const T& src)
{
return src;
}
};
template<typename T>
struct se_storage<T, 16>
template <typename T>
struct se_storage<T, 16, 16>
{
using type = v128;
@@ -431,43 +473,20 @@ struct se_storage<T, 16>
const v128 result = swap(src);
return reinterpret_cast<const T&>(result);
}
};
template<typename T> using se_storage_t = typename se_storage<T>::type;
template<typename T1, typename T2>
struct se_convert
{
using type_from = std::remove_cv_t<T1>;
using type_to = std::remove_cv_t<T2>;
using stype_from = se_storage_t<std::remove_cv_t<T1>>;
using stype_to = se_storage_t<std::remove_cv_t<T2>>;
using storage_from = se_storage<std::remove_cv_t<T1>>;
using storage_to = se_storage<std::remove_cv_t<T2>>;
static inline std::enable_if_t<std::is_same<type_from, type_to>::value, stype_to> convert(const stype_from& data)
static inline T copy(const T& src)
{
return data;
}
static inline stype_to convert(const stype_from& data, ...)
{
return storage_to::to(storage_from::from(data));
return src;
}
};
static struct se_raw_tag_t {} constexpr se_raw{};
template<typename T, bool Se = true>
class se_t;
// Switched endianness
template<typename T>
class se_t<T, true>
template <typename T, std::size_t Align>
class se_t<T, true, Align>
{
using type = typename std::remove_cv<T>::type;
using stype = se_storage_t<type>;
using storage = se_storage<type>;
using stype = typename se_storage<type, Align>::type;
using storage = se_storage<type, Align>;
stype m_data;
@@ -476,24 +495,6 @@ class se_t<T, true>
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
template<typename T2, typename = void>
struct bool_converter
{
static inline bool to_bool(const se_t<T2>& value)
{
return static_cast<bool>(value.value());
}
};
template<typename T2>
struct bool_converter<T2, std::enable_if_t<std::is_integral<T2>::value>>
{
static inline bool to_bool(const se_t<T2>& value)
{
return value.m_data != 0;
}
};
public:
se_t() = default;
@@ -503,27 +504,15 @@ public:
: m_data(storage::to(value))
{
}
// Construct directly from raw data (don't use)
constexpr se_t(const stype& raw_value, const se_raw_tag_t&)
: m_data(raw_value)
{
}
type value() const
{
return storage::from(m_data);
}
// Access underlying raw data (don't use)
constexpr const stype& raw_data() const noexcept
{
return m_data;
}
se_t& operator =(const se_t&) = default;
se_t& operator=(const se_t&) = default;
se_t& operator =(type value)
se_t& operator=(type value)
{
return m_data = storage::to(value), *this;
}
@@ -534,181 +523,127 @@ public:
{
return storage::from(m_data);
}
// Optimization
explicit operator bool() const
{
return bool_converter<type>::to_bool(*this);
}
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator &=(const se_t<T2>& right)
{
return m_data &= right.raw_data(), *this;
}
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(CT right)
{
return m_data &= storage::to(right), *this;
}
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator |=(const se_t<T2>& right)
{
return m_data |= right.raw_data(), *this;
}
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(CT right)
{
return m_data |= storage::to(right), *this;
}
// Optimization
template<typename T2>
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator ^=(const se_t<T2>& right)
{
return m_data ^= right.raw_data(), *this;
}
// Optimization
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(CT right)
{
return m_data ^= storage::to(right), *this;
}
};
// Native endianness
template<typename T>
class se_t<T, false>
template <typename T, std::size_t Align>
class se_t<T, false, Align>
{
using type = typename std::remove_cv<T>::type;
using stype = typename se_storage<type, Align>::type;
using storage = se_storage<type, Align>;
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
type m_data;
stype m_data;
public:
se_t() = default;
constexpr se_t(type value)
: m_data(value)
se_t(type value)
: m_data(reinterpret_cast<const stype&>(value))
{
}
// Construct directly from raw data (don't use)
constexpr se_t(const type& raw_value, const se_raw_tag_t&)
: m_data(raw_value)
type value() const
{
return storage::copy(reinterpret_cast<const type&>(m_data));
}
constexpr type value() const
{
return m_data;
}
se_t& operator=(const se_t& value) = default;
// Access underlying raw data (don't use)
constexpr const type& raw_data() const noexcept
se_t& operator=(type value)
{
return m_data;
}
se_t& operator =(const se_t& value) = default;
se_t& operator =(type value)
{
return m_data = value, *this;
return m_data = reinterpret_cast<const stype&>(value), *this;
}
using simple_type = simple_t<T>;
constexpr operator type() const
operator type() const
{
return m_data;
}
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(const CT& right)
{
return m_data &= right, *this;
}
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(const CT& right)
{
return m_data |= right, *this;
}
template<typename CT>
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(const CT& right)
{
return m_data ^= right, *this;
return storage::copy(reinterpret_cast<const type&>(m_data));
}
};
// se_t with native endianness (alias)
template<typename T> using nse_t = se_t<T, false>;
// se_t<> with native endianness
template <typename T, std::size_t Align = alignof(T)>
using nse_t = se_t<T, false, Align>;
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator +=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator+=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value += right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator -=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator-=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value -= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator *=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator*=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value *= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator /=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator/=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value /= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator %=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator%=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value %= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator <<=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator&=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value &= right);
}
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator|=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value |= right);
}
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator^=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value ^= right);
}
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator<<=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value <<= right);
}
template<typename T, bool Se, typename T1>
inline se_t<T, Se>& operator >>=(se_t<T, Se>& left, const T1& right)
template <typename T, bool Se, std::size_t Align, typename T1>
inline se_t<T, Se, Align>& operator>>=(se_t<T, Se, Align>& left, const T1& right)
{
auto value = left.value();
return left = (value >>= right);
}
template<typename T, bool Se>
inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
template <typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align> operator++(se_t<T, Se, Align>& left, int)
{
auto value = left.value();
auto result = value++;
@@ -716,8 +651,8 @@ inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
return result;
}
template<typename T, bool Se>
inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
template <typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align> operator--(se_t<T, Se, Align>& left, int)
{
auto value = left.value();
auto result = value--;
@@ -725,173 +660,111 @@ inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
return result;
}
template<typename T, bool Se>
inline se_t<T, Se>& operator ++(se_t<T, Se>& right)
template <typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align>& operator++(se_t<T, Se, Align>& right)
{
auto value = right.value();
return right = ++value;
}
template<typename T, bool Se>
inline se_t<T, Se>& operator --(se_t<T, Se>& right)
template <typename T, bool Se, std::size_t Align>
inline se_t<T, Se, Align>& operator--(se_t<T, Se, Align>& right)
{
auto value = right.value();
return right = --value;
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator ==(const se_t<T1>& left, const se_t<T2>& right)
{
return left.raw_data() == right.raw_data();
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator ==(const se_t<T1>& left, T2 right)
{
return left.raw_data() == se_storage<T1>::to(right);
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator ==(T1 left, const se_t<T2>& right)
{
return se_storage<T2>::to(left) == right.raw_data();
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator !=(const se_t<T1>& left, const se_t<T2>& right)
{
return left.raw_data() != right.raw_data();
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator !=(const se_t<T1>& left, T2 right)
{
return left.raw_data() != se_storage<T1>::to(right);
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator !=(T1 left, const se_t<T2>& right)
{
return se_storage<T2>::to(left) != right.raw_data();
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() & right.raw_data(), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() & se_storage<T1>::to(right), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() & T2())>> operator &(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) & right.raw_data(), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() | right.raw_data(), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() | se_storage<T1>::to(right), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() | T2())>> operator |(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) | right.raw_data(), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, const se_t<T2>& right)
{
return{ left.raw_data() ^ right.raw_data(), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, T2 right)
{
return{ left.raw_data() ^ se_storage<T1>::to(right), se_raw };
}
// Optimization
template<typename T1, typename T2>
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(T1 left, const se_t<T2>& right)
{
return{ se_storage<T2>::to(left) ^ right.raw_data(), se_raw };
}
// Optimization
template<typename T>
inline std::enable_if_t<std::is_integral<T>::value && sizeof(T) >= 4, se_t<decltype(~T())>> operator ~(const se_t<T>& right)
{
return{ ~right.raw_data(), se_raw };
}
#if IS_LE_MACHINE == 1
template<typename T> using be_t = se_t<T, true>;
template<typename T> using le_t = se_t<T, false>;
template <typename T, std::size_t Align = alignof(T)>
using be_t = se_t<T, true, Align>;
template <typename T, std::size_t Align = alignof(T)>
using le_t = se_t<T, false, Align>;
#endif
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
template<typename T, bool Se, typename = void>
template <typename T, bool Se, typename = void>
struct to_se
{
template <typename T2, typename = void>
struct to_se_
{
using type = T2;
};
template <typename T2>
struct to_se_<T2, std::enable_if_t<std::is_arithmetic<T2>::value || std::is_enum<T2>::value>>
{
using type = se_t<T2, Se>;
};
// Convert arithmetic and enum types
using type = typename std::conditional<std::is_arithmetic<T>::value || std::is_enum<T>::value, se_t<T, Se>, T>::type;
using type = typename to_se_<T>::type;
};
template<bool Se> struct to_se<v128, Se> { using type = se_t<v128, Se>; };
template<bool Se> struct to_se<bool, Se> { using type = bool; };
template<bool Se> struct to_se<char, Se> { using type = char; };
template<bool Se> struct to_se<u8, Se> { using type = u8; };
template<bool Se> struct to_se<s8, Se> { using type = s8; };
template <bool Se>
struct to_se<v128, Se>
{
using type = se_t<v128, Se>;
};
template<typename T, bool Se>
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
template <bool Se>
struct to_se<u128, Se>
{
using type = se_t<u128, Se>;
};
template <bool Se>
struct to_se<s128, Se>
{
using type = se_t<s128, Se>;
};
template <bool Se>
struct to_se<bool, Se>
{
using type = bool;
};
template <bool Se>
struct to_se<char, Se>
{
using type = char;
};
template <bool Se>
struct to_se<u8, Se>
{
using type = u8;
};
template <bool Se>
struct to_se<s8, Se>
{
using type = s8;
};
template <typename T, bool Se>
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
{
// Move const qualifier
using type = const typename to_se<T, Se>::type;
};
template<typename T, bool Se>
template <typename T, bool Se>
struct to_se<volatile T, Se, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>>
{
// Move volatile qualifier
using type = volatile typename to_se<T, Se>::type;
};
template<typename T, bool Se>
template <typename T, bool Se>
struct to_se<T[], Se>
{
// Move array qualifier
using type = typename to_se<T, Se>::type[];
};
template<typename T, bool Se, std::size_t N>
template <typename T, bool Se, std::size_t N>
struct to_se<T[N], Se>
{
// Move array qualifier
@@ -900,25 +773,27 @@ struct to_se<T[N], Se>
// BE/LE aliases for to_se<>
#if IS_LE_MACHINE == 1
template<typename T> using to_be_t = typename to_se<T, true>::type;
template<typename T> using to_le_t = typename to_se<T, false>::type;
template <typename T>
using to_be_t = typename to_se<T, true>::type;
template <typename T>
using to_le_t = typename to_se<T, false>::type;
#endif
// BE/LE aliases for atomic_t
#if IS_LE_MACHINE == 1
template<typename T> using atomic_be_t = atomic_t<be_t<T>>;
template<typename T> using atomic_le_t = atomic_t<le_t<T>>;
template <typename T>
using atomic_be_t = atomic_t<be_t<T>>;
template <typename T>
using atomic_le_t = atomic_t<le_t<T>>;
#endif
// Formatting for BE/LE data
template<typename T, bool Se>
struct unveil<se_t<T, Se>, void>
template <typename T, bool Se, std::size_t Align>
struct fmt_unveil<se_t<T, Se, Align>, void>
{
static inline auto get(const se_t<T, Se>& arg)
using type = typename fmt_unveil<T>::type;
static inline auto get(const se_t<T, Se, Align>& arg)
{
return unveil<T>::get(arg);
return fmt_unveil<T>::get(arg);
}
};
#undef IS_BINARY_COMPARABLE
#undef IS_INTEGER
+34 -1
View File
@@ -9,7 +9,7 @@ struct bf_base
using vtype = simple_t<type>;
// Datatype bitsize
static constexpr uint bitmax = sizeof(T) * CHAR_BIT; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
// Field bitsize
static constexpr uint bitsize = N;
@@ -242,3 +242,36 @@ struct ff_t : bf_base<T, N>
return V;
}
};
template<typename T, uint I, uint N>
struct fmt_unveil<bf_t<T, I, N>, void>
{
using type = typename fmt_unveil<simple_t<T>>::type;
static inline auto get(const bf_t<T, I, N>& bf)
{
return fmt_unveil<type>::get(bf);
}
};
template<typename F, typename... Fields>
struct fmt_unveil<cf_t<F, Fields...>, void>
{
using type = typename fmt_unveil<simple_t<typename F::type>>::type;
static inline auto get(const cf_t<F, Fields...>& cf)
{
return fmt_unveil<type>::get(cf);
}
};
template<typename T, T V, uint N>
struct fmt_unveil<ff_t<T, V, N>, void>
{
using type = typename fmt_unveil<simple_t<T>>::type;
static inline auto get(const ff_t<T, V, N>& ff)
{
return fmt_unveil<type>::get(ff);
}
};
-258
View File
@@ -1,258 +0,0 @@
#pragma once
#include "types.h"
// Small bitset for enum class types with available values [0, BitSize).
// T must be either enum type or convertible to (registered with via simple_t<T>).
// Internal representation is single value of type T.
template<typename T, std::size_t BitSize = sizeof(T) * CHAR_BIT>
struct bitset_t
{
using type = simple_t<T>;
using under = std::underlying_type_t<type>;
enum class raw_type : under {};
static constexpr auto bitsize = BitSize;
bitset_t() = default;
constexpr bitset_t(type _enum_const)
: m_value(static_cast<type>(shift(_enum_const)))
{
}
constexpr bitset_t(raw_type raw_value)
: m_value(static_cast<T>(static_cast<under>(raw_value)))
{
}
// Get underlying value
constexpr under _value() const
{
return static_cast<under>(m_value);
}
explicit constexpr operator bool() const
{
return _value() ? true : false;
}
bitset_t& operator +=(bitset_t rhs)
{
return *this = static_cast<raw_type>(_value() | rhs._value());
}
bitset_t& operator -=(bitset_t rhs)
{
return *this = static_cast<raw_type>(_value() & ~rhs._value());
}
bitset_t& operator &=(bitset_t rhs)
{
return *this = static_cast<raw_type>(_value() & rhs._value());
}
bitset_t& operator ^=(bitset_t rhs)
{
return *this = static_cast<raw_type>(_value() ^ rhs._value());
}
friend constexpr bitset_t operator +(bitset_t lhs, bitset_t rhs)
{
return static_cast<raw_type>(lhs._value() | rhs._value());
}
friend constexpr bitset_t operator -(bitset_t lhs, bitset_t rhs)
{
return static_cast<raw_type>(lhs._value() & ~rhs._value());
}
friend constexpr bitset_t operator &(bitset_t lhs, bitset_t rhs)
{
return static_cast<raw_type>(lhs._value() & rhs._value());
}
friend constexpr bitset_t operator ^(bitset_t lhs, bitset_t rhs)
{
return static_cast<raw_type>(lhs._value() ^ rhs._value());
}
bool test(bitset_t rhs) const
{
const under v = _value();
const under s = rhs._value();
return (v & s) != 0;
}
bool test_and_set(bitset_t rhs)
{
const under v = _value();
const under s = rhs._value();
*this = static_cast<raw_type>(v | s);
return (v & s) != 0;
}
bool test_and_reset(bitset_t rhs)
{
const under v = _value();
const under s = rhs._value();
*this = static_cast<raw_type>(v & ~s);
return (v & s) != 0;
}
bool test_and_complement(bitset_t rhs)
{
const under v = _value();
const under s = rhs._value();
*this = static_cast<raw_type>(v ^ s);
return (v & s) != 0;
}
private:
static constexpr under shift(const T& value)
{
return static_cast<under>(value) < BitSize ? static_cast<under>(1) << static_cast<under>(value) : throw value;
}
T m_value;
};
template<typename T, typename RT = T>
constexpr RT make_bitset()
{
return RT{};
}
// Fold enum constants into bitset_t<> (must be implemented with constexpr initializer_list constructor instead)
template<typename T = void, typename Arg, typename... Args, typename RT = std::conditional_t<std::is_void<T>::value, bitset_t<Arg>, T>>
constexpr RT make_bitset(Arg&& _enum_const, Args&&... args)
{
return RT{ std::forward<Arg>(_enum_const) } + make_bitset<RT>(std::forward<Args>(args)...);
}
template<typename T, typename CT>
struct atomic_add<bitset_t<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
using raw_type = typename bitset_t<T>::raw_type;
static inline bitset_t<T> op1(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::fetch_or(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto fetch_op = &op1;
static inline bitset_t<T> op2(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::or_fetch(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_sub<bitset_t<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
using raw_type = typename bitset_t<T>::raw_type;
static inline bitset_t<T> op1(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), ~right._value()));
}
static constexpr auto fetch_op = &op1;
static inline bitset_t<T> op2(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), ~right._value()));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_and<bitset_t<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
using raw_type = typename bitset_t<T>::raw_type;
static inline bitset_t<T> op1(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto fetch_op = &op1;
static inline bitset_t<T> op2(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T, typename CT>
struct atomic_xor<bitset_t<T>, CT, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
using raw_type = typename bitset_t<T>::raw_type;
static inline bitset_t<T> op1(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::fetch_xor(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto fetch_op = &op1;
static inline bitset_t<T> op2(bitset_t<T>& left, bitset_t<T> right)
{
return static_cast<raw_type>(atomic_storage<under>::xor_fetch(reinterpret_cast<under&>(left), right._value()));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_test_and_set<bitset_t<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
static inline bool _op(bitset_t<T>& left, const T& value)
{
return atomic_storage<under>::bts(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_reset<bitset_t<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
static inline bool _op(bitset_t<T>& left, const T& value)
{
return atomic_storage<under>::btr(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_complement<bitset_t<T>, T, std::enable_if_t<std::is_enum<T>::value>>
{
using under = typename bitset_t<T>::under;
static inline bool _op(bitset_t<T>& left, const T& value)
{
return atomic_storage<under>::btc(reinterpret_cast<under&>(left), static_cast<uint>(value));
}
static constexpr auto atomic_op = &_op;
};
+70 -4
View File
@@ -12,7 +12,7 @@ namespace cfg
{
if (_type != type::node)
{
throw std::logic_error("Invalid root node");
fmt::throw_exception<std::logic_error>("Invalid root node" HERE);
}
}
@@ -21,7 +21,7 @@ namespace cfg
{
if (!owner.m_nodes.emplace(name, this).second)
{
throw std::logic_error("Node already exists");
fmt::throw_exception<std::logic_error>("Node already exists: %s" HERE, name);
}
}
@@ -32,7 +32,7 @@ namespace cfg
return *static_cast<const node&>(*this).m_nodes.at(name);
}
throw std::logic_error("Invalid node type");
fmt::throw_exception<std::logic_error>("Invalid node type" HERE);
}
entry_base& entry_base::operator[](const char* name) const
@@ -42,7 +42,17 @@ namespace cfg
return *static_cast<const node&>(*this).m_nodes.at(name);
}
throw std::logic_error("Invalid node type");
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 entry_base::from_list(std::vector<std::string>&&)
{
fmt::throw_exception<std::logic_error>("from_list() purecall" HERE);
}
// Emit YAML
@@ -85,6 +95,62 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
return true;
}
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string& value)
{
for (u64 i = 0;; i++)
{
std::string var;
func(var, i);
if (var == value)
{
if (out) *out = i;
return true;
}
std::string hex;
fmt_class_string<u64>::format(hex, i);
if (var == hex)
{
break;
}
}
try
{
const auto val = std::stoull(value, nullptr, 0);
if (out) *out = val;
return true;
}
catch (...)
{
return false;
}
}
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
{
std::vector<std::string> result;
for (u64 i = 0;; i++)
{
std::string var;
func(var, i);
std::string hex;
fmt_class_string<u64>::format(hex, i);
if (var == hex)
{
break;
}
result.emplace_back(std::move(var));
}
return result;
}
void cfg::encode(YAML::Emitter& out, const cfg::entry_base& rhs)
{
switch (rhs.get_type())
+22 -34
View File
@@ -2,6 +2,7 @@
#include "Utilities/types.h"
#include "Utilities/Atomic.h"
#include "Utilities/StrFmt.h"
#include <initializer_list>
#include <exception>
@@ -18,6 +19,12 @@ namespace cfg
// Convert string to signed integer
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max);
// Internal hack
bool try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string&);
// Internal hack
std::vector<std::string> try_to_enum_list(decltype(&fmt_class_string<int>::format) func);
// Config tree entry type.
enum class type : uint
{
@@ -62,10 +69,7 @@ namespace cfg
}
// Try to convert from string (optional)
virtual bool from_string(const std::string&)
{
throw std::logic_error("from_string() not specified");
}
virtual bool from_string(const std::string&);
// Get string list (optional)
virtual std::vector<std::string> to_list() const
@@ -74,10 +78,7 @@ namespace cfg
}
// Set multiple values. Implementation-specific, optional.
virtual bool from_list(std::vector<std::string>&&)
{
throw std::logic_error("from_list() not specified");
}
virtual bool from_list(std::vector<std::string>&&);
};
// Config tree node which contains another nodes
@@ -179,7 +180,7 @@ namespace cfg
for (const auto& v : init)
{
// Ensure elements are unique
VERIFY(map.emplace(v.first, v.second).second);
verify(HERE), map.emplace(v.first, v.second).second;
}
return map;
@@ -216,7 +217,7 @@ namespace cfg
}
map_entry(node& owner, const std::string& name, std::size_t def_index, init_type init)
: map_entry(owner, name, def_index < init.size() ? (init.begin() + def_index)->first : throw std::logic_error("Invalid default value index"), init)
: map_entry(owner, name, (init.begin() + (def_index < init.size() ? def_index : 0))->first, init)
{
}
@@ -296,26 +297,20 @@ namespace cfg
std::string to_string() const override
{
for (std::size_t i = 0; i < sizeof(bijective<T, const char*>::map) / sizeof(bijective_pair<T, const char*>); i++)
{
if (bijective<T, const char*>::map[i].v1 == m_value)
{
return bijective<T, const char*>::map[i].v2;
}
}
return{}; // TODO: ???
std::string result;
fmt_class_string<T>::format(result, fmt_unveil<T>::get(m_value));
return result; // TODO: ???
}
bool from_string(const std::string& value) override
{
for (std::size_t i = 0; i < sizeof(bijective<T, const char*>::map) / sizeof(bijective_pair<T, const char*>); i++)
u64 result;
if (try_to_enum_value(&result, &fmt_class_string<T>::format, value))
{
if (bijective<T, const char*>::map[i].v2 == value)
{
m_value = bijective<T, const char*>::map[i].v1;
return true;
}
// No narrowing check, it's hard to do right there
m_value = static_cast<T>(static_cast<std::underlying_type_t<T>>(result));
return true;
}
return false;
@@ -323,14 +318,7 @@ namespace cfg
std::vector<std::string> to_list() const override
{
std::vector<std::string> result;
for (std::size_t i = 0; i < sizeof(bijective<T, const char*>::map) / sizeof(bijective_pair<T, const char*>); i++)
{
result.emplace_back(bijective<T, const char*>::map[i].v2);
}
return result;
return try_to_enum_list(&fmt_class_string<T>::format);
}
};
@@ -364,7 +352,7 @@ namespace cfg
{
if (value < Min || value > Max)
{
throw fmt::exception("Value out of the valid range: %lld" HERE, s64{ value });
fmt::throw_exception("Value out of the valid range: %lld" HERE, s64{ value });
}
m_value = value;
+185 -155
View File
@@ -1,7 +1,8 @@
#include "File.h"
#include "StrFmt.h"
#include "Macro.h"
#include "SharedMutex.h"
#include "BEType.h"
#include "Crypto/sha1.h"
#include <unordered_map>
#include <algorithm>
@@ -14,36 +15,35 @@
static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
{
const auto buf_size = source.size() + 1; // size + null terminator
// String size + null terminator
const std::size_t buf_size = source.size() + 1;
const int size = source.size() < INT_MAX ? static_cast<int>(buf_size) : throw fmt::exception("to_wchar(): invalid source length (0x%llx)", source.size());
// Safe size
const int size = narrow<int>(buf_size, "to_wchar" HERE);
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]); // allocate buffer assuming that length is the max possible size
// Buffer for max possible output length
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]);
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
{
throw fmt::exception("to_wchar(): MultiByteToWideChar() failed: error %u.", GetLastError());
}
verify("to_wchar" HERE), MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size);
return buffer;
}
static void to_utf8(std::string& result, const wchar_t* source)
static void to_utf8(std::string& out, const wchar_t* source)
{
const auto length = std::wcslen(source);
// String size
const std::size_t length = std::wcslen(source);
const int buf_size = length <= INT_MAX / 3 ? static_cast<int>(length) * 3 + 1 : throw fmt::exception("to_utf8(): invalid source length (0x%llx)", length);
// Safe buffer size for max possible output length (including null terminator)
const int buf_size = narrow<int>(length * 3 + 1, "to_utf8" HERE);
result.resize(buf_size); // set max possible length for utf-8 + null terminator
// Resize buffer
out.resize(buf_size - 1);
if (const int nwritten = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &result.front(), buf_size, NULL, NULL))
{
result.resize(nwritten - 1); // fix the size, remove null terminator
}
else
{
throw fmt::exception("to_utf8(): WideCharToMultiByte() failed: error %u.", GetLastError());
}
const int result = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &out.front(), buf_size, NULL, NULL);
// Fix the size
out.resize(verify("to_utf8" HERE, result) - 1);
}
static time_t to_time(const ULARGE_INTEGER& ft)
@@ -78,7 +78,9 @@ static fs::error to_error(DWORD e)
case ERROR_ALREADY_EXISTS: return fs::error::exist;
case ERROR_FILE_EXISTS: return fs::error::exist;
case ERROR_NEGATIVE_SEEK: return fs::error::inval;
default: throw fmt::exception("Unknown Win32 error: %u.", e);
case ERROR_DIRECTORY: return fs::error::inval;
case ERROR_INVALID_NAME: return fs::error::inval;
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
}
}
@@ -107,7 +109,7 @@ 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;
default: throw fmt::exception("Unknown system error: %d.", e);
default: fmt::throw_exception("Unknown system error: %d.", e);
}
}
@@ -170,7 +172,7 @@ std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device)
{
EXPECTS(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
verify(HERE), name.size() > 2, name[0] == '/', name[1] == '/', name.find('/', 2) == -1;
return get_device_manager().set_device(name, device);
}
@@ -199,33 +201,6 @@ std::string fs::get_parent_dir(const std::string& path)
}
}
static const auto test_get_parent_dir = []() -> bool
{
// Success:
VERIFY(fs::get_parent_dir("/x/y///") == "/x");
VERIFY(fs::get_parent_dir("/x/y/") == "/x");
VERIFY(fs::get_parent_dir("/x/y") == "/x");
VERIFY(fs::get_parent_dir("x:/y") == "x:");
VERIFY(fs::get_parent_dir("//x/y") == "//x");
// Failure:
VERIFY(fs::get_parent_dir("").empty());
VERIFY(fs::get_parent_dir("x/").empty());
VERIFY(fs::get_parent_dir("x").empty());
VERIFY(fs::get_parent_dir("x///").empty());
VERIFY(fs::get_parent_dir("/x/").empty());
VERIFY(fs::get_parent_dir("/x").empty());
VERIFY(fs::get_parent_dir("/").empty());
VERIFY(fs::get_parent_dir("//").empty());
VERIFY(fs::get_parent_dir("//x").empty());
VERIFY(fs::get_parent_dir("//x/").empty());
VERIFY(fs::get_parent_dir("///").empty());
VERIFY(fs::get_parent_dir("///x").empty());
VERIFY(fs::get_parent_dir("///x/").empty());
return false;
}();
bool fs::stat(const std::string& path, stat_t& info)
{
if (auto device = get_virtual_device(path))
@@ -461,7 +436,7 @@ bool fs::rename(const std::string& from, const std::string& to)
if (device != get_virtual_device(to))
{
throw fmt::exception("fs::rename() between different devices not implemented.\nFrom: %s\nTo: %s", from, to);
fmt::throw_exception("fs::rename() between different devices not implemented.\nFrom: %s\nTo: %s", from, to);
}
if (device)
@@ -494,7 +469,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
if (device != get_virtual_device(to) || device) // TODO
{
throw fmt::exception("fs::copy_file() for virtual devices not implemented.\nFrom: %s\nTo: %s", from, to);
fmt::throw_exception("fs::copy_file() for virtual devices not implemented.\nFrom: %s\nTo: %s", from, to);
}
#ifdef _WIN32
@@ -618,15 +593,15 @@ bool fs::truncate_file(const std::string& path, u64 length)
void fs::file::xnull() const
{
throw std::logic_error("fs::file is null");
fmt::throw_exception<std::logic_error>("fs::file is null");
}
void fs::file::xfail() const
{
throw fmt::exception("Unexpected fs::error %u", g_tls_error);
fmt::throw_exception("Unexpected fs::error %s", g_tls_error);
}
bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
{
if (auto device = get_virtual_device(path))
{
@@ -641,25 +616,25 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
#ifdef _WIN32
DWORD access = 0;
if (mode & fs::read) access |= GENERIC_READ;
if (mode & fs::write) access |= mode & fs::append ? FILE_APPEND_DATA : GENERIC_WRITE;
if (test(mode & fs::read)) access |= GENERIC_READ;
if (test(mode & fs::write)) access |= test(mode & fs::append) ? FILE_APPEND_DATA : GENERIC_WRITE;
DWORD disp = 0;
if (mode & fs::create)
if (test(mode & fs::create))
{
disp =
mode & fs::excl ? CREATE_NEW :
mode & fs::trunc ? CREATE_ALWAYS : OPEN_ALWAYS;
test(mode & fs::excl) ? CREATE_NEW :
test(mode & fs::trunc) ? CREATE_ALWAYS : OPEN_ALWAYS;
}
else
{
if (mode & fs::excl)
if (test(mode & fs::excl))
{
g_tls_error = error::inval;
return false;
}
disp = mode & fs::trunc ? TRUNCATE_EXISTING : OPEN_EXISTING;
disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING;
}
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -688,10 +663,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
stat_t stat() override
{
FILE_BASIC_INFO basic_info;
if (!GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::stat" HERE), GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
stat_t info;
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
@@ -722,27 +694,17 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
return false;
}
const BOOL result = SetEndOfFile(m_handle); // change file size
if (!result || !SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN)) // restore position
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return result != FALSE;
verify("file::trunc" HERE), SetEndOfFile(m_handle), SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN);
return true;
}
u64 read(void* buffer, u64 count) override
{
// TODO (call ReadFile multiple times if count is too big)
const int size = ::narrow<int>(count, "Too big count" HERE);
EXPECTS(size >= 0);
const int size = narrow<int>(count, "file::read" HERE);
DWORD nread;
if (!ReadFile(m_handle, buffer, size, &nread, NULL))
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::read" HERE), ReadFile(m_handle, buffer, size, &nread, NULL);
return nread;
}
@@ -750,14 +712,10 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override
{
// TODO (call WriteFile multiple times if count is too big)
const int size = ::narrow<int>(count, "Too big count" HERE);
EXPECTS(size >= 0);
const int size = narrow<int>(count, "file::write" HERE);
DWORD nwritten;
if (!WriteFile(m_handle, buffer, size, &nwritten, NULL))
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::write" HERE), WriteFile(m_handle, buffer, size, &nwritten, NULL);
return nwritten;
}
@@ -771,12 +729,9 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
whence == seek_set ? FILE_BEGIN :
whence == seek_cur ? FILE_CURRENT :
whence == seek_end ? FILE_END :
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::seek" HERE), SetFilePointerEx(m_handle, pos, &pos, mode);
return pos.QuadPart;
}
@@ -784,10 +739,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
u64 size() override
{
LARGE_INTEGER size;
if (!GetFileSizeEx(m_handle, &size))
{
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::size" HERE), GetFileSizeEx(m_handle, &size);
return size.QuadPart;
}
@@ -797,14 +749,14 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
#else
int flags = 0;
if (mode & fs::read && mode & fs::write) flags |= O_RDWR;
else if (mode & fs::read) flags |= O_RDONLY;
else if (mode & fs::write) flags |= O_WRONLY;
if (test(mode & fs::read) && test(mode & fs::write)) flags |= O_RDWR;
else if (test(mode & fs::read)) flags |= O_RDONLY;
else if (test(mode & fs::write)) flags |= O_WRONLY;
if (mode & fs::append) flags |= O_APPEND;
if (mode & fs::create) flags |= O_CREAT;
if (mode & fs::trunc) flags |= O_TRUNC;
if (mode & fs::excl) flags |= O_EXCL;
if (test(mode & fs::append)) flags |= O_APPEND;
if (test(mode & fs::create)) flags |= O_CREAT;
if (test(mode & fs::trunc)) flags |= O_TRUNC;
if (test(mode & fs::excl)) flags |= O_EXCL;
const int fd = ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
@@ -832,10 +784,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
stat_t stat() override
{
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
throw fmt::exception("System error: %d." HERE, errno);
}
verify("file::stat" HERE), ::fstat(m_fd, &file_info) == 0;
stat_t info;
info.is_directory = S_ISDIR(file_info.st_mode);
@@ -862,10 +811,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
u64 read(void* buffer, u64 count) override
{
const auto result = ::read(m_fd, buffer, count);
if (result == -1)
{
throw fmt::exception("System error: %d." HERE, errno);
}
verify("file::read" HERE), result != -1;
return result;
}
@@ -873,10 +819,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override
{
const auto result = ::write(m_fd, buffer, count);
if (result == -1)
{
throw fmt::exception("System error: %d." HERE, errno);
}
verify("file::write" HERE), result != -1;
return result;
}
@@ -887,13 +830,10 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
whence == seek_set ? SEEK_SET :
whence == seek_cur ? SEEK_CUR :
whence == seek_end ? SEEK_END :
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
const auto result = ::lseek(m_fd, offset, mode);
if (result == -1)
{
throw fmt::exception("System error: %d." HERE, errno);
}
verify("file::seek" HERE), result != -1;
return result;
}
@@ -901,10 +841,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
u64 size() override
{
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
throw fmt::exception("System error: %d." HERE, errno);
}
verify("file::size" HERE), ::fstat(m_fd, &file_info) == 0;
return file_info.st_size;
}
@@ -934,26 +871,27 @@ fs::file::file(const void* ptr, std::size_t size)
fs::stat_t stat() override
{
throw std::logic_error("Not supported" HERE);
fmt::throw_exception<std::logic_error>("Not supported" HERE);
}
bool trunc(u64 length) override
{
throw std::logic_error("Not allowed" HERE);
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
}
u64 read(void* buffer, u64 count) override
{
const u64 start = m_pos;
const u64 end = seek(count, fs::seek_cur);
const u64 read_size = end >= start ? end - start : throw std::logic_error("Stream overflow" HERE);
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
{
throw std::logic_error("Not allowed" HERE);
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
}
u64 seek(s64 offset, fs::seek_mode whence) override
@@ -962,7 +900,7 @@ fs::file::file(const void* ptr, std::size_t size)
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) :
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
}
u64 size() override
@@ -976,7 +914,7 @@ fs::file::file(const void* ptr, std::size_t size)
void fs::dir::xnull() const
{
throw std::logic_error("fs::dir is null");
fmt::throw_exception<std::logic_error>("fs::dir is null");
}
bool fs::dir::open(const std::string& path)
@@ -994,7 +932,7 @@ bool fs::dir::open(const std::string& path)
#ifdef _WIN32
WIN32_FIND_DATAW found;
const auto handle = FindFirstFileW(to_wchar(path + "/*").get(), &found);
const auto handle = FindFirstFileExW(to_wchar(path + "/*").get(), FindExInfoBasic, &found, FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
if (handle == INVALID_HANDLE_VALUE)
{
@@ -1004,8 +942,6 @@ bool fs::dir::open(const std::string& path)
class windows_dir final : public dir_base
{
const HANDLE m_handle;
std::vector<dir_entry> m_entries;
std::size_t m_pos = 0;
@@ -1025,33 +961,24 @@ bool fs::dir::open(const std::string& path)
}
public:
windows_dir(HANDLE handle, const WIN32_FIND_DATAW& found)
: m_handle(handle)
windows_dir(HANDLE handle, WIN32_FIND_DATAW& found)
{
add_entry(found);
}
~windows_dir()
{
FindClose(m_handle);
while (FindNextFileW(handle, &found))
{
add_entry(found);
}
verify("dir::read" HERE), ERROR_NO_MORE_FILES == GetLastError();
FindClose(handle);
}
bool read(dir_entry& out) override
{
if (m_pos == m_entries.size())
if (m_pos >= m_entries.size())
{
WIN32_FIND_DATAW found;
if (!FindNextFileW(m_handle, &found))
{
if (ERROR_NO_MORE_FILES == GetLastError())
{
return false;
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
add_entry(found);
return false;
}
out = m_entries[m_pos++];
@@ -1098,10 +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)
{
throw fmt::exception("System error: %d." HERE, errno);
}
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);
@@ -1207,6 +1131,78 @@ const std::string& fs::get_executable_dir()
return s_dir;
}
std::string fs::get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix)
{
static const std::string s_dir = []
{
const std::string& dir = get_config_dir() + "/data/";
if (!is_dir(dir) && !create_path(dir))
{
return get_config_dir();
}
return dir;
}();
std::vector<u8> buf;
buf.reserve(location.size() + 1);
// Normalize location
for (char c : location)
{
#ifdef _WIN32
if (c == '/' || c == '\\')
#else
if (c == '/')
#endif
{
if (buf.empty() || buf.back() != '/')
{
buf.push_back('/');
}
continue;
}
buf.push_back(c);
}
// Calculate hash
u8 hash[20];
sha1(buf.data(), buf.size(), hash);
// Concatenate
std::string&& result = fmt::format("%s%s/%016llx%08x-%s/", s_dir, prefix, reinterpret_cast<be_t<u64>&>(hash[0]), reinterpret_cast<be_t<u32>&>(hash[8]), suffix);
if (!is_dir(result))
{
// Create dir if necessary
if (create_path(result))
{
// Acknowledge original location
file(result + ".location", rewrite).write(buf);
}
}
return result;
}
std::string fs::get_data_dir(const std::string& prefix, const std::string& path)
{
#ifdef _WIN32
const auto& delim = "/\\";
#else
const auto& delim = "/";
#endif
// Extract file name and location
const std::string& location = fs::get_parent_dir(path);
const std::size_t name_pos = path.find_first_not_of(delim, location.size());
return fs::get_data_dir(prefix, location, name_pos == -1 ? std::string{} : path.substr(name_pos));
}
void fs::remove_all(const std::string& path, bool remove_root)
{
for (const auto& entry : dir(path))
@@ -1257,3 +1253,37 @@ u64 fs::get_dir_size(const std::string& path)
return result;
}
template<>
void fmt_class_string<fs::seek_mode>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto arg)
{
switch (arg)
{
STR_CASE(fs::seek_mode::seek_set);
STR_CASE(fs::seek_mode::seek_cur);
STR_CASE(fs::seek_mode::seek_end);
}
return unknown;
});
}
template<>
void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto arg)
{
switch (arg)
{
case fs::error::ok: return "OK";
case fs::error::inval: return "Invalid arguments";
case fs::error::noent: return "Not found";
case fs::error::exist: return "Already exists";
}
return unknown;
});
}
+22 -15
View File
@@ -1,17 +1,16 @@
#pragma once
#include "types.h"
#include "bit_set.h"
#include <memory>
#include <string>
#include <vector>
#include <type_traits>
#include "types.h"
#include "BitSet.h"
namespace fs
{
// File open mode flags
enum struct open_mode : u32
enum class open_mode : u32
{
read,
write,
@@ -19,16 +18,18 @@ namespace fs
create,
trunc,
excl,
__bitset_enum_max
};
constexpr bitset_t<open_mode> read = open_mode::read; // Enable reading
constexpr bitset_t<open_mode> write = open_mode::write; // Enable writing
constexpr bitset_t<open_mode> append = open_mode::append; // Always append to the end of the file
constexpr bitset_t<open_mode> create = open_mode::create; // Create file if it doesn't exist
constexpr bitset_t<open_mode> trunc = open_mode::trunc; // Clear opened file if it's not empty
constexpr bitset_t<open_mode> excl = open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr auto read = +open_mode::read; // Enable reading
constexpr auto write = +open_mode::write; // Enable writing
constexpr auto append = +open_mode::append; // Always append to the end of the file
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 bitset_t<open_mode> rewrite = write + create + trunc;
constexpr auto rewrite = open_mode::write + open_mode::create + open_mode::trunc;
// File seek mode
enum class seek_mode : u32
@@ -93,7 +94,7 @@ namespace fs
virtual bool remove(const std::string& path) = 0;
virtual bool trunc(const std::string& path, u64 length) = 0;
virtual std::unique_ptr<file_base> open(const std::string& path, bitset_t<open_mode> mode) = 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;
};
@@ -151,13 +152,13 @@ namespace fs
file() = default;
// Open file with specified mode
explicit file(const std::string& path, bitset_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, bitset_t<open_mode> mode = ::fs::read);
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);
@@ -439,6 +440,12 @@ namespace fs
// 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);
// Get data/cache directory for specified prefix and path (suffix will be filename)
std::string get_data_dir(const std::string& prefix, const std::string& path);
// Delete directory and all its contents recursively
void remove_all(const std::string& path, bool remove_root = true);
+41 -24
View File
@@ -7,7 +7,6 @@
#include <array>
#include "types.h"
#include "Macro.h"
#include "StrFmt.h"
#include "File.h"
#include "Log.h"
@@ -46,7 +45,7 @@ static const u64 s_memory_size = 0x20000000;
static void* const s_memory = []() -> void*
{
#ifdef _WIN32
for (u64 addr = 0x1000000; addr <= 0x60000000; addr += 0x1000000)
for (u64 addr = 0x10000000; addr <= 0x60000000; addr += 0x1000000)
{
if (VirtualAlloc((void*)addr, s_memory_size, MEM_RESERVE, PAGE_NOACCESS))
{
@@ -60,6 +59,10 @@ static void* const s_memory = []() -> void*
#endif
}();
// Code section
static u8* s_code_addr;
static u64 s_code_size;
// EH frames
static u8* s_unwind_info;
static u64 s_unwind_size;
@@ -80,7 +83,7 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
[[noreturn]] static void null()
{
throw std::runtime_error("Null function" HERE);
fmt::throw_exception("Null function" HERE);
}
virtual u64 getSymbolAddress(const std::string& name) override
@@ -121,11 +124,14 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
if (::mprotect(m_next, size, PROT_READ | PROT_WRITE | PROT_EXEC))
#endif
{
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at 0x%p", m_next);
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at %p", m_next);
return nullptr;
}
LOG_SUCCESS(GENERAL, "LLVM: Code section %u '%s' allocated -> 0x%p (size=0x%llx, aligned 0x%x)", sec_id, sec_name.data(), m_next, size, align);
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);
}
@@ -140,23 +146,36 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
return nullptr;
}
if (!is_ro)
{
LOG_ERROR(GENERAL, "LLVM: Writeable data section not supported!");
}
#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 0x%p", m_next);
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at %p", m_next);
return nullptr;
}
LOG_SUCCESS(GENERAL, "LLVM: Data section %u '%s' allocated -> 0x%p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), m_next, size, align, is_ro ? "ro" : "rw");
LOG_SUCCESS(GENERAL, "LLVM: Data section %u '%s' allocated -> %p (size=0x%llx, aligned 0x%x, %s)", sec_id, sec_name.data(), m_next, size, align, is_ro ? "ro" : "rw");
return (u8*)std::exchange(m_next, (void*)next);
}
virtual bool finalizeMemory(std::string* = nullptr) override
{
// TODO: make sections read-only when necessary
// 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
return false;
}
@@ -180,17 +199,17 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
#ifdef _WIN32
if (!RtlDeleteFunctionTable(s_unwind.data()))
{
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable(addr=0x%p) failed! Error %u", s_unwind_info, GetLastError());
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
}
if (!VirtualFree(s_memory, 0, MEM_DECOMMIT))
{
LOG_FATAL(GENERAL, "VirtualFree(0x%p) failed! Error %u", s_memory, GetLastError());
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(0x%p) failed! Error %d", s_memory, errno);
LOG_FATAL(GENERAL, "mprotect(%p) failed! Error %d", s_memory, errno);
}
// TODO: unregister EH frames if necessary
@@ -216,7 +235,7 @@ static EventListener s_listener;
jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unordered_map<std::string, std::uintptr_t>&& table)
{
EXPECTS(s_memory);
verify(HERE), s_memory;
std::string result;
@@ -231,14 +250,13 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
.setErrorStr(&result)
.setMCJITMemoryManager(std::make_unique<MemoryManager>(std::move(table)))
.setOptLevel(llvm::CodeGenOpt::Aggressive)
.setRelocationModel(llvm::Reloc::PIC_)
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Medium : llvm::CodeModel::Large) // TODO
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Small : llvm::CodeModel::Large) // TODO
.setMCPU(llvm::sys::getHostCPUName())
.create());
if (!m_engine)
{
throw fmt::exception("LLVM: Failed to create ExecutionEngine: %s", result);
fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result);
}
m_engine->setProcessAllSections(true); // ???
@@ -268,19 +286,17 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
func_set.emplace(pair.second);
}
// Hack (cannot obtain last function size)
func_set.emplace(::align(*--func_set.end() + 4096, 4096));
const u64 base = (u64)s_memory;
const u8* bits = s_unwind_info;
s_unwind.clear();
s_unwind.reserve(m_map.size());
for (auto it = func_set.begin(), end = --func_set.end(); it != end; it++)
for (const u64 addr : func_set)
{
const u64 addr = *it;
const u64 next = *func_set.upper_bound(addr);
// 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;
@@ -298,6 +314,7 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
if (flags != 1)
{
// Can't happen for trivial code
LOG_ERROR(GENERAL, "LLVM: unsupported UNWIND_INFO version/flags (0x%02x)", flags);
break;
}
@@ -307,15 +324,15 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
if (s_unwind_info + s_unwind_size != bits)
{
LOG_FATAL(GENERAL, "LLVM: .xdata analysis failed! (0x%p != 0x%p)", 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_FATAL(GENERAL, "RtlAddFunctionTable(addr=0x%p) failed! Error %u", s_unwind_info, GetLastError());
LOG_ERROR(GENERAL, "RtlAddFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
}
else
{
LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (addr=0x%p, size=0x%llx)", s_unwind_info, s_unwind_size);
LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (%p, size=0x%llx)", s_unwind_info, s_unwind_size);
}
#endif
}
+23
View File
@@ -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.
+78 -56
View File
@@ -2,27 +2,35 @@
#include "File.h"
#include "StrFmt.h"
#include <cstdarg>
#include "rpcs3_version.h"
#include <string>
// Thread-specific log prefix provider
thread_local std::string(*g_tls_log_prefix)() = nullptr;
#ifndef _MSC_VER
constexpr DECLARE(bijective<logs::level, const char*>::map);
#endif
template<>
void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto lev)
{
switch (lev)
{
case logs::level::always: return "Nothing";
case logs::level::fatal: return "Fatal";
case logs::level::error: return "Error";
case logs::level::todo: return "TODO";
case logs::level::success: return "Success";
case logs::level::warning: return "Warning";
case logs::level::notice: return "Notice";
case logs::level::trace: return "Trace";
}
return unknown;
});
}
namespace logs
{
struct listener
{
listener() = default;
virtual ~listener() = default;
virtual void log(const channel& ch, level sev, const std::string& text) = 0;
};
class file_writer
{
// Could be memory-mapped file
@@ -34,10 +42,7 @@ namespace logs
virtual ~file_writer() = default;
// Append raw data
void log(const std::string& text);
// Get current file size (may be used by secondary readers)
std::size_t size() const;
void log(const char* text, std::size_t size);
};
struct file_listener : public file_writer, public listener
@@ -46,17 +51,19 @@ namespace logs
: 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(const channel& ch, level sev, const std::string& text) override;
virtual void log(const message& msg, const std::string& prefix, const std::string& text) override;
};
static file_listener& get_logger()
static file_listener* get_logger()
{
// Use magic static
static file_listener logger("RPCS3.log");
return logger;
return &logger;
}
channel GENERAL(nullptr, level::notice);
@@ -69,12 +76,32 @@ namespace logs
channel ARMv7("ARMv7");
}
void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt...)
void logs::listener::add(logs::listener* _new)
{
va_list args;
va_start(args, fmt);
get_logger().log(ch, sev, fmt::unsafe_vformat(fmt, args));
va_end(args);
// Get first (main) listener
listener* lis = get_logger();
// 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;
}
}
void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u64* args)
{
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();
// Send message to all listeners
while (lis)
{
lis->log(*this, prefix, text);
lis = lis->m_next;
}
}
[[noreturn]] extern void catch_all_exceptions();
@@ -85,7 +112,7 @@ logs::file_writer::file_writer(const std::string& name)
{
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
{
throw fmt::exception("Can't create log file %s (error %d)", name, fs::g_tls_error);
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
}
}
catch (...)
@@ -94,54 +121,49 @@ logs::file_writer::file_writer(const std::string& name)
}
}
void logs::file_writer::log(const std::string& text)
void logs::file_writer::log(const char* text, std::size_t size)
{
m_file.write(text);
m_file.write(text, size);
}
std::size_t logs::file_writer::size() const
void logs::file_listener::log(const logs::message& msg, const std::string& prefix, const std::string& _text)
{
return m_file.pos();
}
void logs::file_listener::log(const logs::channel& ch, logs::level sev, const std::string& text)
{
std::string msg; msg.reserve(text.size() + 200);
std::string text; text.reserve(prefix.size() + _text.size() + 200);
// Used character: U+00B7 (Middle Dot)
switch (sev)
switch (msg.sev)
{
case level::always: msg = u8"·A "; break;
case level::fatal: msg = u8"·F "; break;
case level::error: msg = u8"·E "; break;
case level::todo: msg = u8"·U "; break;
case level::success: msg = u8"·S "; break;
case level::warning: msg = u8"·W "; break;
case level::notice: msg = u8"·! "; break;
case level::trace: msg = u8"·T "; break;
case level::always: text = u8"·A "; break;
case level::fatal: text = u8"·F "; break;
case level::error: text = u8"·E "; break;
case level::todo: text = u8"·U "; break;
case level::success: text = u8"·S "; break;
case level::warning: text = u8"·W "; break;
case level::notice: text = u8"·! "; break;
case level::trace: text = u8"·T "; break;
}
// TODO: print time?
if (auto prefix = g_tls_log_prefix)
if (prefix.size() > 0)
{
msg += '{';
msg += prefix();
msg += "} ";
text += "{";
text += prefix;
text += "} ";
}
if (ch.name)
if (msg.ch->name)
{
msg += ch.name;
msg += sev == level::todo ? " TODO: " : ": ";
text += msg.ch->name;
text += msg.sev == level::todo ? " TODO: " : ": ";
}
else if (sev == level::todo)
else if (msg.sev == level::todo)
{
msg += "TODO: ";
text += "TODO: ";
}
msg += text;
msg += '\n';
text += _text;
text += '\n';
file_writer::log(msg);
file_writer::log(text.data(), text.size());
}
+45 -35
View File
@@ -2,6 +2,7 @@
#include "types.h"
#include "Atomic.h"
#include "StrFmt.h"
namespace logs
{
@@ -17,6 +18,37 @@ namespace logs
trace, // lowest level (usually disabled)
};
struct channel;
// Message information (temporary data)
struct message
{
const channel* ch;
level sev;
// Send log message to global logger instance
void broadcast(const char*, const fmt_type_info*, const u64*);
};
class listener
{
// Next listener (linked list)
atomic_t<listener*> m_next{};
friend struct message;
public:
constexpr listener() = default;
virtual ~listener() = default;
// Process log message
virtual void log(const message& msg, const std::string& prefix, const std::string& text) = 0;
// Add new listener
static void add(listener*);
};
struct channel
{
// Channel prefix (added to every log message)
@@ -34,19 +66,17 @@ namespace logs
// Formatting function
template<typename... Args>
void format(level sev, const char* fmt, const Args&... args) const
SAFE_BUFFERS FORCE_INLINE void format(level sev, const char* fmt, const Args&... args) const
{
#ifdef _MSC_VER
if (sev <= enabled)
#else
if (__builtin_expect(sev <= enabled, 0))
#endif
broadcast(*this, sev, fmt, ::unveil<Args>::get(args)...);
if (UNLIKELY(sev <= enabled))
{
message{this, sev}.broadcast(fmt, fmt::get_type_info<fmt_unveil_t<Args>...>(), fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
}
}
#define GEN_LOG_METHOD(_sev)\
template<typename... Args>\
void _sev(const char* fmt, const Args&... args) const\
SAFE_BUFFERS void _sev(const char* fmt, const Args&... args) const\
{\
return format<Args...>(level::_sev, fmt, args...);\
}
@@ -60,10 +90,6 @@ namespace logs
GEN_LOG_METHOD(trace)
#undef GEN_LOG_METHOD
private:
// Send log message to global logger instance
static void broadcast(const channel& ch, level sev, const char* fmt...);
};
/* Small set of predefined channels */
@@ -78,28 +104,12 @@ namespace logs
extern channel ARMv7;
}
template<>
struct bijective<logs::level, const char*>
{
static constexpr bijective_pair<logs::level, const char*> map[]
{
{ logs::level::always, "Nothing" },
{ logs::level::fatal, "Fatal" },
{ logs::level::error, "Error" },
{ logs::level::todo, "TODO" },
{ logs::level::success, "Success" },
{ logs::level::warning, "Warning" },
{ logs::level::notice, "Notice" },
{ logs::level::trace, "Trace" },
};
};
// Legacy:
#define LOG_SUCCESS(ch, fmt, ...) logs::ch.success(fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) logs::ch.notice (fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) logs::ch.warning(fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) logs::ch.error (fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) logs::ch.todo (fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) logs::ch.trace (fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) logs::ch.fatal (fmt, ##__VA_ARGS__)
#define LOG_SUCCESS(ch, fmt, ...) logs::ch.success("" fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) logs::ch.notice ("" fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) logs::ch.warning("" fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) logs::ch.error ("" fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) logs::ch.todo ("" fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) logs::ch.trace ("" fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) logs::ch.fatal ("" fmt, ##__VA_ARGS__)
+1 -1
View File
@@ -61,7 +61,7 @@ public:
Show();
}
force_inline void Update(const u8 thread_id, const u64 value, const wxString& msg)
void Update(const u8 thread_id, const u64 value, const wxString& msg)
{
if(thread_id > m_cores) return;
-83
View File
@@ -1,83 +0,0 @@
#pragma once
#include <cstdint>
#include <exception>
template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
constexpr T align(const T& value, std::uint64_t align)
{
return static_cast<T>((value + (align - 1)) & ~(align - 1));
}
template<typename To, typename From>
constexpr To narrow_impl(const To& result, const From& value, const char* message)
{
return static_cast<From>(result) != value ? throw std::runtime_error(message) : result;
}
// Narrow cast (similar to gsl::narrow) with fixed message
template<typename To, typename From>
constexpr auto narrow(const From& value, const char* fixed_msg = "::narrow() failed") -> decltype(static_cast<To>(static_cast<From>(std::declval<To>())))
{
return narrow_impl(static_cast<To>(value), value, fixed_msg);
}
// Return 32 bit .size() for container
template<typename CT>
constexpr auto size32(const CT& container, const char* fixed_msg = "::size32() failed") -> decltype(static_cast<std::uint32_t>(container.size()))
{
return narrow<std::uint32_t>(container.size(), fixed_msg);
}
// Return 32 bit size for an array
template<typename T, std::size_t Size>
constexpr std::uint32_t size32(const T(&)[Size])
{
static_assert(Size <= UINT32_MAX, "size32() error: too big");
return static_cast<std::uint32_t>(Size);
}
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size")
#define CHECK_ALIGN(type, align) static_assert(alignof(type) == align, "Invalid " #type " type alignment")
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
#define CHECK_STORAGE(type, storage) static_assert(sizeof(type) <= sizeof(storage) && alignof(type) <= alignof(decltype(storage)), #type " is too small")
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define SIZE_32(type) static_cast<std::uint32_t>(sizeof(type))
// Return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define ALIGN_32(type) static_cast<std::uint32_t>(alignof(type))
// Return 32 bit custom offsetof()
#define OFFSET_32(type, x) static_cast<std::uint32_t>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<const volatile char&>(reinterpret_cast<type*>(0ull)->x)))
// Sometimes to avoid writing std::remove_cv_t<>, example: std::is_same<CV T1, CV T2>
#define CV const volatile
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
// Macro set, wraps an expression into lambda
#define WRAP_EXPR(expr, ...) [&](__VA_ARGS__) { return expr; }
#define COPY_EXPR(expr, ...) [=](__VA_ARGS__) { return expr; }
#define PURE_EXPR(expr, ...) [] (__VA_ARGS__) { return expr; }
#define return_ return
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
// Ensure that the expression is evaluated to true. Always evaluated and allowed to have side effects (unlike assert() macro).
#define VERIFY(expr) do { if (!(expr)) throw std::runtime_error("Verification failed: " #expr HERE); } while (0)
// EXPECTS() and ENSURES() are intended to check function arguments and results.
// Expressions are not guaranteed to evaluate.
#define EXPECTS(expr) do { if (!(expr)) throw std::runtime_error("Precondition failed: " #expr HERE); } while (0)
#define ENSURES(expr) do { if (!(expr)) throw std::runtime_error("Postcondition failed: " #expr HERE); } while (0)
#define DECLARE(...) decltype(__VA_ARGS__) __VA_ARGS__
#define STR_CASE(value) case value: return #value
-51
View File
@@ -1,51 +0,0 @@
#include "Platform.h"
#ifdef __APPLE__
#include <sys/types.h>
#include <sys/_types/_timespec.h>
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
#undef CPU_STATE_MAX
#define MT_NANO (+1.0E-9)
#define MT_GIGA UINT64_C(1000000000)
// TODO create a list of timers,
static double mt_timebase = 0.0;
static uint64_t mt_timestart = 0;
// TODO be more careful in a multithreaded environement
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
kern_return_t retval = KERN_SUCCESS;
if( clk_id == TIMER_ABSTIME)
{
if (!mt_timestart) { // only one timer, initilized on the first call to the TIMER
mach_timebase_info_data_t tb = { 0 };
mach_timebase_info(&tb);
mt_timebase = tb.numer;
mt_timebase /= tb.denom;
mt_timestart = mach_absolute_time();
}
double diff = (mach_absolute_time() - mt_timestart) * mt_timebase;
tp->tv_sec = diff * MT_NANO;
tp->tv_nsec = diff - (tp->tv_sec * MT_GIGA);
}
else // other clk_ids are mapped to the coresponding mach clock_service
{
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), clk_id, &cclock);
retval = clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec;
}
return retval;
}
#endif /* __APPLE__ */
-122
View File
@@ -1,122 +0,0 @@
#pragma once
#include <cstdint>
#include <immintrin.h>
#include <emmintrin.h>
#define IS_LE_MACHINE 1
#define IS_BE_MACHINE 0
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#ifdef _MSC_VER
#define ASSUME(cond) __assume(cond)
#define LIKELY(cond) (cond)
#define UNLIKELY(cond) (cond)
#else
#define ASSUME(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#define LIKELY(cond) __builtin_expect(!!(cond), 1)
#define UNLIKELY(cond) __builtin_expect(!!(cond), 0)
#endif
// Some platforms don't support thread_local well yet.
#ifndef _MSC_VER
#define thread_local __thread
#endif
#ifdef _MSC_VER
#define never_inline __declspec(noinline)
#else
#define never_inline __attribute__((noinline))
#endif
#ifdef _MSC_VER
#define force_inline __forceinline
#else
#define force_inline __attribute__((always_inline)) inline
#endif
#if defined(__GNUG__)
#include <stdlib.h>
#define _fpclass(x) std::fpclassify(x)
#define INFINITE 0xFFFFFFFF
#ifdef __APPLE__
// XXX only supports a single timer
#define TIMER_ABSTIME -1
/* The opengroup spec isn't clear on the mapping from REALTIME to CALENDAR
being appropriate or not.
http://pubs.opengroup.org/onlinepubs/009695299/basedefs/time.h.html */
#define CLOCK_REALTIME 1 // #define CALENDAR_CLOCK 1 from mach/clock_types.h
#define CLOCK_MONOTONIC 0 // #define SYSTEM_CLOCK 0
typedef int clockid_t;
/* the mach kernel uses struct mach_timespec, so struct timespec
is loaded from <sys/_types/_timespec.h> for compatability */
// struct timespec { time_t tv_sec; long tv_nsec; };
int clock_gettime(clockid_t clk_id, struct timespec *tp);
#endif /* __APPLE__ */
#endif /* __GNUG__ */
inline std::uint32_t cntlz32(std::uint32_t arg)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse(&res, arg) ? res ^ 31 : 32;
#else
return arg ? __builtin_clzll(arg) - 32 : 32;
#endif
}
inline std::uint64_t cntlz64(std::uint64_t arg)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse64(&res, arg) ? res ^ 63 : 64;
#else
return arg ? __builtin_clzll(arg) : 64;
#endif
}
// Helper function, used by ""_u16, ""_u32, ""_u64
constexpr std::uint8_t to_u8(char c)
{
return static_cast<std::uint8_t>(c);
}
// Convert 2-byte string to u16 value like reinterpret_cast does
constexpr std::uint16_t operator""_u16(const char* s, std::size_t length)
{
return length != 2 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 4-byte string to u32 value like reinterpret_cast does
constexpr std::uint32_t operator""_u32(const char* s, std::size_t length)
{
return length != 4 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 8-byte string to u64 value like reinterpret_cast does
constexpr std::uint64_t operator""_u64(const char* s, std::size_t length)
{
return length != 8 ? throw s :
#if IS_LE_MACHINE == 1
static_cast<std::uint64_t>(to_u8(s[7]) << 24 | to_u8(s[6]) << 16 | to_u8(s[5]) << 8 | to_u8(s[4])) << 32 | to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
-1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
// Binary semaphore
class benaphore
-1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.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.
+1 -5
View File
@@ -9,10 +9,8 @@ static struct defer_sleep_tag {} constexpr defer_sleep{};
template<typename T> using sleep_queue = std::deque<T*>;
// Automatic object handling a thread pointer (T*) in the sleep queue
// Sleep is called in the constructor (if not null)
// Awake is called in the destructor (if not null)
// Sleep queue is actually std::deque with pointers, be careful about the lifetime
template<typename T, void(T::*Sleep)() = &T::sleep, void(T::*Awake)() = &T::awake>
template<typename T>
class sleep_entry final
{
sleep_queue<T>& m_queue;
@@ -24,7 +22,6 @@ public:
: m_queue(queue)
, m_thread(entry)
{
if (Sleep) (m_thread.*Sleep)();
}
// Constructor; calls enter()
@@ -38,7 +35,6 @@ public:
~sleep_entry()
{
leave();
if (Awake) (m_thread.*Awake)();
}
// Add thread to the sleep queue
+271 -60
View File
@@ -1,73 +1,284 @@
#include "StrFmt.h"
#include "BEType.h"
#include "StrUtil.h"
#include "cfmt.h"
#include <cassert>
#include <array>
#include <memory>
#include <algorithm>
std::string v128::to_hex() const
#ifdef _WIN32
#include <Windows.h>
#else
#include <errno.h>
#endif
void fmt_class_string<const void*>::format(std::string& out, u64 arg)
{
return fmt::format("%016llx%016llx", _u64[1], _u64[0]);
}
std::string v128::to_xyzw() const
{
return fmt::format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]);
}
std::string fmt::unsafe_vformat(const char* fmt, va_list _args) noexcept
{
// Fixed stack buffer for the first attempt
std::array<char, 4096> fixed_buf;
// Possibly dynamically allocated buffer for the second attempt
std::unique_ptr<char[]> buf;
// Pointer to the current buffer
char* buf_addr = fixed_buf.data();
for (std::size_t buf_size = fixed_buf.size();;)
if (arg)
{
va_list args;
va_copy(args, _args);
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
const std::size_t len = std::vsnprintf(buf_addr, buf_size, fmt, args);
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif
va_end(args);
assert(len <= INT_MAX);
if (len < buf_size)
{
return{ buf_addr, len };
}
buf.reset(buf_addr = new char[buf_size = len + 1]);
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
}
else
{
out += "(NULL)";
}
}
std::string fmt::unsafe_format(const char* fmt...) noexcept
void fmt_class_string<const char*>::format(std::string& out, u64 arg)
{
va_list args;
va_start(args, fmt);
auto result = unsafe_vformat(fmt, args);
va_end(args);
return result;
if (arg)
{
out += reinterpret_cast<const char*>(static_cast<std::uintptr_t>(arg));
}
else
{
out += "(NULL)";
}
}
fmt::exception_base::exception_base(const char* fmt...)
: std::runtime_error((va_start(m_args, fmt), unsafe_vformat(fmt, m_args)))
template <>
void fmt_class_string<std::string>::format(std::string& out, u64 arg)
{
va_end(m_args);
out += get_object(arg).c_str(); // TODO?
}
template <>
void fmt_class_string<std::vector<char>>::format(std::string& out, u64 arg)
{
const std::vector<char>& obj = get_object(arg);
out.append(obj.cbegin(), obj.cend());
}
template <>
void fmt_class_string<char>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#hhx", static_cast<char>(arg));
}
template <>
void fmt_class_string<uchar>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#hhx", static_cast<uchar>(arg));
}
template <>
void fmt_class_string<schar>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#hhx", static_cast<schar>(arg));
}
template <>
void fmt_class_string<short>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#hx", static_cast<short>(arg));
}
template <>
void fmt_class_string<ushort>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#hx", static_cast<ushort>(arg));
}
template <>
void fmt_class_string<int>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#x", static_cast<int>(arg));
}
template <>
void fmt_class_string<uint>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#x", static_cast<uint>(arg));
}
template <>
void fmt_class_string<long>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#lx", static_cast<long>(arg));
}
template <>
void fmt_class_string<ulong>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#lx", static_cast<ulong>(arg));
}
template <>
void fmt_class_string<llong>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#llx", static_cast<llong>(arg));
}
template <>
void fmt_class_string<ullong>::format(std::string& out, u64 arg)
{
fmt::append(out, "%#llx", static_cast<ullong>(arg));
}
template <>
void fmt_class_string<float>::format(std::string& out, u64 arg)
{
fmt::append(out, "%gf", static_cast<float>(reinterpret_cast<f64&>(arg)));
}
template <>
void fmt_class_string<double>::format(std::string& out, u64 arg)
{
fmt::append(out, "%g", reinterpret_cast<f64&>(arg));
}
template <>
void fmt_class_string<bool>::format(std::string& out, u64 arg)
{
out += arg ? "true" : "false";
}
template <>
void fmt_class_string<v128>::format(std::string& out, u64 arg)
{
const v128& vec = get_object(arg);
fmt::append(out, "0x%016llx%016llx", vec._u64[1], vec._u64[0]);
}
namespace fmt
{
void raw_error(const char* msg)
{
throw std::runtime_error{msg};
}
void raw_verify_error(const char* msg, const fmt_type_info* sup, u64 arg)
{
std::string out{"Verification failed"};
// Print error code (may be irrelevant)
#ifdef _WIN32
if (DWORD error = GetLastError())
{
fmt::append(out, " (e%#x)", error);
}
#else
if (int error = errno)
{
fmt::append(out, " (e%d)", error);
}
#endif
if (sup)
{
out += " (";
sup->fmt_string(out, arg); // Print value
out += ")";
}
if (msg)
{
out += ": ";
out += msg;
}
throw std::runtime_error{out};
}
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg)
{
std::string out{"Narrow error"};
if (sup)
{
out += " (";
sup->fmt_string(out, arg); // Print value
out += ")";
}
if (msg)
{
out += ": ";
out += msg;
}
throw std::range_error{out};
}
// Hidden template
template <typename T>
void raw_throw_exception(const char* fmt, const fmt_type_info* sup, const u64* args)
{
std::string out;
raw_append(out, fmt, sup, args);
throw T{out};
}
// Explicit instantiations (not exhaustive)
template void raw_throw_exception<std::runtime_error>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::logic_error>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::domain_error>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::invalid_argument>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::out_of_range>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::range_error>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::overflow_error>(const char*, const fmt_type_info*, const u64*);
template void raw_throw_exception<std::underflow_error>(const char*, const fmt_type_info*, const u64*);
struct cfmt_src;
}
// Temporary implementation
struct fmt::cfmt_src
{
const fmt_type_info* sup;
const u64* args;
bool test(std::size_t index) const
{
if (!sup[index].fmt_string)
{
return false;
}
return true;
}
template <typename T>
T get(std::size_t index) const
{
return reinterpret_cast<const T&>(args[index]);
}
void skip(std::size_t extra)
{
++sup += extra;
++args += extra;
}
std::size_t fmt_string(std::string& out, std::size_t extra) const
{
const std::size_t start = out.size();
sup[extra].fmt_string(out, args[extra]);
return out.size() - start;
}
// Returns type size (0 if unknown, pointer, unsigned, assumed max)
std::size_t type(std::size_t extra) const
{
// Hack: use known function pointers to determine type
#define TYPE(type) \
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type);
TYPE(int);
TYPE(llong);
TYPE(schar);
TYPE(short);
if (std::is_signed<char>::value) TYPE(char);
TYPE(long);
#undef TYPE
return 0;
}
};
void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept
{
cfmt_append(out, fmt, cfmt_src{sup, args});
}
std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to)
@@ -82,7 +293,7 @@ std::string fmt::replace_first(const std::string& src, const std::string& from,
return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length());
}
std::string fmt::replace_all(const std::string &src, const std::string& from, const std::string& to)
std::string fmt::replace_all(const std::string& src, const std::string& from, const std::string& to)
{
std::string target = src;
for (auto pos = target.find(from); pos != std::string::npos; pos = target.find(from, pos + 1))
@@ -102,7 +313,7 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
{
for (auto &separator : separators)
for (auto& separator : separators)
{
if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0)
{
@@ -111,7 +322,7 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
result.push_back(candidate);
cursor_begin = cursor_end + separator.length();
cursor_end = cursor_begin - 1;
cursor_end = cursor_begin - 1;
break;
}
}
@@ -130,7 +341,7 @@ std::string fmt::trim(const std::string& source, const std::string& values)
std::size_t begin = source.find_first_not_of(values);
if (begin == source.npos)
return{};
return {};
return source.substr(begin, source.find_last_not_of(values) + 1);
}
@@ -143,7 +354,7 @@ std::string fmt::to_upper(const std::string& string)
return result;
}
bool fmt::match(const std::string &source, const std::string &mask)
bool fmt::match(const std::string& source, const std::string& mask)
{
std::size_t source_position = 0, mask_position = 0;
+240 -32
View File
@@ -1,52 +1,260 @@
#pragma once
#include <cstdarg>
#include <exception>
#include <string>
#include "Platform.h"
#include "types.h"
#include <exception>
#include <stdexcept>
#include <string>
namespace fmt
{
std::string unsafe_format(const char* fmt...) noexcept;
std::string unsafe_vformat(const char*, va_list) noexcept;
template <typename... Args>
static std::string format(const char*, const Args&...);
}
// Formatting function
template<typename... Args>
inline std::string format(const char* fmt, const Args&... args)
template <typename T, typename>
struct fmt_unveil
{
static_assert(sizeof(T) > 0, "fmt_unveil<>: cannot pass forward-declared object");
using type = T;
static inline u64 get(const T& arg)
{
return unsafe_format(fmt, ::unveil<Args>::get(args)...);
return reinterpret_cast<std::uintptr_t>(&arg);
}
// Helper class
class exception_base : public std::runtime_error
// Temporary value container (can possibly be created by other fmt_unveil<> specializations)
struct u64_wrapper
{
// Helper (there is no other room)
va_list m_args;
T arg;
protected:
// Internal formatting constructor
exception_base(const char* fmt...);
};
// Exception type derived from std::runtime_error with formatting constructor
class exception : public exception_base
{
public:
template<typename... Args>
exception(const char* fmt, const Args&... args)
: exception_base(fmt, ::unveil<Args>::get(args)...)
// Allow implicit conversion
operator u64() const
{
return reinterpret_cast<std::uintptr_t>(&arg);
}
};
// Narrow cast (similar to gsl::narrow) with exception message formatting
template<typename To, typename From, typename... Args>
inline auto narrow(const char* format_str, const From& value, const Args&... args) -> decltype(static_cast<To>(static_cast<From>(std::declval<To>())))
// This overload resolution takes the precedence
static inline u64_wrapper get(T&& arg)
{
const auto result = static_cast<To>(value);
if (static_cast<From>(result) != value) throw fmt::exception(format_str, value, args...);
return u64_wrapper{std::move(arg)};
}
};
template <typename T>
struct fmt_unveil<T, std::enable_if_t<std::is_integral<T>::value && sizeof(T) <= 8 && alignof(T) <= 8>>
{
using type = T;
static inline u64 get(T arg)
{
return static_cast<T>(arg);
}
};
template <typename T>
struct fmt_unveil<T, std::enable_if_t<std::is_floating_point<T>::value && sizeof(T) <= 8 && alignof(T) <= 8>>
{
using type = T;
// Convert FP to f64 and reinterpret (TODO?)
static inline u64 get(f64 arg)
{
return reinterpret_cast<u64&>(arg);
}
};
template <typename T>
struct fmt_unveil<T, std::enable_if_t<std::is_enum<T>::value>>
{
using type = T;
static inline u64 get(T arg)
{
return static_cast<std::underlying_type_t<T>>(arg);
}
};
template <typename T>
struct fmt_unveil<T*, void>
{
using type = const T*;
static inline u64 get(const T* arg)
{
return reinterpret_cast<std::uintptr_t>(arg);
}
};
template <typename T, std::size_t N>
struct fmt_unveil<T[N], void>
{
using type = const T*;
static inline u64 get(const T* arg)
{
return reinterpret_cast<std::uintptr_t>(arg);
}
};
template <>
struct fmt_unveil<b8, void>
{
using type = bool;
static inline u64 get(const b8& value)
{
return fmt_unveil<bool>::get(value);
}
};
// String type format provider, also type classifier (format() called if an argument is formatted as "%s")
template <typename T, typename = void>
struct fmt_class_string
{
// Formatting function (must be explicitly specialized)
static void format(std::string& out, u64 arg);
// Helper typedef (visible in format())
using type = T;
// Helper function (converts arg to object reference)
static SAFE_BUFFERS FORCE_INLINE const T& get_object(u64 arg)
{
return *reinterpret_cast<const T*>(static_cast<std::uintptr_t>(arg));
}
// Helper function (safely converts arg to enum value)
static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, const char* (*get)(T value))
{
const auto value = static_cast<std::underlying_type_t<T>>(arg);
// Check narrowing
if (static_cast<u64>(value) == arg)
{
if (const char* str = get(static_cast<T>(value)))
{
out += str;
return;
}
}
// Fallback to underlying type formatting
fmt_class_string<std::underlying_type_t<T>>::format(out, static_cast<u64>(value));
}
// Helper function (bitset formatting)
static SAFE_BUFFERS FORCE_INLINE void format_bitset(std::string& out, u64 arg, const char* prefix, const char* delim, const char* suffix, void (*fmt)(std::string&, u64))
{
// Start from raw value
fmt_class_string<u64>::format(out, arg);
out += prefix;
for (u64 i = 0; i < 64; i++)
{
const u64 mask = 1ull << i;
if (arg & mask)
{
fmt(out, i);
if (arg > mask)
{
out += delim;
}
}
}
out += suffix;
}
// Helper constant (may be used in format_enum as lambda return value)
static constexpr const char* unknown = nullptr;
};
template <>
struct fmt_class_string<const void*, void>
{
static void format(std::string& out, u64 arg);
};
template <typename T>
struct fmt_class_string<T*, void> : fmt_class_string<const void*, void>
{
// Classify all pointers as const void*
};
template <>
struct fmt_class_string<const char*, void>
{
static void format(std::string& out, u64 arg);
};
template <>
struct fmt_class_string<char*, void> : fmt_class_string<const char*>
{
// Classify char* as const char*
};
struct fmt_type_info
{
decltype(&fmt_class_string<int>::format) fmt_string;
template <typename T>
static constexpr fmt_type_info make()
{
return fmt_type_info
{
&fmt_class_string<T>::format,
};
}
};
// Argument array type (each element generated via fmt_unveil<>)
template <typename... Args>
using fmt_args_t = const u64(&&)[sizeof...(Args) + 1];
namespace fmt
{
template <typename... Args>
SAFE_BUFFERS FORCE_INLINE const fmt_type_info* get_type_info()
{
// Constantly initialized null-terminated list of type-specific information
static constexpr fmt_type_info result[sizeof...(Args) + 1]{fmt_type_info::make<Args>()...};
return result;
}
// Internal formatting function
void raw_append(std::string& out, const char*, const fmt_type_info*, const u64*) noexcept;
// Formatting function
template <typename... Args>
SAFE_BUFFERS FORCE_INLINE void append(std::string& out, const char* fmt, const Args&... args)
{
raw_append(out, fmt, fmt::get_type_info<fmt_unveil_t<Args>...>(), fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
}
// Formatting function
template <typename... Args>
SAFE_BUFFERS FORCE_INLINE std::string format(const char* fmt, const Args&... args)
{
std::string result;
append<Args...>(result, fmt, args...);
return result;
}
// Internal exception message formatting template, must be explicitly specialized or instantiated in cpp to minimize code bloat
template <typename T>
[[noreturn]] void raw_throw_exception(const char*, const fmt_type_info*, const u64*);
// Throw exception with formatting
template <typename T = std::runtime_error, typename... Args>
[[noreturn]] SAFE_BUFFERS FORCE_INLINE void throw_exception(const char* fmt, const Args&... args)
{
raw_throw_exception<T>(fmt, fmt::get_type_info<fmt_unveil_t<Args>...>(), fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
}
}
+17 -17
View File
@@ -7,8 +7,8 @@
#include <functional>
// Copy null-terminated string from std::string to char array with truncation
template<std::size_t N>
inline void strcpy_trunc(char(&dst)[N], const std::string& src)
template <std::size_t N>
inline void strcpy_trunc(char (&dst)[N], const std::string& src)
{
const std::size_t count = src.size() >= N ? N - 1 : src.size();
std::memcpy(dst, src.c_str(), count);
@@ -16,8 +16,8 @@ inline void strcpy_trunc(char(&dst)[N], const std::string& src)
}
// Copy null-terminated string from char array to another char array with truncation
template<std::size_t N, std::size_t N2>
inline void strcpy_trunc(char(&dst)[N], const char(&src)[N2])
template <std::size_t N, std::size_t N2>
inline void strcpy_trunc(char (&dst)[N], const char (&src)[N2])
{
const std::size_t count = N2 >= N ? N - 1 : N2;
std::memcpy(dst, src, count);
@@ -27,10 +27,10 @@ inline void strcpy_trunc(char(&dst)[N], const char(&src)[N2])
namespace fmt
{
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
std::string replace_all(const std::string &src, const std::string& from, const std::string& to);
std::string replace_all(const std::string& src, const std::string& from, const std::string& to);
template<size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::string>(&list)[list_size])
template <size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::string> (&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
{
@@ -53,8 +53,8 @@ namespace fmt
return src;
}
template<size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>>(&list)[list_size])
template <size_t list_size>
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>> (&list)[list_size])
{
for (size_t pos = 0; pos < src.length(); ++pos)
{
@@ -80,17 +80,17 @@ namespace fmt
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
std::string trim(const std::string& source, const std::string& values = " \t");
template<typename T>
template <typename T>
std::string merge(const T& source, const std::string& separator)
{
if (!source.size())
{
return{};
return {};
}
std::string result;
auto it = source.begin();
auto it = source.begin();
auto end = source.end();
for (--end; it != end; ++it)
{
@@ -100,23 +100,23 @@ namespace fmt
return result + source.back();
}
template<typename T>
template <typename T>
std::string merge(std::initializer_list<T> sources, const std::string& separator)
{
if (!sources.size())
{
return{};
return {};
}
std::string result;
bool first = true;
for (auto &v : sources)
for (auto& v : sources)
{
if (first)
{
result = fmt::merge(v, separator);
first = false;
first = false;
}
else
{
@@ -129,5 +129,5 @@ namespace fmt
std::string to_upper(const std::string& string);
bool match(const std::string &source, const std::string &mask);
bool match(const std::string& source, const std::string& mask);
}
+337 -50
View File
@@ -6,12 +6,14 @@
#include "Thread.h"
#ifdef _WIN32
#include <windows.h>
#include <Windows.h>
#include <Psapi.h>
#else
#ifdef __APPLE__
#define _XOPEN_SOURCE
#define __USE_GNU
#endif
#include <errno.h>
#include <signal.h>
#include <ucontext.h>
#endif
@@ -19,11 +21,7 @@
static void report_fatal_error(const std::string& msg)
{
std::string _msg = msg + "\n"
"HOW TO REPORT ERRORS:\n"
"1) Check the FAQ, readme, other sources. Please ensure that your hardware and software configuration is compliant.\n"
"2) You must provide FULL information: how to reproduce the error (your actions), RPCS3.log file, other *.log files whenever requested.\n"
"3) Please ensure that your software (game) is 'Playable' or close. Please note that 'Non-playable' games will be ignored.\n"
"4) If the software (game) is not 'Playable', please ensure that this error is unexpected, i.e. it didn't happen before or similar.\n"
"HOW TO REPORT ERRORS: Check the FAQ, README, other sources.\n"
"Please, don't send incorrect reports. Thanks for understanding.\n";
#ifdef _WIN32
@@ -590,6 +588,57 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
}
break;
}
case 0xc4: // 3-byte VEX prefix
case 0xc5: // 2-byte VEX prefix
{
// Last prefix byte: op2 or op3
const u8 opx = op1 == 0xc5 ? op2 : op3;
// Implied prefixes
rex |= op2 & 0x80 ? 0 : 0x4; // REX.R
rex |= op1 == 0xc4 && op3 & 0x80 ? 0x8 : 0; // REX.W ???
oso = (opx & 0x3) == 0x1;
repe = (opx & 0x3) == 0x2;
repne = (opx & 0x3) == 0x3;
const u8 vopm = op1 == 0xc5 ? 1 : op2 & 0x1f;
const u8 vop1 = op1 == 0xc5 ? op3 : code[2];
const u8 vlen = (opx & 0x4) ? 32 : 16;
const u8 vreg = (~opx >> 3) & 0xf;
out_length += op1 == 0xc5 ? 2 : 3;
code += op1 == 0xc5 ? 2 : 3;
if (vopm == 0x1) switch (vop1) // Implied leading byte 0x0F
{
case 0x11:
case 0x29:
{
if (!repe && !repne) // VMOVAPS/VMOVAPD/VMOVUPS/VMOVUPD mem,reg
{
out_op = X64OP_STORE;
out_reg = get_modRM_reg_xmm(code, rex);
out_size = vlen;
out_length += get_modRM_size(code);
return;
}
break;
}
case 0x7f:
{
if (repe || oso) // VMOVDQU/VMOVDQA mem,reg
{
out_op = X64OP_STORE;
out_reg = get_modRM_reg_xmm(code, rex);
out_size = vlen;
out_length += get_modRM_size(code);
return;
}
break;
}
}
break;
}
case 0xc6:
{
if (!lock && !oso && get_modRM_reg(code, 0) == 0) // MOV r8/m8, imm8
@@ -811,7 +860,7 @@ bool get_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, size_
return true;
}
LOG_ERROR(MEMORY, "get_x64_reg_value(): invalid arguments (reg=%d, d_size=%lld, i_size=%lld)", reg, d_size, i_size);
LOG_ERROR(MEMORY, "get_x64_reg_value(): invalid arguments (reg=%d, d_size=%lld, i_size=%lld)", (u32)reg, d_size, i_size);
return false;
}
@@ -830,7 +879,7 @@ bool put_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, u64 v
}
}
LOG_ERROR(MEMORY, "put_x64_reg_value(): invalid destination (reg=%d, d_size=%lld, value=0x%llx)", reg, d_size, value);
LOG_ERROR(MEMORY, "put_x64_reg_value(): invalid destination (reg=%d, d_size=%lld, value=0x%llx)", (u32)reg, d_size, value);
return false;
}
@@ -977,7 +1026,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
{
if (op == X64OP_NONE)
{
LOG_ERROR(MEMORY, "decode_x64_reg_op(%016llxh): unsupported opcode found (%016llX%016llX)", code, *(be_t<u64>*)(code), *(be_t<u64>*)(code + 8));
LOG_ERROR(MEMORY, "decode_x64_reg_op(%p): unsupported opcode: %s", code, *(be_t<v128, 1>*)code);
}
};
@@ -1010,7 +1059,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
if (a_size != 4 || !d_size || !i_size)
{
LOG_ERROR(MEMORY, "Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", op, reg, d_size, a_size, i_size);
LOG_ERROR(MEMORY, "Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", (u32)op, (u32)reg, d_size, a_size, i_size);
report_opcode();
return false;
}
@@ -1082,7 +1131,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
case X64OP_STOS:
default:
{
LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", op, reg, d_size, i_size);
LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", (u32)op, (u32)reg, d_size, i_size);
report_opcode();
return false;
}
@@ -1099,7 +1148,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
// write memory using "privileged" access to avoid breaking reservation
if (!d_size || !i_size)
{
LOG_ERROR(MEMORY, "Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", op, reg, d_size, a_size, i_size);
LOG_ERROR(MEMORY, "Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", (u32)op, (u32)reg, d_size, a_size, i_size);
report_opcode();
return false;
}
@@ -1113,7 +1162,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
{
if (reg - X64R_XMM0 >= 16)
{
LOG_ERROR(MEMORY, "X64OP_STORE: d_size=16, reg=%d", reg);
LOG_ERROR(MEMORY, "X64OP_STORE: d_size=16, reg=%d", (u32)reg);
return false;
}
@@ -1525,7 +1574,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
}
default:
{
LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", op, reg, d_size, a_size, i_size);
LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", (u32)op, (u32)reg, d_size, a_size, i_size);
report_opcode();
return false;
}
@@ -1539,8 +1588,34 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
}
// Detect leaf function
static bool is_leaf_function(u64 rip)
{
#ifdef _WIN32
DWORD64 base = 0;
if (const auto rtf = RtlLookupFunctionEntry(rip, &base, nullptr))
{
// Access UNWIND_INFO structure
const auto uw = (u8*)(base + rtf->UnwindData);
// Leaf function has zero epilog size and no unwind codes
return uw[0] == 1 && uw[1] == 0 && uw[2] == 0 && uw[3] == 0;
}
// No unwind info implies leaf function
return true;
#else
// TODO
return false;
#endif
}
static thread_local u64 s_tls_ret_pos = 0;
static thread_local u64 s_tls_ret_addr = 0;
[[noreturn]] static void throw_access_violation(const char* cause, u64 addr)
{
if (s_tls_ret_pos) *(u64*)s_tls_ret_pos = s_tls_ret_addr; // Fix stack
vm::throw_access_violation(addr, cause);
std::abort();
}
@@ -1553,10 +1628,13 @@ static void prepare_throw_access_violation(x64_context* context, const char* cau
ARG2(context) = address;
// Push the exception address as a "return" address (throw_access_violation() shall not return)
*--(u64*&)(RSP(context)) = RIP(context);
s_tls_ret_addr = RIP(context);
s_tls_ret_pos = is_leaf_function(s_tls_ret_addr) ? 0 : RSP(context) -= sizeof(u64);
RIP(context) = (u64)std::addressof(throw_access_violation);
}
static void _handle_interrupt(x64_context* ctx);
#ifdef _WIN32
static LONG exception_handler(PEXCEPTION_POINTERS pExp)
@@ -1594,7 +1672,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
return EXCEPTION_CONTINUE_EXECUTION;
}
msg += fmt::format("Access violation %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
msg += fmt::format("Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
}
else
{
@@ -1606,8 +1684,58 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
}
}
std::vector<HMODULE> modules;
for (DWORD size = 256; modules.size() != size; size /= sizeof(HMODULE))
{
modules.resize(size);
if (!EnumProcessModules(GetCurrentProcess(), modules.data(), size * sizeof(HMODULE), &size))
{
modules.clear();
break;
}
}
msg += fmt::format("Instruction address: %p.\n", pExp->ContextRecord->Rip);
msg += fmt::format("Image base: %p.\n", GetModuleHandle(NULL));
DWORD64 unwind_base;
if (const auto rtf = RtlLookupFunctionEntry(pExp->ContextRecord->Rip, &unwind_base, nullptr))
{
// Get function address
const DWORD64 func_addr = rtf->BeginAddress + unwind_base;
msg += fmt::format("Function address: %p (base+0x%x).\n", func_addr, rtf->BeginAddress);
// Access UNWIND_INFO structure
//const auto uw = (u8*)(unwind_base + rtf->UnwindData);
}
for (HMODULE module : modules)
{
MODULEINFO info;
if (GetModuleInformation(GetCurrentProcess(), module, &info, sizeof(info)))
{
const DWORD64 base = (DWORD64)info.lpBaseOfDll;
if (pExp->ContextRecord->Rip >= base && pExp->ContextRecord->Rip < base + info.SizeOfImage)
{
std::string module_name;
for (DWORD size = 15; module_name.size() != size;)
{
module_name.resize(size);
size = GetModuleBaseNameA(GetCurrentProcess(), module, &module_name.front(), size + 1);
if (!size)
{
module_name.clear();
break;
}
}
msg += fmt::format("Module name: '%s'.\n", module_name);
msg += fmt::format("Module base: %p.\n", info.lpBaseOfDll);
}
}
}
msg += fmt::format("RPCS3 image base: %p.\n", GetModuleHandle(NULL));
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
{
@@ -1646,6 +1774,11 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
{
x64_context* context = (ucontext_t*)uct;
if (sig == SIGUSR1)
{
return _handle_interrupt(context);
}
#ifdef __APPLE__
const bool is_writing = context->uc_mcontext->__es.__err & 0x2;
#else
@@ -1669,7 +1802,7 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
else
{
// TODO (debugger interaction)
report_fatal_error(fmt::format("Access violation %s location %p at %p.", cause, info->si_addr, RIP(context)));
report_fatal_error(fmt::format("Segfault %s location %p at %p.", cause, info->si_addr, RIP(context)));
std::abort();
}
}
@@ -1683,7 +1816,15 @@ const bool s_exception_handler_set = []() -> bool
if (::sigaction(SIGSEGV, &sa, NULL) == -1)
{
std::printf("sigaction() failed (0x%x).", errno);
std::printf("sigaction(SIGSEGV) failed (0x%x).", errno);
std::abort();
}
sa.sa_sigaction = signal_handler;
if (::sigaction(SIGUSR1, &sa, NULL) == -1)
{
std::printf("sigaction(SIGUSR1) failed (0x%x).", errno);
std::abort();
}
@@ -1715,22 +1856,27 @@ struct thread_ctrl::internal
{
std::mutex mutex;
std::condition_variable cond;
std::condition_variable join; // Allows simultaneous joining
std::condition_variable jcv; // Allows simultaneous joining
std::condition_variable icv;
task_stack atexit;
std::exception_ptr exception; // Caught exception
std::exception_ptr exception; // Stored exception
std::chrono::high_resolution_clock::time_point time_limit;
#ifdef _WIN32
DWORD thread_id = 0;
#endif
x64_context _context{};
x64_context* const thread_ctx = &this->_context;
atomic_t<void(*)()> interrupt{}; // Interrupt function
};
thread_local thread_ctrl::internal* g_tls_internal = nullptr;
extern std::mutex& get_current_thread_mutex()
{
return g_tls_internal->mutex;
}
extern std::condition_variable& get_current_thread_cv()
{
return g_tls_internal->cond;
@@ -1752,7 +1898,6 @@ void thread_ctrl::start(const std::shared_ptr<thread_ctrl>& ctrl, task_stack tas
}
catch (...)
{
ctrl->initialize_once();
ctrl->m_data->exception = std::current_exception();
}
@@ -1762,15 +1907,11 @@ void thread_ctrl::start(const std::shared_ptr<thread_ctrl>& ctrl, task_stack tas
void thread_ctrl::wait_start(u64 timeout)
{
initialize_once();
m_data->time_limit = std::chrono::high_resolution_clock::now() + std::chrono::microseconds(timeout);
}
bool thread_ctrl::wait_wait(u64 timeout)
{
initialize_once();
std::unique_lock<std::mutex> lock(m_data->mutex, std::adopt_lock);
if (timeout && m_data->cond.wait_until(lock, m_data->time_limit) == std::cv_status::timeout)
@@ -1794,11 +1935,12 @@ void thread_ctrl::test()
void thread_ctrl::initialize()
{
initialize_once(); // TODO (temporarily)
// Initialize TLS variable
g_tls_this_thread = this;
g_tls_internal = this->m_data;
#ifdef _WIN32
m_data->thread_id = GetCurrentThreadId();
#endif
g_tls_log_prefix = []
{
@@ -1840,6 +1982,10 @@ void thread_ctrl::initialize()
void thread_ctrl::finalize() noexcept
{
// Disable and discard possible interrupts
interrupt_disable();
test_interrupt();
// TODO
vm::reservation_free();
@@ -1857,7 +2003,6 @@ void thread_ctrl::finalize() noexcept
void thread_ctrl::push_atexit(task_stack task)
{
initialize_once();
m_data->atexit.push(std::move(task));
}
@@ -1870,6 +2015,8 @@ thread_ctrl::thread_ctrl(std::string&& name)
#undef new
new (&m_thread) std::thread;
#pragma pop_macro("new")
initialize_once();
}
thread_ctrl::~thread_ctrl()
@@ -1915,24 +2062,20 @@ void thread_ctrl::join()
// Notify others if necessary
if (UNLIKELY(m_joining.exchange(0x80000000) != 1))
{
initialize_once();
// Serialize for reliable notification
m_data->mutex.lock();
m_data->mutex.unlock();
m_data->join.notify_all();
m_data->jcv.notify_all();
}
}
else
{
// Hard way
initialize_once();
std::unique_lock<std::mutex> lock(m_data->mutex);
m_data->join.wait(lock, WRAP_EXPR(m_joining >= 0x80000000));
m_data->jcv.wait(lock, [&] { return m_joining >= 0x80000000; });
}
if (UNLIKELY(m_data && m_data->exception))
if (UNLIKELY(m_data && m_data->exception && !std::uncaught_exception()))
{
std::rethrow_exception(m_data->exception);
}
@@ -1940,7 +2083,6 @@ void thread_ctrl::join()
void thread_ctrl::lock()
{
initialize_once();
m_data->mutex.lock();
}
@@ -1956,8 +2098,6 @@ void thread_ctrl::lock_notify()
return;
}
initialize_once();
// Serialize for reliable notification, condition is assumed to be changed externally
m_data->mutex.lock();
m_data->mutex.unlock();
@@ -1974,6 +2114,153 @@ void thread_ctrl::set_exception(std::exception_ptr e)
m_data->exception = e;
}
static void _handle_interrupt(x64_context* ctx)
{
// Copy context for further use (TODO: is it safe on all platforms?)
g_tls_internal->_context = *ctx;
thread_ctrl::handle_interrupt();
}
static thread_local void(*s_tls_handler)() = nullptr;
[[noreturn]] static void execute_interrupt_handler()
{
// Fix stack for throwing
if (s_tls_ret_pos) s_tls_ret_addr = std::exchange(*(u64*)s_tls_ret_pos, s_tls_ret_addr);
// Run either throwing or returning interrupt handler
s_tls_handler();
// Restore context in the case of return
const auto ctx = g_tls_internal->thread_ctx;
if (s_tls_ret_pos)
{
RIP(ctx) = std::exchange(*(u64*)s_tls_ret_pos, s_tls_ret_addr);
RSP(ctx) += sizeof(u64);
}
else
{
RIP(ctx) = s_tls_ret_addr;
}
#ifdef _WIN32
RtlRestoreContext(ctx, nullptr);
#else
::setcontext(ctx);
#endif
}
void thread_ctrl::handle_interrupt()
{
const auto _this = g_tls_this_thread;
const auto ctx = g_tls_internal->thread_ctx;
if (_this->m_guard & 0x80000000)
{
// Discard interrupt if interrupts are disabled
if (g_tls_internal->interrupt.exchange(nullptr))
{
_this->lock();
_this->unlock();
g_tls_internal->icv.notify_one();
}
}
else if (_this->m_guard == 0)
{
// Set interrupt immediately if no guard set
if (const auto handler = g_tls_internal->interrupt.exchange(nullptr))
{
_this->lock();
_this->unlock();
g_tls_internal->icv.notify_one();
#ifdef _WIN32
// Install function call
s_tls_ret_addr = RIP(ctx);
s_tls_ret_pos = is_leaf_function(s_tls_ret_addr) ? 0 : RSP(ctx) -= sizeof(u64);
s_tls_handler = handler;
RIP(ctx) = (u64)execute_interrupt_handler;
#else
// Call handler directly (TODO: install function call preserving red zone)
return handler();
#endif
}
}
else
{
// Set delayed interrupt otherwise
_this->m_guard |= 0x40000000;
}
#ifdef _WIN32
RtlRestoreContext(ctx, nullptr);
#endif
}
void thread_ctrl::interrupt(void(*handler)())
{
verify(HERE), this != g_tls_this_thread; // TODO: self-interrupt
verify(HERE), m_data->interrupt.compare_and_swap_test(nullptr, handler); // TODO: multiple interrupts
#ifdef _WIN32
const auto ctx = m_data->thread_ctx;
const HANDLE nt = OpenThread(THREAD_ALL_ACCESS, FALSE, m_data->thread_id);
verify(HERE), nt;
verify(HERE), SuspendThread(nt) != -1;
ctx->ContextFlags = CONTEXT_FULL;
verify(HERE), GetThreadContext(nt, ctx);
ctx->ContextFlags = CONTEXT_FULL;
const u64 _rip = RIP(ctx);
RIP(ctx) = (u64)std::addressof(thread_ctrl::handle_interrupt);
verify(HERE), SetThreadContext(nt, ctx);
RIP(ctx) = _rip;
verify(HERE), ResumeThread(nt) != -1;
CloseHandle(nt);
#else
pthread_kill(reinterpret_cast<std::thread&>(m_thread).native_handle(), SIGUSR1);
#endif
std::unique_lock<std::mutex> lock(m_data->mutex, std::adopt_lock);
while (m_data->interrupt)
{
m_data->icv.wait(lock);
}
lock.release();
}
void thread_ctrl::test_interrupt()
{
if (m_guard & 0x80000000)
{
if (m_data->interrupt.exchange(nullptr))
{
lock(), unlock(), m_data->icv.notify_one();
}
return;
}
if (m_guard == 0x40000000 && !std::uncaught_exception())
{
m_guard = 0;
// Execute delayed interrupt handler
if (const auto handler = m_data->interrupt.exchange(nullptr))
{
lock(), unlock(), m_data->icv.notify_one();
return handler();
}
}
}
void thread_ctrl::sleep(u64 useconds)
{
std::this_thread::sleep_for(std::chrono::microseconds(useconds));
@@ -1993,18 +2280,18 @@ std::string named_thread::get_name() const
return fmt::format("('%s') Unnamed Thread", typeid(*this).name());
}
void named_thread::start()
void named_thread::start_thread(const std::shared_ptr<void>& _this)
{
// Get shared_ptr instance (will throw if called from the constructor or the object has been created incorrectly)
auto&& ptr = shared_from_this();
// Ensure it's not called from the constructor and the correct object is passed
verify("named_thread::start_thread" HERE), _this.get() == this;
// Run thread
m_thread = thread_ctrl::spawn(get_name(), [thread = std::move(ptr)]()
thread_ctrl::spawn(m_thread, get_name(), [this, _this]()
{
try
{
LOG_TRACE(GENERAL, "Thread started");
thread->on_task();
on_task();
LOG_TRACE(GENERAL, "Thread ended");
}
catch (const std::exception& e)
@@ -2017,6 +2304,6 @@ void named_thread::start()
LOG_NOTICE(GENERAL, "Thread aborted");
}
thread->on_exit();
on_exit();
});
}
+147 -17
View File
@@ -1,12 +1,12 @@
#pragma once
#include "types.h"
#include "Atomic.h"
#include <exception>
#include <string>
#include <memory>
#include "Platform.h"
#include "Atomic.h"
// Will report exception and call std::abort() if put in catch(...)
[[noreturn]] void catch_all_exceptions();
@@ -94,6 +94,9 @@ private:
// Thread join contention counter
atomic_t<u32> m_joining{};
// Thread interrupt guard counter
volatile u32 m_guard = 0x80000000;
// Thread internals
atomic_t<internal*> m_data{};
@@ -187,6 +190,42 @@ public:
// 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()
{
m_guard++;
}
// Interrupt guard recursive leave
void guard_leave()
{
if (UNLIKELY(--m_guard & 0x40000000))
{
test_interrupt();
}
}
// 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);
@@ -194,9 +233,12 @@ public:
// Wait until pred(). Abortable, may throw. Thread must be locked.
// Timeout in microseconds (zero means infinite).
template<typename F>
static inline auto wait(u64 useconds, F&& pred)
static inline auto wait_for(u64 useconds, F&& pred)
{
g_tls_this_thread->wait_start(useconds);
if (useconds)
{
g_tls_this_thread->wait_start(useconds);
}
while (true)
{
@@ -213,6 +255,26 @@ public:
}
}
// 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)
@@ -230,7 +292,7 @@ public:
}
}
// Wait once. Thread must be locked.
// Wait once. Abortable, may throw. Thread must be locked.
static inline void wait()
{
g_tls_this_thread->test();
@@ -238,7 +300,7 @@ public:
g_tls_this_thread->test();
}
// Wait unconditionally until aborted. Thread must be locked.
// Wait eternally. Abortable, may throw. Thread must be locked.
[[noreturn]] static inline void eternalize()
{
while (true)
@@ -263,17 +325,24 @@ public:
// Named thread factory
template<typename N, typename F>
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func)
static inline void spawn(N&& name, F&& func)
{
auto ctrl = std::make_shared<thread_ctrl>(std::forward<N>(name));
auto&& out = std::make_shared<thread_ctrl>(std::forward<N>(name));
thread_ctrl::start(ctrl, std::forward<F>(func));
thread_ctrl::start(out, std::forward<F>(func));
}
return ctrl;
// Named thread factory
template<typename N, typename F>
static inline void spawn(std::shared_ptr<thread_ctrl>& out, N&& name, F&& func)
{
out = std::make_shared<thread_ctrl>(std::forward<N>(name));
thread_ctrl::start(out, std::forward<F>(func));
}
};
class named_thread : public std::enable_shared_from_this<named_thread>
class named_thread
{
// Pointer to managed resource (shared with actual thread)
std::shared_ptr<thread_ctrl> m_thread;
@@ -290,8 +359,8 @@ public:
virtual std::string get_name() const;
protected:
// Start thread (cannot be called from the constructor: should throw bad_weak_ptr in such case)
void start();
// Start thread (cannot be called from the constructor: should throw in such case)
void start_thread(const std::shared_ptr<void>& _this);
// Thread task (called in the thread)
virtual void on_task() = 0;
@@ -301,9 +370,9 @@ protected:
public:
// ID initialization
virtual void on_init()
virtual void on_init(const std::shared_ptr<void>& _this)
{
start();
return start_thread(_this);
}
// ID finalization
@@ -317,6 +386,31 @@ public:
{
return m_thread.get();
}
void join() const
{
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
@@ -352,6 +446,36 @@ public:
}
};
// 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
{
@@ -360,8 +484,8 @@ class scope_thread final
public:
template<typename N, typename F>
scope_thread(N&& name, F&& func)
: m_thread(thread_ctrl::spawn(std::forward<N>(name), std::forward<F>(func)))
{
thread_ctrl::spawn(m_thread, std::forward<N>(name), std::forward<F>(func));
}
// Deleted copy/move constructors + copy/move operators
@@ -372,4 +496,10 @@ public:
{
m_thread->join();
}
// Access thread_ctrl
thread_ctrl* operator->() const
{
return m_thread.get();
}
};
+6 -9
View File
@@ -16,30 +16,27 @@ namespace memory_helper
void* reserve_memory(size_t size)
{
#ifdef _WIN32
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
ENSURES(ret != NULL);
return verify("reserve_memory" HERE, VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS));
#else
void* ret = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
ENSURES(ret != 0);
return verify("reserve_memory" HERE, ::mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0));
#endif
return ret;
}
void commit_page_memory(void* pointer, size_t size)
{
#ifdef _WIN32
VERIFY(VirtualAlloc(pointer, size, MEM_COMMIT, PAGE_READWRITE) != NULL);
verify(HERE), VirtualAlloc(pointer, size, MEM_COMMIT, PAGE_READWRITE);
#else
VERIFY(mprotect((void*)((u64)pointer & -4096), size, PROT_READ | PROT_WRITE) != -1);
verify(HERE), ::mprotect((void*)((u64)pointer & -4096), size, PROT_READ | PROT_WRITE) != -1;
#endif
}
void free_reserved_memory(void* pointer, size_t size)
{
#ifdef _WIN32
VERIFY(VirtualFree(pointer, 0, MEM_DECOMMIT) != 0);
verify(HERE), VirtualFree(pointer, 0, MEM_DECOMMIT);
#else
VERIFY(mprotect(pointer, size, PROT_NONE) != -1);
verify(HERE), ::mprotect(pointer, size, PROT_NONE) != -1;
#endif
}
}
+732
View File
@@ -0,0 +1,732 @@
#pragma once
/*
This header helps to extend scoped enum types (enum class) in two possible ways:
1) Enabling bitwise operators for enums
2) Advanced bs_t<> template (this converts enum type to another "bitset" enum type)
To enable bitwise operators, enum scope must contain `__bitwise_ops` entry.
enum class flags
{
__bitwise_ops, // Not essential, but recommended to put it first
flag1 = 1 << 0,
flag2 = 1 << 1,
};
Examples:
`flags::flag1 | flags::flag2` - bitwise OR
`flags::flag1 & flags::flag2` - bitwise AND
`flags::flag1 ^ flags::flag2` - bitwise XOR
`~flags::flag1` - bitwise NEG
To enable bs_t<> template, enum scope must contain `__bitset_enum_max` entry.
enum class flagzz : u32
{
flag1, // Bit indices start from zero
flag2,
__bitset_enum_max // It must be the last value
};
Now some operators are enabled for two enum types: `flagzz` and `bs_t<flagzz>`.
These are very different from previously described bitwise operators.
Examples:
`+flagzz::flag1` - unary `+` operator convert flagzz value to bs_t<flagzz>
`flagzz::flag1 + flagzz::flag2` - bitset union
`flagzz::flag1 - flagzz::flag2` - bitset difference
Intersection (&) and symmetric difference (^) is also available.
*/
#include "types.h"
// Helper template
template<typename T>
struct bs_base
{
// Underlying type
using under = std::underlying_type_t<T>;
// Actual bitset type
enum class type : under
{
null = 0, // Empty bitset
__bitset_set_type = 0 // SFINAE marker
};
static constexpr std::size_t bitmax = sizeof(T) * 8;
static constexpr std::size_t bitsize = static_cast<under>(T::__bitset_enum_max);
static_assert(std::is_enum<T>::value, "bs_t<> error: invalid type (must be enum)");
static_assert(!bitsize || bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max");
// Helper function
static constexpr under shift(T value)
{
return static_cast<under>(1) << static_cast<under>(value);
}
friend type& operator +=(type& lhs, type rhs)
{
reinterpret_cast<under&>(lhs) |= static_cast<under>(rhs);
return lhs;
}
friend type& operator -=(type& lhs, type rhs)
{
reinterpret_cast<under&>(lhs) &= ~static_cast<under>(rhs);
return lhs;
}
friend type& operator &=(type& lhs, type rhs)
{
reinterpret_cast<under&>(lhs) &= static_cast<under>(rhs);
return lhs;
}
friend type& operator ^=(type& lhs, type rhs)
{
reinterpret_cast<under&>(lhs) ^= static_cast<under>(rhs);
return lhs;
}
friend type& operator +=(type& lhs, T rhs)
{
reinterpret_cast<under&>(lhs) |= shift(rhs);
return lhs;
}
friend type& operator -=(type& lhs, T rhs)
{
reinterpret_cast<under&>(lhs) &= ~shift(rhs);
return lhs;
}
friend type& operator &=(type& lhs, T rhs)
{
reinterpret_cast<under&>(lhs) &= shift(rhs);
return lhs;
}
friend type& operator ^=(type& lhs, T rhs)
{
reinterpret_cast<under&>(lhs) ^= shift(rhs);
return lhs;
}
friend constexpr type operator +(type lhs, type rhs)
{
return static_cast<type>(static_cast<under>(lhs) | static_cast<under>(rhs));
}
friend constexpr type operator -(type lhs, type rhs)
{
return static_cast<type>(static_cast<under>(lhs) & ~static_cast<under>(rhs));
}
friend constexpr type operator &(type lhs, type rhs)
{
return static_cast<type>(static_cast<under>(lhs) & static_cast<under>(rhs));
}
friend constexpr type operator ^(type lhs, type rhs)
{
return static_cast<type>(static_cast<under>(lhs) ^ static_cast<under>(rhs));
}
friend constexpr type operator &(type lhs, T rhs)
{
return static_cast<type>(static_cast<under>(lhs) & shift(rhs));
}
friend constexpr type operator ^(type lhs, T rhs)
{
return static_cast<type>(static_cast<under>(lhs) ^ shift(rhs));
}
friend constexpr type operator &(T lhs, type rhs)
{
return static_cast<type>(shift(lhs) & static_cast<under>(rhs));
}
friend constexpr type operator ^(T lhs, type rhs)
{
return static_cast<type>(shift(lhs) ^ static_cast<under>(rhs));
}
friend constexpr bool operator ==(T lhs, type rhs)
{
return shift(lhs) == rhs;
}
friend constexpr bool operator ==(type lhs, T rhs)
{
return lhs == shift(rhs);
}
friend constexpr bool operator !=(T lhs, type rhs)
{
return shift(lhs) != rhs;
}
friend constexpr bool operator !=(type lhs, T rhs)
{
return lhs != shift(rhs);
}
friend constexpr bool test(type value)
{
return static_cast<under>(value) != 0;
}
friend constexpr bool test(type lhs, type rhs)
{
return (static_cast<under>(lhs) & static_cast<under>(rhs)) != 0;
}
friend constexpr bool test(type lhs, T rhs)
{
return (static_cast<under>(lhs) & shift(rhs)) != 0;
}
friend constexpr bool test(T lhs, type rhs)
{
return (shift(lhs) & static_cast<under>(rhs)) != 0;
}
friend bool test_and_set(type& lhs, type rhs)
{
return test_and_set(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
}
friend bool test_and_set(type& lhs, T rhs)
{
return test_and_set(reinterpret_cast<under&>(lhs), shift(rhs));
}
friend bool test_and_reset(type& lhs, type rhs)
{
return test_and_reset(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
}
friend bool test_and_reset(type& lhs, T rhs)
{
return test_and_reset(reinterpret_cast<under&>(lhs), shift(rhs));
}
friend bool test_and_complement(type& lhs, type rhs)
{
return test_and_complement(reinterpret_cast<under&>(lhs), static_cast<under>(rhs));
}
friend bool test_and_complement(type& lhs, T rhs)
{
return test_and_complement(reinterpret_cast<under&>(lhs), shift(rhs));
}
};
// Bitset type for enum class with available bits [0, T::__bitset_enum_max)
template<typename T>
using bs_t = typename bs_base<T>::type;
// Unary '+' operator: promote plain enum value to bitset value
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator +(T value)
{
return static_cast<bs_t<T>>(bs_base<T>::shift(value));
}
// Binary '+' operator: bitset union
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator +(T lhs, T rhs)
{
return static_cast<bs_t<T>>(bs_base<T>::shift(lhs) | bs_base<T>::shift(rhs));
}
// Binary '+' operator: bitset union
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator +(typename bs_base<T>::type lhs, T rhs)
{
return static_cast<bs_t<T>>(static_cast<typename bs_base<T>::under>(lhs) | bs_base<T>::shift(rhs));
}
// Binary '+' operator: bitset union
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator +(T lhs, typename bs_base<T>::type rhs)
{
return static_cast<bs_t<T>>(bs_base<T>::shift(lhs) | static_cast<typename bs_base<T>::under>(rhs));
}
// Binary '-' operator: bitset difference
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator -(T lhs, T rhs)
{
return static_cast<bs_t<T>>(bs_base<T>::shift(lhs) & ~bs_base<T>::shift(rhs));
}
// Binary '-' operator: bitset difference
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator -(typename bs_base<T>::type lhs, T rhs)
{
return static_cast<bs_t<T>>(static_cast<typename bs_base<T>::under>(lhs) & ~bs_base<T>::shift(rhs));
}
// Binary '-' operator: bitset difference
template<typename T, typename = decltype(T::__bitset_enum_max)>
constexpr bs_t<T> operator -(T lhs, typename bs_base<T>::type rhs)
{
return static_cast<bs_t<T>>(bs_base<T>::shift(lhs) & ~static_cast<typename bs_base<T>::under>(rhs));
}
template<typename BS, typename T>
struct atomic_add<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bs_t<T> op1(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::fetch_or(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto fetch_op = &op1;
static inline bs_t<T> op2(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::or_fetch(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename BS, typename T>
struct atomic_sub<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bs_t<T> op1(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), ~bs_base<T>::shift(right)));
}
static constexpr auto fetch_op = &op1;
static inline bs_t<T> op2(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), ~bs_base<T>::shift(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename BS, typename T>
struct atomic_and<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bs_t<T> op1(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto fetch_op = &op1;
static inline bs_t<T> op2(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename BS, typename T>
struct atomic_xor<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bs_t<T> op1(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::fetch_xor(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto fetch_op = &op1;
static inline bs_t<T> op2(bs_t<T>& left, T right)
{
return static_cast<bs_t<T>>(atomic_storage<under>::xor_fetch(reinterpret_cast<under&>(left), bs_base<T>::shift(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_add<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_or(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::or_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_sub<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), ~static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), ~static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_and<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_xor<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_xor(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::xor_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename BS, typename T>
struct atomic_test_and_set<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bool _op(bs_t<T>& left, T value)
{
return atomic_storage<under>::bts(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename BS, typename T>
struct atomic_test_and_reset<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bool _op(bs_t<T>& left, T value)
{
return atomic_storage<under>::btr(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename BS, typename T>
struct atomic_test_and_complement<BS, T, void_t<decltype(T::__bitset_enum_max), std::enable_if_t<std::is_same<BS, bs_t<T>>::value>>>
{
using under = typename bs_base<T>::under;
static inline bool _op(bs_t<T>& left, T value)
{
return atomic_storage<under>::btc(reinterpret_cast<under&>(left), static_cast<uint>(static_cast<under>(value)));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_set<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_set(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_reset<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_reset(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_complement<T, T, void_t<decltype(T::__bitset_set_type)>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_complement(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
// Binary '|' operator: bitwise OR
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr T operator |(T lhs, T rhs)
{
return static_cast<T>(std::underlying_type_t<T>(lhs) | std::underlying_type_t<T>(rhs));
}
// Binary '&' operator: bitwise AND
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr T operator &(T lhs, T rhs)
{
return static_cast<T>(std::underlying_type_t<T>(lhs) & std::underlying_type_t<T>(rhs));
}
// Binary '^' operator: bitwise XOR
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr T operator ^(T lhs, T rhs)
{
return static_cast<T>(std::underlying_type_t<T>(lhs) ^ std::underlying_type_t<T>(rhs));
}
// Unary '~' operator: bitwise NEG
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr T operator ~(T value)
{
return static_cast<T>(~std::underlying_type_t<T>(value));
}
// Bitwise OR assignment
template<typename T, typename = decltype(T::__bitwise_ops)>
inline T& operator |=(T& lhs, T rhs)
{
reinterpret_cast<std::underlying_type_t<T>&>(lhs) |= std::underlying_type_t<T>(rhs);
return lhs;
}
// Bitwise AND assignment
template<typename T, typename = decltype(T::__bitwise_ops)>
inline T& operator &=(T& lhs, T rhs)
{
reinterpret_cast<std::underlying_type_t<T>&>(lhs) &= std::underlying_type_t<T>(rhs);
return lhs;
}
// Bitwise XOR assignment
template<typename T, typename = decltype(T::__bitwise_ops)>
inline T& operator ^=(T& lhs, T rhs)
{
reinterpret_cast<std::underlying_type_t<T>&>(lhs) ^= std::underlying_type_t<T>(rhs);
return lhs;
}
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr bool test(T value)
{
return std::underlying_type_t<T>(value) != 0;
}
template<typename T, typename = decltype(T::__bitwise_ops)>
constexpr bool test(T lhs, T rhs)
{
return (std::underlying_type_t<T>(lhs) & std::underlying_type_t<T>(rhs)) != 0;
}
template<typename T, typename = decltype(T::__bitwise_ops)>
inline bool test_and_set(T& lhs, T rhs)
{
return test_and_set(reinterpret_cast<std::underlying_type_t<T>&>(lhs), std::underlying_type_t<T>(rhs));
}
template<typename T, typename = decltype(T::__bitwise_ops)>
inline bool test_and_reset(T& lhs, T rhs)
{
return test_and_reset(reinterpret_cast<std::underlying_type_t<T>&>(lhs), std::underlying_type_t<T>(rhs));
}
template<typename T, typename = decltype(T::__bitwise_ops)>
inline bool test_and_complement(T& lhs, T rhs)
{
return test_and_complement(reinterpret_cast<std::underlying_type_t<T>&>(lhs), std::underlying_type_t<T>(rhs));
}
template<typename T>
struct atomic_or<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_or(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::or_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_and<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_and(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::and_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_xor<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline T op1(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::fetch_xor(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto fetch_op = &op1;
static inline T op2(T& left, T right)
{
return static_cast<T>(atomic_storage<under>::xor_fetch(reinterpret_cast<under&>(left), static_cast<under>(right)));
}
static constexpr auto op_fetch = &op2;
static constexpr auto atomic_op = &op2;
};
template<typename T>
struct atomic_test_and_set<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_set(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_reset<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_reset(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
template<typename T>
struct atomic_test_and_complement<T, T, void_t<decltype(T::__bitwise_ops), std::enable_if_t<std::is_enum<T>::value>>>
{
using under = std::underlying_type_t<T>;
static inline bool _op(T& left, T value)
{
return atomic_storage<under>::test_and_complement(reinterpret_cast<under&>(left), static_cast<under>(value));
}
static constexpr auto fetch_op = &_op;
static constexpr auto op_fetch = &_op;
static constexpr auto atomic_op = &_op;
};
+614
View File
@@ -0,0 +1,614 @@
#pragma once
#include "types.h"
#include <climits>
#include <string>
#include <vector>
#include <algorithm>
/*
C-style format parser. Appends formatted string to `out`, returns number of characters written.
`out`: mutable reference to std::string, std::vector<char> or other compatible container
`fmt`: null-terminated string of `Char` type (char or constructible from char)
`src`: rvalue reference to argument provider.
*/
template<typename Dst, typename Char, typename Src>
std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
{
const std::size_t start_pos = out.size();
struct cfmt_context
{
std::size_t size; // Size of current format sequence
u8 args; // Number of extra args used
u8 type; // Integral type bytesize
bool dot; // Precision enabled
bool left;
bool sign;
bool space;
bool alter;
bool zeros;
uint width;
uint prec;
};
cfmt_context ctx{0};
// Error handling: print untouched sequence, stop further formatting
const auto drop_sequence = [&]
{
out.insert(out.end(), fmt - ctx.size, fmt);
ctx.size = -1;
};
const auto read_decimal = [&](uint result) -> uint
{
while (fmt[0] >= '0' && fmt[0] <= '9' && result <= (UINT_MAX / 10))
{
result = result * 10 + (fmt[0] - '0');
fmt++, ctx.size++;
}
return result;
};
const auto write_octal = [&](u64 value, u64 min_num)
{
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (cntlz64(value | 1, true) + 2) / 3), '0');
// Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 8)
{
*i = value % 8 + '0';
}
};
const auto write_hex = [&](u64 value, bool upper, u64 min_num)
{
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - cntlz64(value | 1, true) / 4), '0');
// Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 16)
{
*i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[value % 16];
}
};
const auto write_decimal = [&](u64 value, s64 min_size)
{
const std::size_t start = out.size();
do
{
out.push_back(value % 10 + '0');
value /= 10;
}
while (0 < --min_size || value);
// Revert written characters
for (std::size_t i = start, j = out.size() - 1; i < j; i++, j--)
{
std::swap(out[i], out[j]);
}
};
// Single pass over fmt string (null-terminated), TODO: check correct order
while (const Char ch = *fmt++) if (ctx.size == 0)
{
if (ch == '%')
{
ctx.size = 1;
}
else
{
out.push_back(ch);
}
}
else if (ctx.size == 1 && ch == '%')
{
ctx = {0};
out.push_back(ch);
}
else if (ctx.size == -1)
{
out.push_back(ch);
}
else switch (ctx.size++, ch)
{
case '-': ctx.left = true; break;
case '+': ctx.sign = true; break;
case ' ': ctx.space = true; break;
case '#': ctx.alter = true; break;
case '0': ctx.zeros = true; break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
if (UNLIKELY(ctx.width))
{
drop_sequence();
}
else
{
ctx.width = read_decimal(ch - '0');
}
break;
}
case '*':
{
if (UNLIKELY(ctx.width || !src.test(ctx.args)))
{
drop_sequence();
}
else
{
const int warg = src.template get<int>(ctx.args++);
ctx.width = std::abs(warg);
ctx.left |= warg < 0;
}
break;
}
case '.':
{
if (UNLIKELY(ctx.dot || ctx.prec))
{
drop_sequence();
}
else if (*fmt >= '0' && *fmt <= '9') // TODO: does it allow '0'?
{
ctx.prec = read_decimal(0);
ctx.dot = true;
}
else if (*fmt == '*')
{
if (UNLIKELY(!src.test(ctx.args)))
{
drop_sequence();
}
else
{
fmt++, ctx.size++;
const int parg = src.template get<int>(ctx.args++);
ctx.prec = std::max(parg, 0);
ctx.dot = parg >= 0;
}
}
else
{
ctx.prec = 0;
ctx.dot = true;
}
break;
}
case 'h':
{
if (UNLIKELY(ctx.type))
{
drop_sequence();
}
else if (fmt[0] == 'h')
{
fmt++, ctx.size++;
ctx.type = sizeof(char);
}
else
{
ctx.type = sizeof(short);
}
break;
}
case 'l':
{
if (UNLIKELY(ctx.type))
{
drop_sequence();
}
else if (fmt[0] == 'l')
{
fmt++, ctx.size++;
ctx.type = sizeof(llong);
}
else
{
ctx.type = sizeof(long);
}
break;
}
case 'z':
{
if (UNLIKELY(ctx.type))
{
drop_sequence();
}
else
{
ctx.type = sizeof(std::size_t);
}
break;
}
case 'j':
{
if (UNLIKELY(ctx.type))
{
drop_sequence();
}
else
{
ctx.type = sizeof(std::intmax_t);
}
break;
}
case 't':
{
if (UNLIKELY(ctx.type))
{
drop_sequence();
}
else
{
ctx.type = sizeof(std::ptrdiff_t);
}
break;
}
case 'c':
{
if (UNLIKELY(ctx.type || !src.test(ctx.args)))
{
drop_sequence();
break;
}
const std::size_t start = out.size();
out.push_back(src.template get<Char>(ctx.args));
if (1 < ctx.width)
{
// Add spaces if necessary
out.insert(out.begin() + start + ctx.left, ctx.width - 1, ' ');
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 's':
{
if (UNLIKELY(ctx.type || !src.test(ctx.args)))
{
drop_sequence();
break;
}
const std::size_t start = out.size();
const std::size_t size1 = src.fmt_string(out, ctx.args);
if (ctx.dot && size1 > ctx.prec)
{
// Shrink if necessary
out.resize(start + ctx.prec);
}
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add spaces if necessary
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'd':
case 'i':
{
if (UNLIKELY(!src.test(ctx.args)))
{
drop_sequence();
break;
}
if (!ctx.type)
{
ctx.type = (u8)src.type(ctx.args);
}
// Sign-extended argument expected
const u64 val = src.template get<u64>(ctx.args);
const bool negative = ctx.type && static_cast<s64>(val) < 0;
const std::size_t start = out.size();
if (!ctx.dot || ctx.prec)
{
if (negative)
{
out.push_back('-');
}
else if (ctx.sign)
{
out.push_back('+');
}
else if (ctx.space)
{
out.push_back(' ');
}
write_decimal(negative ? 0 - val : val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add padding if necessary
if (ctx.zeros && !ctx.left && !ctx.dot)
{
out.insert(out.begin() + start + (negative || ctx.sign || ctx.space), ctx.width - size2, '0');
}
else
{
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
}
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'o':
{
if (UNLIKELY(!src.test(ctx.args)))
{
drop_sequence();
break;
}
if (!ctx.type)
{
ctx.type = (u8)src.type(ctx.args);
}
const u64 mask =
ctx.type == 1 ? 0xffull :
ctx.type == 2 ? 0xffffull :
ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull;
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
if (ctx.alter)
{
out.push_back('0');
if (val)
{
write_octal(val, ctx.prec ? ctx.prec - 1 : 0);
}
}
else if (!ctx.dot || ctx.prec)
{
write_octal(val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add padding if necessary
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ctx.zeros && !ctx.left && !ctx.dot ? '0' : ' ');
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'x':
case 'X':
{
if (UNLIKELY(!src.test(ctx.args)))
{
drop_sequence();
break;
}
if (!ctx.type)
{
ctx.type = (u8)src.type(ctx.args);
}
const u64 mask =
ctx.type == 1 ? 0xffull :
ctx.type == 2 ? 0xffffull :
ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull;
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
if (ctx.alter)
{
out.push_back('0');
if (val)
{
out.push_back(ch); // Prepend 0x or 0X
write_hex(val, ch == 'X', ctx.prec);
}
}
else if (!ctx.dot || ctx.prec)
{
write_hex(val, ch == 'X', ctx.prec);
}
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add padding if necessary
if (ctx.zeros && !ctx.left && !ctx.dot)
{
out.insert(out.begin() + start + (ctx.alter && val ? 2 : 0), ctx.width - size2, '0');
}
else
{
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
}
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'u':
{
if (UNLIKELY(!src.test(ctx.args)))
{
drop_sequence();
break;
}
if (!ctx.type)
{
ctx.type = (u8)src.type(ctx.args);
}
const u64 mask =
ctx.type == 1 ? 0xffull :
ctx.type == 2 ? 0xffffull :
ctx.type == 4 ? 0xffffffffull : 0xffffffffffffffffull;
// Trunc sign-extended signed types
const u64 val = src.template get<u64>(ctx.args) & mask;
const std::size_t start = out.size();
if (!ctx.dot || ctx.prec)
{
write_decimal(val, ctx.prec);
}
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add padding if necessary
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ctx.zeros && !ctx.left && !ctx.dot ? '0' : ' ');
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'p':
{
if (UNLIKELY(!src.test(ctx.args) || ctx.type))
{
drop_sequence();
break;
}
const u64 val = src.template get<u64>(ctx.args);
const std::size_t start = out.size();
write_hex(val, false, sizeof(void*) * 2);
const std::size_t size2 = out.size() - start;
if (size2 < ctx.width)
{
// Add padding if necessary
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'f':
case 'F':
case 'e':
case 'E':
case 'a':
case 'A':
case 'g':
case 'G':
{
if (UNLIKELY(!src.test(ctx.args) || ctx.type))
{
drop_sequence();
break;
}
// Fallback (TODO)
const std::string _fmt(fmt - ctx.size, fmt);
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;
if (const std::size_t _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2))
{
out.resize(out.size() + _size);
std::snprintf(&out.front() + out.size() - _size, _size + 1, _fmt.c_str(), arg0, arg1, arg2);
}
src.skip(ctx.args);
ctx = {0};
break;
}
case 'L': // long double, not supported
case 'n': // writeback, not supported
default:
{
drop_sequence();
}
}
// Handle unfinished sequence
if (ctx.size && ctx.size != -1)
{
fmt--, drop_sequence();
}
return out.size() - start_pos;
}
+10
View File
@@ -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
+43 -1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
//! There is no way to know the current size. The smaller index is, the faster it's accessed.
@@ -103,3 +102,46 @@ public:
});
}
};
//! Simple lock-free map. Based on lf_array<>. All elements are accessible, implicitly initialized.
template<typename K, typename T, typename Hash = value_hash<K>, std::size_t Size = 256>
class lf_hashmap
{
struct pair_t
{
// Default-constructed key means "no key"
atomic_t<K> key{};
T value{};
};
//
lf_array<pair_t, Size> m_data{};
// Value for default-constructed key
T m_default_key_data{};
public:
constexpr lf_hashmap() = default;
// Access element (added implicitly)
T& operator [](const K& key)
{
if (UNLIKELY(key == K{}))
{
return m_default_key_data;
}
// Calculate hash and array position
for (std::size_t pos = Hash{}(key) % Size;; pos += Size)
{
// Access the array
auto& pair = m_data[pos];
// Check the key value (optimistic)
if (LIKELY(pair.key == key) || pair.key.compare_and_swap_test(K{}, key))
{
return pair.value;
}
}
}
};
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
// Based on variant/recursive_wrapper.hpp from boost.
//
// Original license:
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <cassert>
#include <utility>
//namespace mapbox {
//namespace util {
namespace std {
template <typename T>
class recursive_wrapper
{
T* p_;
void assign(T const& rhs)
{
this->get() = rhs;
}
public:
using type = T;
/**
* Default constructor default initializes the internally stored value.
* For POD types this means nothing is done and the storage is
* uninitialized.
*
* @throws std::bad_alloc if there is insufficient memory for an object
* of type T.
* @throws any exception thrown by the default constructur of T.
*/
recursive_wrapper()
: p_(new T){}
~recursive_wrapper() noexcept { delete p_; }
recursive_wrapper(recursive_wrapper const& operand)
: p_(new T(operand.get())) {}
recursive_wrapper(T const& operand)
: p_(new T(operand)) {}
recursive_wrapper(recursive_wrapper&& operand)
: p_(new T(std::move(operand.get()))) {}
recursive_wrapper(T&& operand)
: p_(new T(std::move(operand))) {}
inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
{
assign(rhs.get());
return *this;
}
inline recursive_wrapper& operator=(T const& rhs)
{
assign(rhs);
return *this;
}
inline void swap(recursive_wrapper& operand) noexcept
{
T* temp = operand.p_;
operand.p_ = p_;
p_ = temp;
}
recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
{
swap(rhs);
return *this;
}
recursive_wrapper& operator=(T&& rhs)
{
get() = std::move(rhs);
return *this;
}
T& get()
{
assert(p_);
return *get_pointer();
}
T const& get() const
{
assert(p_);
return *get_pointer();
}
T* get_pointer() { return p_; }
const T* get_pointer() const { return p_; }
operator T const&() const { return this->get(); }
operator T&() { return this->get(); }
}; // class recursive_wrapper
template <typename T>
inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
{
lhs.swap(rhs);
}
}
//} // namespace util
//} // namespace mapbox
#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
-1
View File
@@ -3,7 +3,6 @@
/* For internal use. Don't include. */
#include "types.h"
#include "Macro.h"
#include "Atomic.h"
#ifdef _WIN32
+556 -165
View File
File diff suppressed because it is too large Load Diff
+973
View File
@@ -0,0 +1,973 @@
#ifndef MAPBOX_UTIL_VARIANT_HPP
#define MAPBOX_UTIL_VARIANT_HPP
#include <cassert>
#include <cstddef> // size_t
#include <new> // operator new
#include <stdexcept> // runtime_error
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include "recursive_wrapper.hpp"
// clang-format off
// [[deprecated]] is only available in C++14, use this for the time being
#if __cplusplus <= 201103L
# ifdef __GNUC__
# define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated))
# elif defined(_MSC_VER)
# define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated)
# else
# define MAPBOX_VARIANT_DEPRECATED
# endif
#else
# define MAPBOX_VARIANT_DEPRECATED [[deprecated]]
#endif
#ifdef _MSC_VER
// https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
# ifdef NDEBUG
# define VARIANT_INLINE __forceinline
# else
# define VARIANT_INLINE //__declspec(noinline)
# endif
#else
# ifdef NDEBUG
# define VARIANT_INLINE //inline __attribute__((always_inline))
# else
# define VARIANT_INLINE __attribute__((noinline))
# endif
#endif
// clang-format on
// Exceptions
#if defined( __EXCEPTIONS) || defined( _MSC_VER)
#define HAS_EXCEPTIONS
#endif
#define VARIANT_MAJOR_VERSION 1
#define VARIANT_MINOR_VERSION 1
#define VARIANT_PATCH_VERSION 0
#define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
//namespace mapbox {
// namespace util {
namespace std {
// XXX This should derive from std::logic_error instead of std::runtime_error.
// See https://github.com/mapbox/variant/issues/48 for details.
class bad_variant_access : public std::runtime_error
{
public:
explicit bad_variant_access(const std::string& what_arg)
: runtime_error(what_arg) {}
explicit bad_variant_access(const char* what_arg)
: runtime_error(what_arg) {}
}; // class bad_variant_access
template <typename R = void>
struct MAPBOX_VARIANT_DEPRECATED static_visitor
{
using result_type = R;
protected:
static_visitor() {}
~static_visitor() {}
};
namespace detail {
static constexpr std::size_t invalid_value = std::size_t(-1);
template <typename T, typename... Types>
struct direct_type;
template <typename T, typename First, typename... Types>
struct direct_type<T, First, Types...>
{
static constexpr std::size_t index = std::is_same<T, First>::value
? sizeof...(Types)
: direct_type<T, Types...>::index;
};
template <typename T>
struct direct_type<T>
{
static constexpr std::size_t index = invalid_value;
};
#if __cpp_lib_logical_traits >= 201510L
using std::disjunction;
#else
template <typename...>
struct disjunction : std::false_type {};
template <typename B1>
struct disjunction<B1> : B1 {};
template <typename B1, typename B2>
struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
template <typename B1, typename... Bs>
struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
#endif
template <typename T, typename... Types>
struct convertible_type;
template <typename T, typename First, typename... Types>
struct convertible_type<T, First, Types...>
{
static constexpr std::size_t index = std::is_convertible<T, First>::value
? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
: convertible_type<T, Types...>::index;
};
template <typename T>
struct convertible_type<T>
{
static constexpr std::size_t index = invalid_value;
};
template <typename T, typename... Types>
struct value_traits
{
using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index;
static constexpr bool is_direct = direct_index != invalid_value;
static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index;
static constexpr bool is_valid = index != invalid_value;
static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0;
using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
};
template <typename T, typename R = void>
struct enable_if_type
{
using type = R;
};
template <typename F, typename V, typename Enable = void>
struct result_of_unary_visit
{
using type = typename std::result_of<F(V&)>::type;
};
template <typename F, typename V>
struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
{
using type = typename F::result_type;
};
template <typename F, typename V, typename Enable = void>
struct result_of_binary_visit
{
using type = typename std::result_of<F(V&, V&)>::type;
};
template <typename F, typename V>
struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
{
using type = typename F::result_type;
};
template <std::size_t arg1, std::size_t... others>
struct static_max;
template <std::size_t arg>
struct static_max<arg>
{
static const std::size_t value = arg;
};
template <std::size_t arg1, std::size_t arg2, std::size_t... others>
struct static_max<arg1, arg2, others...>
{
static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
};
template <typename... Types>
struct variant_helper;
template <typename T, typename... Types>
struct variant_helper<T, Types...>
{
VARIANT_INLINE static void destroy(const std::size_t type_index, void* data)
{
if (type_index == sizeof...(Types))
{
reinterpret_cast<T*>(data)->~T();
}
else
{
variant_helper<Types...>::destroy(type_index, data);
}
}
VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value)
{
if (old_type_index == sizeof...(Types))
{
new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
}
else
{
variant_helper<Types...>::move(old_type_index, old_value, new_value);
}
}
VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value)
{
if (old_type_index == sizeof...(Types))
{
new (new_value) T(*reinterpret_cast<const T*>(old_value));
}
else
{
variant_helper<Types...>::copy(old_type_index, old_value, new_value);
}
}
};
template <>
struct variant_helper<>
{
VARIANT_INLINE static void destroy(const std::size_t, void*) {}
VARIANT_INLINE static void move(const std::size_t, void*, void*) {}
VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {}
};
template <typename T>
struct unwrapper
{
static T const& apply_const(T const& obj) { return obj; }
static T& apply(T& obj) { return obj; }
};
template <typename T>
struct unwrapper<recursive_wrapper<T>>
{
static auto apply_const(recursive_wrapper<T> const& obj)
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
}
static auto apply(recursive_wrapper<T>& obj)
-> typename recursive_wrapper<T>::type&
{
return obj.get();
}
};
template <typename T>
struct unwrapper<std::reference_wrapper<T>>
{
static auto apply_const(std::reference_wrapper<T> const& obj)
-> typename std::reference_wrapper<T>::type const&
{
return obj.get();
}
static auto apply(std::reference_wrapper<T>& obj)
-> typename std::reference_wrapper<T>::type&
{
return obj.get();
}
};
template <typename F, typename V, typename R, typename... Types>
struct dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types>
struct dispatcher<F, V, R, T, Types...>
{
VARIANT_INLINE static R apply_const(V const& v, F&& f)
{
if (v.template is<T>())
{
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
}
else
{
return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
}
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
if (v.template is<T>())
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
}
else
{
return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
}
}
};
template <typename F, typename V, typename R, typename T>
struct dispatcher<F, V, R, T>
{
VARIANT_INLINE static R apply_const(V const& v, F&& f)
{
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
}
};
template <typename F, typename V, typename R, typename T, typename... Types>
struct binary_dispatcher_rhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
if (rhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
}
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (rhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
}
}
};
template <typename F, typename V, typename R, typename T0, typename T1>
struct binary_dispatcher_rhs<F, V, R, T0, T1>
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
}
};
template <typename F, typename V, typename R, typename T, typename... Types>
struct binary_dispatcher_lhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
if (lhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
}
else
{
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
}
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (lhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
}
else
{
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
}
}
};
template <typename F, typename V, typename R, typename T0, typename T1>
struct binary_dispatcher_lhs<F, V, R, T0, T1>
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
}
};
template <typename F, typename V, typename R, typename... Types>
struct binary_dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types>
struct binary_dispatcher<F, V, R, T, Types...>
{
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
{
if (v0.template is<T>())
{
if (v1.template is<T>())
{
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
}
}
else if (v1.template is<T>())
{
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
}
return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
if (v0.template is<T>())
{
if (v1.template is<T>())
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
}
else if (v1.template is<T>())
{
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
}
};
template <typename F, typename V, typename R, typename T>
struct binary_dispatcher<F, V, R, T>
{
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
{
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
}
};
// comparator functors
struct equal_comp
{
template <typename T>
bool operator()(T const& lhs, T const& rhs) const
{
return lhs == rhs;
}
};
struct less_comp
{
template <typename T>
bool operator()(T const& lhs, T const& rhs) const
{
return lhs < rhs;
}
};
template <typename Variant, typename Comp>
class comparer
{
public:
explicit comparer(Variant const& lhs) noexcept
: lhs_(lhs) {}
comparer& operator=(comparer const&) = delete;
// visitor
template <typename T>
bool operator()(T const& rhs_content) const
{
T const& lhs_content = lhs_.template get_unchecked<T>();
return Comp()(lhs_content, rhs_content);
}
private:
Variant const& lhs_;
};
} // namespace detail
struct no_init
{
};
template <typename... Types>
class variant
{
static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty");
static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
private:
static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
using first_type = typename std::tuple_element<0, std::tuple<Types...>>::type;
using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = detail::variant_helper<Types...>;
std::size_t type_index;
data_type data;
public:
VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
: type_index(sizeof...(Types)-1)
{
static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant");
new (&data) first_type();
}
VARIANT_INLINE variant(no_init) noexcept
: type_index(detail::invalid_value) {}
// http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
template <typename T, typename Traits = detail::value_traits<T, Types...>,
typename Enable = typename std::enable_if<Traits::is_valid>::type>
VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
: type_index(Traits::index)
{
new (&data) typename Traits::target_type(std::forward<T>(val));
}
VARIANT_INLINE variant(variant<Types...> const& old)
: type_index(old.type_index)
{
helper_type::copy(old.type_index, &old.data, &data);
}
VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<std::tuple<Types...>>::value)
: type_index(old.type_index)
{
helper_type::move(old.type_index, &old.data, &data);
}
private:
VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
{
helper_type::destroy(type_index, &data);
type_index = detail::invalid_value;
helper_type::copy(rhs.type_index, &rhs.data, &data);
type_index = rhs.type_index;
}
VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
{
helper_type::destroy(type_index, &data);
type_index = detail::invalid_value;
helper_type::move(rhs.type_index, &rhs.data, &data);
type_index = rhs.type_index;
}
public:
VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
{
move_assign(std::move(other));
return *this;
}
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
{
copy_assign(other);
return *this;
}
// conversions
// move-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept
{
variant<Types...> temp(std::forward<T>(rhs));
move_assign(std::move(temp));
return *this;
}
// copy-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
{
variant<Types...> temp(rhs);
copy_assign(temp);
return *this;
}
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE bool is() const
{
return type_index == detail::direct_type<T, Types...>::index;
}
template <typename T, typename std::enable_if<
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE bool is() const
{
return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
}
VARIANT_INLINE bool valid() const
{
return type_index != detail::invalid_value;
}
template <typename T, typename... Args>
VARIANT_INLINE void set(Args&&... args)
{
helper_type::destroy(type_index, &data);
type_index = detail::invalid_value;
new (&data) T(std::forward<Args>(args)...);
type_index = detail::direct_type<T, Types...>::index;
}
// get_unchecked<T>()
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get_unchecked()
{
return *reinterpret_cast<T*>(&data);
}
#ifdef HAS_EXCEPTIONS
// get<T>()
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get()
{
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T*>(&data);
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get_unchecked() const
{
return *reinterpret_cast<T const*>(&data);
}
#ifdef HAS_EXCEPTIONS
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get() const
{
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T const*>(&data);
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
// get_unchecked<T>() - T stored as recursive_wrapper<T>
template <typename T, typename std::enable_if<
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get_unchecked()
{
return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
}
#ifdef HAS_EXCEPTIONS
// get<T>() - T stored as recursive_wrapper<T>
template <typename T, typename std::enable_if<
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get()
{
if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
{
return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
template <typename T, typename std::enable_if<
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get_unchecked() const
{
return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
}
#ifdef HAS_EXCEPTIONS
template <typename T, typename std::enable_if<
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get() const
{
if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
{
return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
// get_unchecked<T>() - T stored as std::reference_wrapper<T>
template <typename T, typename std::enable_if<
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get_unchecked()
{
return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
}
#ifdef HAS_EXCEPTIONS
// get<T>() - T stored as std::reference_wrapper<T>
template <typename T, typename std::enable_if<
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get()
{
if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
{
return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
template <typename T, typename std::enable_if<
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get_unchecked() const
{
return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
}
#ifdef HAS_EXCEPTIONS
template <typename T, typename std::enable_if<
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get() const
{
if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
{
return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
}
else
{
throw bad_variant_access("in get<T>()");
}
}
#endif
// This function is deprecated because it returns an internal index field.
// Use which() instead.
MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const
{
return type_index;
}
VARIANT_INLINE int which() const noexcept
{
return static_cast<int>(sizeof...(Types)-type_index - 1);
}
template <typename T, typename std::enable_if<
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE static constexpr int which() noexcept
{
return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
}
// visitor
// unary
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
auto VARIANT_INLINE static visit(V const& v, F&& f)
-> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)))
{
return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
}
// non-const
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
auto VARIANT_INLINE static visit(V& v, F&& f)
-> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
{
return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
}
// binary
// const
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
{
return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
}
// non-const
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
{
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
}
~variant() noexcept // no-throw destructor
{
helper_type::destroy(type_index, &data);
}
// comparison operators
// equality
VARIANT_INLINE bool operator==(variant const& rhs) const
{
assert(valid() && rhs.valid());
if (this->which() != rhs.which())
{
return false;
}
detail::comparer<variant, detail::equal_comp> visitor(*this);
return visit(rhs, visitor);
}
VARIANT_INLINE bool operator!=(variant const& rhs) const
{
return !(*this == rhs);
}
// less than
VARIANT_INLINE bool operator<(variant const& rhs) const
{
assert(valid() && rhs.valid());
if (this->which() != rhs.which())
{
return this->which() < rhs.which();
}
detail::comparer<variant, detail::less_comp> visitor(*this);
return visit(rhs, visitor);
}
VARIANT_INLINE bool operator>(variant const& rhs) const
{
return rhs < *this;
}
VARIANT_INLINE bool operator<=(variant const& rhs) const
{
return !(*this > rhs);
}
VARIANT_INLINE bool operator>=(variant const& rhs) const
{
return !(*this < rhs);
}
};
// unary visitor interface
// const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f)))
{
return V::visit(v, std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
{
return V::visit(v, std::forward<F>(f));
}
// binary visitor interface
// const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
{
return V::binary_visit(v0, v1, std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
{
return V::binary_visit(v0, v1, std::forward<F>(f));
}
// getter interface
#ifdef HAS_EXCEPTIONS
template <typename ResultType, typename T>
auto get(T& var)->decltype(var.template get<ResultType>())
{
return var.template get<ResultType>();
}
#endif
template <typename ResultType, typename T>
ResultType& get_unchecked(T& var)
{
return var.template get_unchecked<ResultType>();
}
#ifdef HAS_EXCEPTIONS
template <typename ResultType, typename T>
auto get(T const& var)->decltype(var.template get<ResultType>())
{
return var.template get<ResultType>();
}
#endif
template <typename ResultType, typename T>
ResultType const& get_unchecked(T const& var)
{
return var.template get_unchecked<ResultType>();
}
}
// } // namespace util
//} // namespace mapbox
#endif // MAPBOX_UTIL_VARIANT_HPP
+3 -17
View File
@@ -14,26 +14,12 @@ namespace utils
case version_type::release: return "Release";
}
throw;
return "Unknown";
}
version::version(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo)
: m_hi(hi)
, m_mid(mid)
, m_lo(lo)
uint version::to_hex() const
{
}
version& version::type(version_type type, std::uint8_t type_index)
{
m_type = type;
m_type_index = type_index;
return *this;
}
std::uint16_t version::to_hex() const
{
return (m_hi << 24) | (m_mid << 16) | (m_lo << 8) | ((std::uint8_t(m_type) & 0xf) << 4) | (m_type_index & 0xf);
return (m_hi << 24) | (m_mid << 16) | (m_lo << 8) | ((uint(m_type) & 0xf) << 4) | (m_type_index & 0xf);
}
std::string version::to_string() const
+22 -21
View File
@@ -1,10 +1,11 @@
#pragma once
#include "types.h"
#include <string>
#include <cstdint>
namespace utils
{
enum class version_type : std::uint8_t
enum class version_type : uint
{
pre_alpha,
alpha,
@@ -17,29 +18,35 @@ namespace utils
class version
{
std::uint8_t m_hi;
std::uint8_t m_mid;
std::uint8_t m_lo;
uint m_hi;
uint m_mid;
uint m_lo;
version_type m_type = version_type::release;
std::uint8_t m_type_index = 1;
std::string m_postfix;
uint m_type_index = 1;
const char* m_postfix;
public:
version(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo = 0);
constexpr version(uint hi, uint mid, uint lo, version_type type, uint type_index, const char* postfix)
: m_hi(hi)
, m_mid(mid)
, m_lo(lo)
, m_type(type)
, m_type_index(type_index)
, m_postfix(postfix)
{
}
version& type(version_type type, std::uint8_t type_index = 1);
std::uint8_t hi() const
uint hi() const
{
return m_hi;
}
std::uint8_t mid() const
uint mid() const
{
return m_mid;
}
std::uint8_t lo() const
uint lo() const
{
return m_lo;
}
@@ -54,18 +61,12 @@ namespace utils
return m_postfix;
}
version& postfix(const std::string& value)
{
m_postfix = value;
return *this;
}
std::uint8_t type_index() const
uint type_index() const
{
return m_type_index;
}
std::uint16_t to_hex() const;
uint to_hex() const;
std::string to_string() const;
};
}
+1 -3
View File
@@ -1,8 +1,6 @@
if(APPLE)
else()
if(WIN32 AND NOT VULKAN_PREBUILT)
set(BUILD_TESTS OFF CACHE BOOL "Build tests" FORCE)
set(BUILD_DEMOS OFF CACHE BOOL "Build demos" FORCE)
# TravisCI break build with layers and vkjson
set(BUILD_LAYERS OFF CACHE BOOL "Build demos" FORCE)
set(BUILD_VKJSON OFF CACHE BOOL "Build demos" FORCE)
add_subdirectory( Vulkan-LoaderAndValidationLayers )
+9 -12
View File
@@ -39,23 +39,20 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release
</NMakeBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release</NMakeBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release</NMakeCleanCommandLine>
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release
</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug
</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug
</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF ../Vulkan-LoaderAndValidationLayers
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug</NMakeCleanCommandLine>
</PropertyGroup>
<ItemDefinitionGroup>
+7 -7
View File
@@ -9,21 +9,21 @@ clone_depth: 3
test: off
before_build:
# until git for win 2.5 release with commit checkout
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp rsx_program_decompiler
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp rsx_program_decompiler 3rdparty/cereal
- 7z x wxWidgets.7z -aos -oC:\rpcs3\wxWidgets > null
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
- 7z x vulkan.7z -aos -oC:\rpcs3\Vulkan > null
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/)
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/share/llvm/cmake -DZLIB_ROOT=C:/rpcs3/zlib/)
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/share/llvm/cmake -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
build_script:
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
install:
- ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/wxWidgets.7z'
# - ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/llvmlibs.7z'
- ps: Start-FileDownload 'https://drive.google.com/uc?export=download&id=0B-98fOyaZKJ5YWVnb29JZXFQWkU' -FileName llvmlibs.7z
- ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/zlib.7z'
- appveyor DownloadFile "https://dl.dropboxusercontent.com/s/c1by0uulee6g8th/wxWidgets.7z?dl=0" -FileName wxWidgets.7z
- appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-98fOyaZKJ5YWVnb29JZXFQWkU" -FileName llvmlibs.7z
- appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRa21fbDQteTN1dGs" -FileName vulkan.7z
- appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B6v_qtb9hkicQ2hHa2dRbF83cE0" -FileName zlib.7z
- set WXWIN=C:\rpcs3\wxWidgets
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;C:\wxWidgets;%PATH%
+485
View File
@@ -0,0 +1,485 @@
#!/usr/bin/env python
#
#===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
r"""
clang-format git integration
============================
This file provides a clang-format integration for git. Put it somewhere in your
path and ensure that it is executable. Then, "git clang-format" will invoke
clang-format on the changes in current files or a specific commit.
For further details, run:
git clang-format -h
Requires Python 2.7
"""
import argparse
import collections
import contextlib
import errno
import os
import re
import subprocess
import sys
usage = 'git clang-format [OPTIONS] [<commit>] [--] [<file>...]'
desc = '''
Run clang-format on all lines that differ between the working directory
and <commit>, which defaults to HEAD. Changes are only applied to the working
directory.
The following git-config settings set the default of the corresponding option:
clangFormat.binary
clangFormat.commit
clangFormat.extension
clangFormat.style
'''
# Name of the temporary index file in which save the output of clang-format.
# This file is created within the .git directory.
temp_index_basename = 'clang-format-index'
Range = collections.namedtuple('Range', 'start, count')
def main():
config = load_git_config()
# In order to keep '--' yet allow options after positionals, we need to
# check for '--' ourselves. (Setting nargs='*' throws away the '--', while
# nargs=argparse.REMAINDER disallows options after positionals.)
argv = sys.argv[1:]
try:
idx = argv.index('--')
except ValueError:
dash_dash = []
else:
dash_dash = argv[idx:]
argv = argv[:idx]
default_extensions = ','.join([
# From clang/lib/Frontend/FrontendOptions.cpp, all lower case
'c', 'h', # C
'm', # ObjC
'mm', # ObjC++
'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp', # C++
# Other languages that clang-format supports
'proto', 'protodevel', # Protocol Buffers
'js', # JavaScript
'ts', # TypeScript
])
p = argparse.ArgumentParser(
usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter,
description=desc)
p.add_argument('--binary',
default=config.get('clangformat.binary', 'clang-format'),
help='path to clang-format'),
p.add_argument('--commit',
default=config.get('clangformat.commit', 'HEAD'),
help='default commit to use if none is specified'),
p.add_argument('--diff', action='store_true',
help='print a diff instead of applying the changes')
p.add_argument('--extensions',
default=config.get('clangformat.extensions',
default_extensions),
help=('comma-separated list of file extensions to format, '
'excluding the period and case-insensitive')),
p.add_argument('-f', '--force', action='store_true',
help='allow changes to unstaged files')
p.add_argument('-p', '--patch', action='store_true',
help='select hunks interactively')
p.add_argument('-q', '--quiet', action='count', default=0,
help='print less information')
p.add_argument('--style',
default=config.get('clangformat.style', None),
help='passed to clang-format'),
p.add_argument('-v', '--verbose', action='count', default=0,
help='print extra information')
# We gather all the remaining positional arguments into 'args' since we need
# to use some heuristics to determine whether or not <commit> was present.
# However, to print pretty messages, we make use of metavar and help.
p.add_argument('args', nargs='*', metavar='<commit>',
help='revision from which to compute the diff')
p.add_argument('ignored', nargs='*', metavar='<file>...',
help='if specified, only consider differences in these files')
opts = p.parse_args(argv)
opts.verbose -= opts.quiet
del opts.quiet
commit, files = interpret_args(opts.args, dash_dash, opts.commit)
changed_lines = compute_diff_and_extract_lines(commit, files)
if opts.verbose >= 1:
ignored_files = set(changed_lines)
filter_by_extension(changed_lines, opts.extensions.lower().split(','))
if opts.verbose >= 1:
ignored_files.difference_update(changed_lines)
if ignored_files:
print 'Ignoring changes in the following files (wrong extension):'
for filename in ignored_files:
print ' ', filename
if changed_lines:
print 'Running clang-format on the following files:'
for filename in changed_lines:
print ' ', filename
if not changed_lines:
print 'no modified files to format'
return
# The computed diff outputs absolute paths, so we must cd before accessing
# those files.
cd_to_toplevel()
old_tree = create_tree_from_workdir(changed_lines)
new_tree = run_clang_format_and_save_to_tree(changed_lines,
binary=opts.binary,
style=opts.style)
if opts.verbose >= 1:
print 'old tree:', old_tree
print 'new tree:', new_tree
if old_tree == new_tree:
if opts.verbose >= 0:
print 'clang-format did not modify any files'
elif opts.diff:
print_diff(old_tree, new_tree)
else:
changed_files = apply_changes(old_tree, new_tree, force=opts.force,
patch_mode=opts.patch)
if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
print 'changed files:'
for filename in changed_files:
print ' ', filename
def load_git_config(non_string_options=None):
"""Return the git configuration as a dictionary.
All options are assumed to be strings unless in `non_string_options`, in which
is a dictionary mapping option name (in lower case) to either "--bool" or
"--int"."""
if non_string_options is None:
non_string_options = {}
out = {}
for entry in run('git', 'config', '--list', '--null').split('\0'):
if entry:
name, value = entry.split('\n', 1)
if name in non_string_options:
value = run('git', 'config', non_string_options[name], name)
out[name] = value
return out
def interpret_args(args, dash_dash, default_commit):
"""Interpret `args` as "[commit] [--] [files...]" and return (commit, files).
It is assumed that "--" and everything that follows has been removed from
args and placed in `dash_dash`.
If "--" is present (i.e., `dash_dash` is non-empty), the argument to its
left (if present) is taken as commit. Otherwise, the first argument is
checked if it is a commit or a file. If commit is not given,
`default_commit` is used."""
if dash_dash:
if len(args) == 0:
commit = default_commit
elif len(args) > 1:
die('at most one commit allowed; %d given' % len(args))
else:
commit = args[0]
object_type = get_object_type(commit)
if object_type not in ('commit', 'tag'):
if object_type is None:
die("'%s' is not a commit" % commit)
else:
die("'%s' is a %s, but a commit was expected" % (commit, object_type))
files = dash_dash[1:]
elif args:
if disambiguate_revision(args[0]):
commit = args[0]
files = args[1:]
else:
commit = default_commit
files = args
else:
commit = default_commit
files = []
return commit, files
def disambiguate_revision(value):
"""Returns True if `value` is a revision, False if it is a file, or dies."""
# If `value` is ambiguous (neither a commit nor a file), the following
# command will die with an appropriate error message.
run('git', 'rev-parse', value, verbose=False)
object_type = get_object_type(value)
if object_type is None:
return False
if object_type in ('commit', 'tag'):
return True
die('`%s` is a %s, but a commit or filename was expected' %
(value, object_type))
def get_object_type(value):
"""Returns a string description of an object's type, or None if it is not
a valid git object."""
cmd = ['git', 'cat-file', '-t', value]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
return None
return stdout.strip()
def compute_diff_and_extract_lines(commit, files):
"""Calls compute_diff() followed by extract_lines()."""
diff_process = compute_diff(commit, files)
changed_lines = extract_lines(diff_process.stdout)
diff_process.stdout.close()
diff_process.wait()
if diff_process.returncode != 0:
# Assume error was already printed to stderr.
sys.exit(2)
return changed_lines
def compute_diff(commit, files):
"""Return a subprocess object producing the diff from `commit`.
The return value's `stdin` file object will produce a patch with the
differences between the working directory and `commit`, filtered on `files`
(if non-empty). Zero context lines are used in the patch."""
cmd = ['git', 'diff-index', '-p', '-U0', commit, '--']
cmd.extend(files)
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.close()
return p
def extract_lines(patch_file):
"""Extract the changed lines in `patch_file`.
The return value is a dictionary mapping filename to a list of (start_line,
line_count) pairs.
The input must have been produced with ``-U0``, meaning unidiff format with
zero lines of context. The return value is a dict mapping filename to a
list of line `Range`s."""
matches = {}
for line in patch_file:
match = re.search(r'^\+\+\+\ [^/]+/(.*)', line)
if match:
filename = match.group(1).rstrip('\r\n')
match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count > 0:
matches.setdefault(filename, []).append(Range(start_line, line_count))
return matches
def filter_by_extension(dictionary, allowed_extensions):
"""Delete every key in `dictionary` that doesn't have an allowed extension.
`allowed_extensions` must be a collection of lowercase file extensions,
excluding the period."""
allowed_extensions = frozenset(allowed_extensions)
for filename in dictionary.keys():
base_ext = filename.rsplit('.', 1)
if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
del dictionary[filename]
def cd_to_toplevel():
"""Change to the top level of the git repository."""
toplevel = run('git', 'rev-parse', '--show-toplevel')
os.chdir(toplevel)
def create_tree_from_workdir(filenames):
"""Create a new git tree with the given files from the working directory.
Returns the object ID (SHA-1) of the created tree."""
return create_tree(filenames, '--stdin')
def run_clang_format_and_save_to_tree(changed_lines, binary='clang-format',
style=None):
"""Run clang-format on each file and save the result to a git tree.
Returns the object ID (SHA-1) of the created tree."""
def index_info_generator():
for filename, line_ranges in changed_lines.iteritems():
mode = oct(os.stat(filename).st_mode)
blob_id = clang_format_to_blob(filename, line_ranges, binary=binary,
style=style)
yield '%s %s\t%s' % (mode, blob_id, filename)
return create_tree(index_info_generator(), '--index-info')
def create_tree(input_lines, mode):
"""Create a tree object from the given input.
If mode is '--stdin', it must be a list of filenames. If mode is
'--index-info' is must be a list of values suitable for "git update-index
--index-info", such as "<mode> <SP> <sha1> <TAB> <filename>". Any other mode
is invalid."""
assert mode in ('--stdin', '--index-info')
cmd = ['git', 'update-index', '--add', '-z', mode]
with temporary_index_file():
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
for line in input_lines:
p.stdin.write('%s\0' % line)
p.stdin.close()
if p.wait() != 0:
die('`%s` failed' % ' '.join(cmd))
tree_id = run('git', 'write-tree')
return tree_id
def clang_format_to_blob(filename, line_ranges, binary='clang-format',
style=None):
"""Run clang-format on the given file and save the result to a git blob.
Returns the object ID (SHA-1) of the created blob."""
clang_format_cmd = [binary, filename]
if style:
clang_format_cmd.extend(['-style='+style])
clang_format_cmd.extend([
'-lines=%s:%s' % (start_line, start_line+line_count-1)
for start_line, line_count in line_ranges])
try:
clang_format = subprocess.Popen(clang_format_cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
except OSError as e:
if e.errno == errno.ENOENT:
die('cannot find executable "%s"' % binary)
else:
raise
clang_format.stdin.close()
hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin']
hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout,
stdout=subprocess.PIPE)
clang_format.stdout.close()
stdout = hash_object.communicate()[0]
if hash_object.returncode != 0:
die('`%s` failed' % ' '.join(hash_object_cmd))
if clang_format.wait() != 0:
die('`%s` failed' % ' '.join(clang_format_cmd))
return stdout.rstrip('\r\n')
@contextlib.contextmanager
def temporary_index_file(tree=None):
"""Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
the file afterward."""
index_path = create_temporary_index(tree)
old_index_path = os.environ.get('GIT_INDEX_FILE')
os.environ['GIT_INDEX_FILE'] = index_path
try:
yield
finally:
if old_index_path is None:
del os.environ['GIT_INDEX_FILE']
else:
os.environ['GIT_INDEX_FILE'] = old_index_path
os.remove(index_path)
def create_temporary_index(tree=None):
"""Create a temporary index file and return the created file's path.
If `tree` is not None, use that as the tree to read in. Otherwise, an
empty index is created."""
gitdir = run('git', 'rev-parse', '--git-dir')
path = os.path.join(gitdir, temp_index_basename)
if tree is None:
tree = '--empty'
run('git', 'read-tree', '--index-output='+path, tree)
return path
def print_diff(old_tree, new_tree):
"""Print the diff between the two trees to stdout."""
# We use the porcelain 'diff' and not plumbing 'diff-tree' because the output
# is expected to be viewed by the user, and only the former does nice things
# like color and pagination.
subprocess.check_call(['git', 'diff', old_tree, new_tree, '--'])
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
"""Apply the changes in `new_tree` to the working directory.
Bails if there are local changes in those files and not `force`. If
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
changed_files = run('git', 'diff-tree', '-r', '-z', '--name-only', old_tree,
new_tree).rstrip('\0').split('\0')
if not force:
unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
if unstaged_files:
print >>sys.stderr, ('The following files would be modified but '
'have unstaged changes:')
print >>sys.stderr, unstaged_files
print >>sys.stderr, 'Please commit, stage, or stash them first.'
sys.exit(2)
if patch_mode:
# In patch mode, we could just as well create an index from the new tree
# and checkout from that, but then the user will be presented with a
# message saying "Discard ... from worktree". Instead, we use the old
# tree as the index and checkout from new_tree, which gives the slightly
# better message, "Apply ... to index and worktree". This is not quite
# right, since it won't be applied to the user's index, but oh well.
with temporary_index_file(old_tree):
subprocess.check_call(['git', 'checkout', '--patch', new_tree])
index_tree = old_tree
else:
with temporary_index_file(new_tree):
run('git', 'checkout-index', '-a', '-f')
return changed_files
def run(*args, **kwargs):
stdin = kwargs.pop('stdin', '')
verbose = kwargs.pop('verbose', True)
strip = kwargs.pop('strip', True)
for name in kwargs:
raise TypeError("run() got an unexpected keyword argument '%s'" % name)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input=stdin)
if p.returncode == 0:
if stderr:
if verbose:
print >>sys.stderr, '`%s` printed to stderr:' % ' '.join(args)
print >>sys.stderr, stderr.rstrip()
if strip:
stdout = stdout.rstrip('\r\n')
return stdout
if verbose:
print >>sys.stderr, '`%s` returned %s' % (' '.join(args), p.returncode)
if stderr:
print >>sys.stderr, stderr.rstrip()
sys.exit(2)
def die(message):
print >>sys.stderr, 'error:', message
sys.exit(2)
if __name__ == '__main__':
main()
+1 -1
Submodule llvm updated: 051e787f26...69e5622092
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# git pre-commit hook that run git-clang-format when committing.
# To use it install clang-format and python 2.7 then copy this
# file to .git/hooks/ and remove the extension
git clang-format --style=file --diff > style.patch
git apply --index style.patch
rm style.patch
exit 0
+6 -20
View File
@@ -12,21 +12,8 @@ add_custom_command(OUTPUT something_that_never_exists
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/git-version.cmake)
if(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.0) # TODO: the same for (apple) clang
message(FATAL_ERROR "GCC ${CMAKE_CXX_COMPILER_VERSION} is too old.")
endif()
# Warnings
add_compile_options(-Wno-attributes -Wno-enum-compare -Wno-invalid-offsetof)
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
add_compile_options(-ftemplate-depth=1024)
if(APPLE)
add_compile_options(-stdlib=libc++)
endif()
if(WIN32)
add_compile_options(-pthread)
endif()
endif()
# Check for a sufficient compiler and set build options
include(ConfigureCompiler)
if(WIN32)
add_definitions(-DUNICODE)
@@ -148,6 +135,7 @@ ${LLVM_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/../3rdparty/stblib"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/shader_code"
"${RPCS3_SRC_DIR}/../3rdparty/cereal/include"
)
if(WIN32)
include_directories(BEFORE "${RPCS3_SRC_DIR}/../3rdparty/XAudio2_7") # Slimmed down version of minidx9 for XAudio2_7 only
@@ -171,6 +159,7 @@ endif()
link_directories(
"${RPCS3_SRC_DIR}/../3rdparty/minidx12/"
"${RPCS3_SRC_DIR}/../Vulkan"
)
if(NOT USE_SYSTEM_FFMPEG)
@@ -194,7 +183,7 @@ RPCS3_SRC
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit/*.cpp"
)
if(APPLE)
if(NOT WIN32)
set (EXCLUDE_DIR "/RSX/VK/")
foreach (TMP_PATH ${RPCS3_SRC})
string (FIND ${TMP_PATH} ${EXCLUDE_DIR} EXCLUDE_DIR_FOUND)
@@ -212,7 +201,7 @@ if(MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /DYNAMICBASE:NO /BASE:0x10000 /FIXED")
endif()
if(WIN32)
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV)
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV HLSL)
if(NOT MSVC)
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} opengl32.lib glu32.lib libpthread)
else()
@@ -233,9 +222,6 @@ else()
else()
target_link_libraries(rpcs3 png16_static)
endif()
if (NOT APPLE)
target_link_libraries(rpcs3 vulkan glslang OSDependent OGLCompiler SPIRV)
endif()
endif()
if(LLVM_FOUND)
target_link_libraries(rpcs3 ${LLVM_LIBS})
+14 -14
View File
@@ -7,86 +7,86 @@
// TODO: Still reliant on wxWidgets for zlib functions. Alternative solutions?
#include <zlib.h>
force_inline u8 Read8(const fs::file& f)
inline u8 Read8(const fs::file& f)
{
u8 ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u16 Read16(const fs::file& f)
inline u16 Read16(const fs::file& f)
{
be_t<u16> ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u32 Read32(const fs::file& f)
inline u32 Read32(const fs::file& f)
{
be_t<u32> ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u64 Read64(const fs::file& f)
inline u64 Read64(const fs::file& f)
{
be_t<u64> ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u16 Read16LE(const fs::file& f)
inline u16 Read16LE(const fs::file& f)
{
u16 ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u32 Read32LE(const fs::file& f)
inline u32 Read32LE(const fs::file& f)
{
u32 ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline u64 Read64LE(const fs::file& f)
inline u64 Read64LE(const fs::file& f)
{
u64 ret;
f.read(&ret, sizeof(ret));
return ret;
}
force_inline void Write8(const fs::file& f, const u8 data)
inline void Write8(const fs::file& f, const u8 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write16LE(const fs::file& f, const u16 data)
inline void Write16LE(const fs::file& f, const u16 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write32LE(const fs::file& f, const u32 data)
inline void Write32LE(const fs::file& f, const u32 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write64LE(const fs::file& f, const u64 data)
inline void Write64LE(const fs::file& f, const u64 data)
{
f.write(&data, sizeof(data));
}
force_inline void Write16(const fs::file& f, const be_t<u16> data)
inline void Write16(const fs::file& f, const be_t<u16> data)
{
f.write(&data, sizeof(data));
}
force_inline void Write32(const fs::file& f, const be_t<u32> data)
inline void Write32(const fs::file& f, const be_t<u32> data)
{
f.write(&data, sizeof(data));
}
force_inline void Write64(const fs::file& f, const be_t<u64> data)
inline void Write64(const fs::file& f, const be_t<u64> data)
{
f.write(&data, sizeof(data));
}
+1 -1
View File
@@ -24,7 +24,7 @@ void AudioDumper::WriteData(const void* buffer, u32 size)
{
if (GetCh())
{
VERIFY(m_output.write(buffer, size) == size);
verify(HERE), size, m_output.write(buffer, size) == size;
m_header.Size += size;
m_header.RIFF.Size += size;
}
+163
View File
@@ -0,0 +1,163 @@
#ifdef _WIN32
#include "Utilities/Log.h"
#include "Utilities/StrFmt.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "XAudio2Thread.h"
#include "3rdparty/XAudio2_7/XAudio2.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
static thread_local HMODULE s_tls_xaudio2_lib{};
static thread_local IXAudio2* s_tls_xaudio2_instance{};
static thread_local IXAudio2MasteringVoice* s_tls_master_voice{};
static thread_local IXAudio2SourceVoice* s_tls_source_voice{};
void XAudio2Thread::xa27_init(void* lib2_7)
{
s_tls_xaudio2_lib = (HMODULE)lib2_7;
HRESULT hr = S_OK;
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CoInitializeEx() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
hr = XAudio2Create(&s_tls_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : XAudio2Create() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, 8, 48000);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", (u32)hr);
s_tls_xaudio2_instance->Release();
Emu.Pause();
}
}
void XAudio2Thread::xa27_destroy()
{
if (s_tls_source_voice != nullptr)
{
s_tls_source_voice->Stop();
s_tls_source_voice->DestroyVoice();
}
if (s_tls_master_voice != nullptr)
{
s_tls_master_voice->DestroyVoice();
}
if (s_tls_xaudio2_instance != nullptr)
{
s_tls_xaudio2_instance->StopEngine();
s_tls_xaudio2_instance->Release();
}
CoUninitialize();
FreeLibrary(s_tls_xaudio2_lib);
}
void XAudio2Thread::xa27_play()
{
HRESULT hr = s_tls_source_voice->Start();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Start() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa27_flush()
{
HRESULT hr = s_tls_source_voice->FlushSourceBuffers();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : FlushSourceBuffers() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa27_stop()
{
HRESULT hr = s_tls_source_voice->Stop();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Stop() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa27_open()
{
HRESULT hr;
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
WORD channels = 8;
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = 48000;
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.cbSize = 0;
hr = s_tls_xaudio2_instance->CreateSourceVoice(&s_tls_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateSourceVoice() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
s_tls_source_voice->SetVolume(4.0);
}
void XAudio2Thread::xa27_add(const void* src, int size)
{
XAUDIO2_VOICE_STATE state;
s_tls_source_voice->GetState(&state);
// XAudio 2.7 bug workaround, when it says "SimpList: non-growable list ran out of room for new elements" and hits int 3
if (state.BuffersQueued > 32)
{
LOG_WARNING(GENERAL, "XAudio2Thread : too many buffers enqueued (%d, pos=%u)", state.BuffersQueued, state.SamplesPlayed);
return xa27_flush();
}
XAUDIO2_BUFFER buffer;
buffer.AudioBytes = size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pAudioData = (const BYTE*)src;
buffer.pContext = 0;
buffer.PlayBegin = 0;
buffer.PlayLength = 256;
HRESULT hr = s_tls_source_voice->SubmitSourceBuffer(&buffer);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : AddData() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
#endif
+164
View File
@@ -0,0 +1,164 @@
#ifdef _WIN32
#include "Utilities/Log.h"
#include "Utilities/StrFmt.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "XAudio2Thread.h"
#include "3rdparty/minidx12/Include/xaudio2.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
static thread_local HMODULE s_tls_xaudio2_lib{};
static thread_local IXAudio2* s_tls_xaudio2_instance{};
static thread_local IXAudio2MasteringVoice* s_tls_master_voice{};
static thread_local IXAudio2SourceVoice* s_tls_source_voice{};
void XAudio2Thread::xa28_init(void* lib)
{
s_tls_xaudio2_lib = (HMODULE)lib;
const auto create = (XAudio2Create)GetProcAddress(s_tls_xaudio2_lib, "XAudio2Create");
HRESULT hr = S_OK;
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CoInitializeEx() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
hr = create(&s_tls_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : XAudio2Create() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
hr = s_tls_xaudio2_instance->CreateMasteringVoice(&s_tls_master_voice, 8, 48000);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", (u32)hr);
s_tls_xaudio2_instance->Release();
Emu.Pause();
}
}
void XAudio2Thread::xa28_destroy()
{
if (s_tls_source_voice != nullptr)
{
s_tls_source_voice->Stop();
s_tls_source_voice->DestroyVoice();
}
if (s_tls_master_voice != nullptr)
{
s_tls_master_voice->DestroyVoice();
}
if (s_tls_xaudio2_instance != nullptr)
{
s_tls_xaudio2_instance->StopEngine();
s_tls_xaudio2_instance->Release();
}
CoUninitialize();
FreeLibrary(s_tls_xaudio2_lib);
}
void XAudio2Thread::xa28_play()
{
HRESULT hr = s_tls_source_voice->Start();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Start() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa28_flush()
{
HRESULT hr = s_tls_source_voice->FlushSourceBuffers();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : FlushSourceBuffers() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa28_stop()
{
HRESULT hr = s_tls_source_voice->Stop();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Stop() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
void XAudio2Thread::xa28_open()
{
HRESULT hr;
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
WORD channels = 8;
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = 48000;
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.cbSize = 0;
hr = s_tls_xaudio2_instance->CreateSourceVoice(&s_tls_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateSourceVoice() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
s_tls_source_voice->SetVolume(4.0);
}
void XAudio2Thread::xa28_add(const void* src, int size)
{
XAUDIO2_VOICE_STATE state;
s_tls_source_voice->GetState(&state);
if (state.BuffersQueued > 32)
{
LOG_WARNING(GENERAL, "XAudio2Thread : too many buffers enqueued (%d, pos=%u)", state.BuffersQueued, state.SamplesPlayed);
return xa28_flush();
}
XAUDIO2_BUFFER buffer;
buffer.AudioBytes = size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pAudioData = (const BYTE*)src;
buffer.pContext = 0;
buffer.PlayBegin = 0;
buffer.PlayLength = 256;
HRESULT hr = s_tls_source_voice->SubmitSourceBuffer(&buffer);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : AddData() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
}
#endif
+55 -105
View File
@@ -1,148 +1,98 @@
#ifdef _WIN32
#include "Utilities/Log.h"
#include "Utilities/StrFmt.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "XAudio2Thread.h"
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
#include <Windows.h>
XAudio2Thread::XAudio2Thread()
: m_xaudio2_instance(nullptr)
, m_master_voice(nullptr)
, m_source_voice(nullptr)
{
HRESULT hr = S_OK;
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CoInitializeEx() failed(0x%08x)", (u32)hr);
Emu.Pause();
LOG_ERROR(GENERAL, "XAudio: failed to increase thread priority");
}
if (auto lib2_9 = LoadLibraryExW(L"XAudio2_9.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))
{
// xa28* implementation is fully compatible with library 2.9
xa28_init(lib2_9);
m_funcs.destroy = &xa28_destroy;
m_funcs.play = &xa28_play;
m_funcs.flush = &xa28_flush;
m_funcs.stop = &xa28_stop;
m_funcs.open = &xa28_open;
m_funcs.add = &xa28_add;
LOG_SUCCESS(GENERAL, "XAudio 2.9 initialized");
return;
}
hr = XAudio2Create(&m_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr))
if (auto lib2_7 = LoadLibraryExW(L"XAudio2_7.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))
{
LOG_ERROR(GENERAL, "XAudio2Thread : XAudio2Create() failed(0x%08x)", (u32)hr);
Emu.Pause();
xa27_init(lib2_7);
m_funcs.destroy = &xa27_destroy;
m_funcs.play = &xa27_play;
m_funcs.flush = &xa27_flush;
m_funcs.stop = &xa27_stop;
m_funcs.open = &xa27_open;
m_funcs.add = &xa27_add;
LOG_SUCCESS(GENERAL, "XAudio 2.7 initialized");
return;
}
if (auto lib2_8 = LoadLibraryExW(L"XAudio2_8.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))
{
xa28_init(lib2_8);
m_funcs.destroy = &xa28_destroy;
m_funcs.play = &xa28_play;
m_funcs.flush = &xa28_flush;
m_funcs.stop = &xa28_stop;
m_funcs.open = &xa28_open;
m_funcs.add = &xa28_add;
LOG_SUCCESS(GENERAL, "XAudio 2.8 initialized");
return;
}
hr = m_xaudio2_instance->CreateMasteringVoice(&m_master_voice);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateMasteringVoice() failed(0x%08x)", (u32)hr);
m_xaudio2_instance->Release();
Emu.Pause();
}
fmt::throw_exception("No supported XAudio2 library found");
}
XAudio2Thread::~XAudio2Thread()
{
if (m_source_voice != nullptr)
{
m_source_voice->Stop();
m_source_voice->DestroyVoice();
}
if (m_master_voice != nullptr)
{
m_master_voice->DestroyVoice();
}
if (m_xaudio2_instance != nullptr)
{
m_xaudio2_instance->StopEngine();
m_xaudio2_instance->Release();
}
CoUninitialize();
m_funcs.destroy();
}
void XAudio2Thread::Play()
{
HRESULT hr = m_source_voice->Start();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Start() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
m_funcs.play();
}
void XAudio2Thread::Close()
{
Stop();
HRESULT hr = m_source_voice->FlushSourceBuffers();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : FlushSourceBuffers() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
m_funcs.stop();
m_funcs.flush();
}
void XAudio2Thread::Stop()
{
HRESULT hr = m_source_voice->Stop();
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : Stop() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
m_funcs.stop();
}
void XAudio2Thread::Open(const void* src, int size)
{
HRESULT hr;
WORD sample_size = g_cfg_audio_convert_to_u16 ? sizeof(u16) : sizeof(float);
WORD channels = 8;
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = g_cfg_audio_convert_to_u16 ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
waveformatex.nChannels = channels;
waveformatex.nSamplesPerSec = 48000;
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
waveformatex.nBlockAlign = channels * sample_size;
waveformatex.wBitsPerSample = sample_size * 8;
waveformatex.cbSize = 0;
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : CreateSourceVoice() failed(0x%08x)", (u32)hr);
Emu.Pause();
return;
}
m_source_voice->SetVolume(4.0);
AddData(src, size);
Play();
m_funcs.open();
m_funcs.add(src, size);
m_funcs.play();
}
void XAudio2Thread::AddData(const void* src, int size)
{
XAUDIO2_BUFFER buffer;
buffer.AudioBytes = size;
buffer.Flags = 0;
buffer.LoopBegin = XAUDIO2_NO_LOOP_REGION;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pAudioData = (const BYTE*)src;
buffer.pContext = 0;
buffer.PlayBegin = 0;
buffer.PlayLength = 256;
HRESULT hr = m_source_voice->SubmitSourceBuffer(&buffer);
if (FAILED(hr))
{
LOG_ERROR(GENERAL, "XAudio2Thread : AddData() failed(0x%08x)", (u32)hr);
Emu.Pause();
}
m_funcs.add(src, size);
}
#endif
+27 -5
View File
@@ -4,13 +4,35 @@
#include "Emu/Audio/AudioThread.h"
#include "3rdparty/XAudio2_7/XAudio2.h"
class XAudio2Thread : public AudioThread
{
IXAudio2* m_xaudio2_instance;
IXAudio2MasteringVoice* m_master_voice;
IXAudio2SourceVoice* m_source_voice;
struct vtable
{
void(*destroy)();
void(*play)();
void(*flush)();
void(*stop)();
void(*open)();
void(*add)(const void*, int);
};
vtable m_funcs;
static void xa27_init(void*);
static void xa27_destroy();
static void xa27_play();
static void xa27_flush();
static void xa27_stop();
static void xa27_open();
static void xa27_add(const void*, int);
static void xa28_init(void*);
static void xa28_destroy();
static void xa28_play();
static void xa28_flush();
static void xa28_stop();
static void xa28_open();
static void xa28_add(const void*, int);
public:
XAudio2Thread();
+65 -29
View File
@@ -3,30 +3,55 @@
#include "CPUThread.h"
#include <mutex>
#include <condition_variable>
template<>
void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](cpu_flag f)
{
switch (f)
{
STR_CASE(cpu_flag::stop);
STR_CASE(cpu_flag::exit);
STR_CASE(cpu_flag::suspend);
STR_CASE(cpu_flag::ret);
STR_CASE(cpu_flag::signal);
STR_CASE(cpu_flag::dbg_global_pause);
STR_CASE(cpu_flag::dbg_global_stop);
STR_CASE(cpu_flag::dbg_pause);
STR_CASE(cpu_flag::dbg_step);
case cpu_flag::__bitset_enum_max: break;
}
return unknown;
});
}
template<>
void fmt_class_string<bs_t<cpu_flag>>::format(std::string& out, u64 arg)
{
format_bitset(out, arg, "[", "|", "]", &fmt_class_string<cpu_flag>::format);
}
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
extern std::mutex& get_current_thread_mutex();
extern std::condition_variable& get_current_thread_cv();
void cpu_thread::on_task()
{
state -= cpu_state::exit;
state -= cpu_flag::exit;
g_tls_current_cpu_thread = this;
Emu.SendDbgCommand(DID_CREATE_THREAD, this);
std::unique_lock<std::mutex> lock(get_current_thread_mutex());
std::unique_lock<named_thread> lock(*this);
// Check thread status
while (!(state & cpu_state::exit))
while (!test(state & cpu_flag::exit))
{
CHECK_EMU_STATUS;
// check stop status
if (!(state & cpu_state::stop))
if (!test(state & cpu_flag::stop))
{
if (lock) lock.unlock();
@@ -34,7 +59,7 @@ void cpu_thread::on_task()
{
cpu_task();
}
catch (cpu_state _s)
catch (cpu_flag _s)
{
state += _s;
}
@@ -44,7 +69,7 @@ void cpu_thread::on_task()
throw;
}
state -= cpu_state::ret;
state -= cpu_flag::ret;
continue;
}
@@ -54,39 +79,38 @@ void cpu_thread::on_task()
continue;
}
get_current_thread_cv().wait(lock);
thread_ctrl::wait();
}
}
void cpu_thread::on_stop()
{
state += cpu_state::exit;
(*this)->lock_notify();
state += cpu_flag::exit;
lock_notify();
}
cpu_thread::~cpu_thread()
{
}
cpu_thread::cpu_thread(cpu_type type)
: type(type)
cpu_thread::cpu_thread()
{
}
bool cpu_thread::check_status()
bool cpu_thread::check_state()
{
std::unique_lock<std::mutex> lock(get_current_thread_mutex(), std::defer_lock);
std::unique_lock<named_thread> lock(*this, std::defer_lock);
while (true)
{
CHECK_EMU_STATUS; // check at least once
if (state & cpu_state::exit)
if (test(state & cpu_flag::exit))
{
return true;
}
if (!state.test(cpu_state_pause) && !state.test(cpu_state::interrupt))
if (!test(state & cpu_state_pause))
{
break;
}
@@ -97,26 +121,38 @@ bool cpu_thread::check_status()
continue;
}
if (!state.test(cpu_state_pause) && state & cpu_state::interrupt && handle_interrupt())
{
continue;
}
get_current_thread_cv().wait(lock);
thread_ctrl::wait();
}
const auto state_ = state.load();
if (state_ & make_bitset(cpu_state::ret, cpu_state::stop))
if (test(state_, cpu_flag::ret + cpu_flag::stop))
{
return true;
}
if (state_ & cpu_state::dbg_step)
if (test(state_, cpu_flag::dbg_step))
{
state += cpu_state::dbg_pause;
state -= cpu_state::dbg_step;
state += cpu_flag::dbg_pause;
state -= cpu_flag::dbg_step;
}
return false;
}
void cpu_thread::run()
{
state -= cpu_flag::stop;
lock_notify();
}
void cpu_thread::set_signal()
{
verify("cpu_flag::signal" HERE), !state.test_and_set(cpu_flag::signal);
notify(); // TODO: lock_notify?
}
std::string cpu_thread::dump() const
{
return fmt::format("Type: %s\n" "State: %s\n", typeid(*this).name(), state.load());
}
+18 -59
View File
@@ -1,77 +1,60 @@
#pragma once
#include "../Utilities/Thread.h"
#include "../Utilities/BitSet.h"
#include "../Utilities/bit_set.h"
// CPU Thread Type
enum class cpu_type : u8
{
ppu, // PPU Thread
spu, // SPU Thread
arm, // ARMv7 Thread
};
// CPU Thread State flags
enum struct cpu_state : u16
// Thread state flags
enum class cpu_flag : u32
{
stop, // Thread not running (HLE, initial state)
exit, // Irreversible exit
suspend, // Thread paused
ret, // Callback return requested
signal, // Thread received a signal (HLE)
interrupt, // Thread interrupted
dbg_global_pause, // Emulation paused
dbg_global_stop, // Emulation stopped
dbg_pause, // Thread paused
dbg_step, // Thread forced to pause after one step (one instruction, etc)
__bitset_enum_max
};
// CPU Thread State flags: pause state union
constexpr bitset_t<cpu_state> cpu_state_pause = make_bitset(cpu_state::suspend, cpu_state::dbg_global_pause, cpu_state::dbg_pause);
// Flag set for pause state
constexpr bs_t<cpu_flag> cpu_state_pause = cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause;
class cpu_thread : public named_thread
{
void on_task() override;
void on_task() override final;
public:
virtual void on_stop() override;
virtual ~cpu_thread() override;
const id_value<> id{};
const cpu_type type;
cpu_thread(cpu_type type);
// Public recursive sleep state counter
atomic_t<u8> sleep_counter{};
cpu_thread();
// Public thread state
atomic_t<bitset_t<cpu_state>> state{ cpu_state::stop };
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
// Object associated with sleep state, possibly synchronization primitive (mutex, semaphore, etc.)
atomic_t<void*> owner{};
// Process thread state, return true if the checker must return
bool check_status();
bool check_state();
// Increse sleep counter
void sleep()
{
if (!sleep_counter++) return; //handle_interrupt();
}
// Run thread
void run();
// Decrese sleep counter
void awake()
{
if (!--sleep_counter) owner = nullptr;
}
// Set cpu_flag::signal
void set_signal();
// Print CPU state
virtual std::string dump() const = 0;
virtual void cpu_init() {}
virtual std::string dump() const;
// Thread entry point function
virtual void cpu_task() = 0;
virtual bool handle_interrupt() { return false; }
};
inline cpu_thread* get_current_cpu_thread() noexcept
@@ -80,27 +63,3 @@ inline cpu_thread* get_current_cpu_thread() noexcept
return g_tls_current_cpu_thread;
}
// Helper for cpu_thread.
// 1) Calls sleep() and locks the thread in the constructor.
// 2) Calls awake() and unlocks the thread in the destructor.
class cpu_thread_lock final
{
cpu_thread& m_thread;
public:
cpu_thread_lock(const cpu_thread_lock&) = delete;
cpu_thread_lock(cpu_thread& thread)
: m_thread(thread)
{
m_thread.sleep();
m_thread->lock();
}
~cpu_thread_lock()
{
m_thread.awake();
m_thread->unlock();
}
};
+69 -208
View File
@@ -1,215 +1,76 @@
#pragma once
#define ERROR_CODE(code) static_cast<s32>(code)
enum CellOk : s32
struct CellOk
{
CELL_OK = 0,
enum : s32
{
__not_an_error,
CELL_OK = 0
};
};
enum CellError : s32
// Temporary workaround
constexpr auto CELL_OK = CellOk::CELL_OK;
enum CellError : u32
{
CELL_EAGAIN = ERROR_CODE(0x80010001), // The resource is temporarily unavailable
CELL_EINVAL = ERROR_CODE(0x80010002), // An invalid argument value is specified
CELL_ENOSYS = ERROR_CODE(0x80010003), // The feature is not yet implemented
CELL_ENOMEM = ERROR_CODE(0x80010004), // Memory allocation failure
CELL_ESRCH = ERROR_CODE(0x80010005), // The resource with the specified identifier does not exist
CELL_ENOENT = ERROR_CODE(0x80010006), // The file does not exist
CELL_ENOEXEC = ERROR_CODE(0x80010007), // The file is in unrecognized format
CELL_EDEADLK = ERROR_CODE(0x80010008), // Resource deadlock is avoided
CELL_EPERM = ERROR_CODE(0x80010009), // The operation is not permitted
CELL_EBUSY = ERROR_CODE(0x8001000A), // The device or resource is busy
CELL_ETIMEDOUT = ERROR_CODE(0x8001000B), // The operation is timed out
CELL_EABORT = ERROR_CODE(0x8001000C), // The operation is aborted
CELL_EFAULT = ERROR_CODE(0x8001000D), // Invalid memory access
CELL_ESTAT = ERROR_CODE(0x8001000F), // State of the target thread is invalid
CELL_EALIGN = ERROR_CODE(0x80010010), // Alignment is invalid.
CELL_EKRESOURCE = ERROR_CODE(0x80010011), // Shortage of the kernel resources
CELL_EISDIR = ERROR_CODE(0x80010012), // The file is a directory
CELL_ECANCELED = ERROR_CODE(0x80010013), // Operation canceled
CELL_EEXIST = ERROR_CODE(0x80010014), // Entry already exists
CELL_EISCONN = ERROR_CODE(0x80010015), // Port is already connected
CELL_ENOTCONN = ERROR_CODE(0x80010016), // Port is not connected
CELL_EAUTHFAIL = ERROR_CODE(0x80010017), // Program authentication fail
CELL_ENOTMSELF = ERROR_CODE(0x80010018), // The file is not a MSELF
CELL_ESYSVER = ERROR_CODE(0x80010019), // System version error
CELL_EAUTHFATAL = ERROR_CODE(0x8001001A), // Fatal system error
CELL_EDOM = ERROR_CODE(0x8001001B),
CELL_ERANGE = ERROR_CODE(0x8001001C),
CELL_EILSEQ = ERROR_CODE(0x8001001D),
CELL_EFPOS = ERROR_CODE(0x8001001E),
CELL_EINTR = ERROR_CODE(0x8001001F),
CELL_EFBIG = ERROR_CODE(0x80010020),
CELL_EMLINK = ERROR_CODE(0x80010021),
CELL_ENFILE = ERROR_CODE(0x80010022),
CELL_ENOSPC = ERROR_CODE(0x80010023),
CELL_ENOTTY = ERROR_CODE(0x80010024),
CELL_EPIPE = ERROR_CODE(0x80010025),
CELL_EROFS = ERROR_CODE(0x80010026),
CELL_ESPIPE = ERROR_CODE(0x80010027),
CELL_E2BIG = ERROR_CODE(0x80010028),
CELL_EACCES = ERROR_CODE(0x80010029),
CELL_EBADF = ERROR_CODE(0x8001002A),
CELL_EIO = ERROR_CODE(0x8001002B),
CELL_EMFILE = ERROR_CODE(0x8001002C),
CELL_ENODEV = ERROR_CODE(0x8001002D),
CELL_ENOTDIR = ERROR_CODE(0x8001002E),
CELL_ENXIO = ERROR_CODE(0x8001002F),
CELL_EXDEV = ERROR_CODE(0x80010030),
CELL_EBADMSG = ERROR_CODE(0x80010031),
CELL_EINPROGRESS = ERROR_CODE(0x80010032),
CELL_EMSGSIZE = ERROR_CODE(0x80010033),
CELL_ENAMETOOLONG = ERROR_CODE(0x80010034),
CELL_ENOLCK = ERROR_CODE(0x80010035),
CELL_ENOTEMPTY = ERROR_CODE(0x80010036),
CELL_ENOTSUP = ERROR_CODE(0x80010037),
CELL_EFSSPECIFIC = ERROR_CODE(0x80010038),
CELL_EOVERFLOW = ERROR_CODE(0x80010039),
CELL_ENOTMOUNTED = ERROR_CODE(0x8001003A),
CELL_ENOTSDATA = ERROR_CODE(0x8001003B),
CELL_EAGAIN = 0x80010001, // The resource is temporarily unavailable
CELL_EINVAL = 0x80010002, // An invalid argument value is specified
CELL_ENOSYS = 0x80010003, // The feature is not yet implemented
CELL_ENOMEM = 0x80010004, // Memory allocation failure
CELL_ESRCH = 0x80010005, // The resource with the specified identifier does not exist
CELL_ENOENT = 0x80010006, // The file does not exist
CELL_ENOEXEC = 0x80010007, // The file is in unrecognized format
CELL_EDEADLK = 0x80010008, // Resource deadlock is avoided
CELL_EPERM = 0x80010009, // The operation is not permitted
CELL_EBUSY = 0x8001000A, // The device or resource is busy
CELL_ETIMEDOUT = 0x8001000B, // The operation is timed out
CELL_EABORT = 0x8001000C, // The operation is aborted
CELL_EFAULT = 0x8001000D, // Invalid memory access
CELL_ESTAT = 0x8001000F, // State of the target thread is invalid
CELL_EALIGN = 0x80010010, // Alignment is invalid.
CELL_EKRESOURCE = 0x80010011, // Shortage of the kernel resources
CELL_EISDIR = 0x80010012, // The file is a directory
CELL_ECANCELED = 0x80010013, // Operation canceled
CELL_EEXIST = 0x80010014, // Entry already exists
CELL_EISCONN = 0x80010015, // Port is already connected
CELL_ENOTCONN = 0x80010016, // Port is not connected
CELL_EAUTHFAIL = 0x80010017, // Program authentication fail
CELL_ENOTMSELF = 0x80010018, // The file is not a MSELF
CELL_ESYSVER = 0x80010019, // System version error
CELL_EAUTHFATAL = 0x8001001A, // Fatal system error
CELL_EDOM = 0x8001001B,
CELL_ERANGE = 0x8001001C,
CELL_EILSEQ = 0x8001001D,
CELL_EFPOS = 0x8001001E,
CELL_EINTR = 0x8001001F,
CELL_EFBIG = 0x80010020,
CELL_EMLINK = 0x80010021,
CELL_ENFILE = 0x80010022,
CELL_ENOSPC = 0x80010023,
CELL_ENOTTY = 0x80010024,
CELL_EPIPE = 0x80010025,
CELL_EROFS = 0x80010026,
CELL_ESPIPE = 0x80010027,
CELL_E2BIG = 0x80010028,
CELL_EACCES = 0x80010029,
CELL_EBADF = 0x8001002A,
CELL_EIO = 0x8001002B,
CELL_EMFILE = 0x8001002C,
CELL_ENODEV = 0x8001002D,
CELL_ENOTDIR = 0x8001002E,
CELL_ENXIO = 0x8001002F,
CELL_EXDEV = 0x80010030,
CELL_EBADMSG = 0x80010031,
CELL_EINPROGRESS = 0x80010032,
CELL_EMSGSIZE = 0x80010033,
CELL_ENAMETOOLONG = 0x80010034,
CELL_ENOLCK = 0x80010035,
CELL_ENOTEMPTY = 0x80010036,
CELL_ENOTSUP = 0x80010037,
CELL_EFSSPECIFIC = 0x80010038,
CELL_EOVERFLOW = 0x80010039,
CELL_ENOTMOUNTED = 0x8001003A,
CELL_ENOTSDATA = 0x8001003B,
};
// Special return type signaling on errors
struct ppu_error_code
{
s32 value;
// Print error message, error code is returned
static s32 report(s32 error, const char* text);
// Must be specialized for specific tag type T
template<typename T>
static const char* print(T code)
{
return nullptr;
}
template<typename T>
s32 error_check(T code)
{
if (const auto text = print(code))
{
return report(code, text);
}
return code;
}
ppu_error_code() = default;
// General error check
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
ppu_error_code(T value)
: value(error_check(value))
{
}
// Force error reporting with a message specified
ppu_error_code(s32 value, const char* text)
: value(report(value, text))
{
}
// Helper
enum class not_an_error : s32 {};
// Silence any error
constexpr ppu_error_code(not_an_error value)
: value(static_cast<s32>(value))
{
}
// Conversion
constexpr operator s32() const
{
return value;
}
};
// Helper macro for silencing possible error checks on returning ppu_error_code values
#define NOT_AN_ERROR(...) static_cast<ppu_error_code::not_an_error>(__VA_ARGS__)
template<typename T, typename>
struct ppu_gpr_cast_impl;
template<>
struct ppu_gpr_cast_impl<ppu_error_code, void>
{
static inline u64 to(const ppu_error_code& code)
{
return code;
}
static inline ppu_error_code from(const u64 reg)
{
return NOT_AN_ERROR(reg);
}
};
template<>
inline const char* ppu_error_code::print(CellError error)
{
switch (error)
{
STR_CASE(CELL_EAGAIN);
STR_CASE(CELL_EINVAL);
STR_CASE(CELL_ENOSYS);
STR_CASE(CELL_ENOMEM);
STR_CASE(CELL_ESRCH);
STR_CASE(CELL_ENOENT);
STR_CASE(CELL_ENOEXEC);
STR_CASE(CELL_EDEADLK);
STR_CASE(CELL_EPERM);
STR_CASE(CELL_EBUSY);
STR_CASE(CELL_ETIMEDOUT);
STR_CASE(CELL_EABORT);
STR_CASE(CELL_EFAULT);
STR_CASE(CELL_ESTAT);
STR_CASE(CELL_EALIGN);
STR_CASE(CELL_EKRESOURCE);
STR_CASE(CELL_EISDIR);
STR_CASE(CELL_ECANCELED);
STR_CASE(CELL_EEXIST);
STR_CASE(CELL_EISCONN);
STR_CASE(CELL_ENOTCONN);
STR_CASE(CELL_EAUTHFAIL);
STR_CASE(CELL_ENOTMSELF);
STR_CASE(CELL_ESYSVER);
STR_CASE(CELL_EAUTHFATAL);
STR_CASE(CELL_EDOM);
STR_CASE(CELL_ERANGE);
STR_CASE(CELL_EILSEQ);
STR_CASE(CELL_EFPOS);
STR_CASE(CELL_EINTR);
STR_CASE(CELL_EFBIG);
STR_CASE(CELL_EMLINK);
STR_CASE(CELL_ENFILE);
STR_CASE(CELL_ENOSPC);
STR_CASE(CELL_ENOTTY);
STR_CASE(CELL_EPIPE);
STR_CASE(CELL_EROFS);
STR_CASE(CELL_ESPIPE);
STR_CASE(CELL_E2BIG);
STR_CASE(CELL_EACCES);
STR_CASE(CELL_EBADF);
STR_CASE(CELL_EIO);
STR_CASE(CELL_EMFILE);
STR_CASE(CELL_ENODEV);
STR_CASE(CELL_ENOTDIR);
STR_CASE(CELL_ENXIO);
STR_CASE(CELL_EXDEV);
STR_CASE(CELL_EBADMSG);
STR_CASE(CELL_EINPROGRESS);
STR_CASE(CELL_EMSGSIZE);
STR_CASE(CELL_ENAMETOOLONG);
STR_CASE(CELL_ENOLCK);
STR_CASE(CELL_ENOTEMPTY);
STR_CASE(CELL_ENOTSUP);
STR_CASE(CELL_EFSSPECIFIC);
STR_CASE(CELL_EOVERFLOW);
STR_CASE(CELL_ENOTMOUNTED);
STR_CASE(CELL_ENOTSDATA);
}
return nullptr;
}
+391 -353
View File
@@ -3,8 +3,6 @@
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
extern std::mutex g_mutex_avcodec_open2;
extern "C"
{
#include "libavcodec/avcodec.h"
@@ -15,97 +13,391 @@ extern "C"
#include "cellPamf.h"
#include "cellAdec.h"
#include <mutex>
#include <thread>
extern std::mutex g_mutex_avcodec_open2;
logs::channel cellAdec("cellAdec", logs::level::notice);
AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
: type(type)
, memAddr(addr)
, memSize(size)
, memBias(0)
, cbFunc(func)
, cbArg(arg)
, is_closed(false)
, is_finished(false)
, just_started(false)
, just_finished(false)
, codec(nullptr)
, input_format(nullptr)
, ctx(nullptr)
, fmt(nullptr)
class AudioDecoder : public ppu_thread
{
av_register_all();
avcodec_register_all();
public:
squeue_t<AdecTask> job;
volatile bool is_closed;
volatile bool is_finished;
bool just_started;
bool just_finished;
switch (type)
{
case CELL_ADEC_TYPE_ATRACX:
case CELL_ADEC_TYPE_ATRACX_2CH:
case CELL_ADEC_TYPE_ATRACX_6CH:
case CELL_ADEC_TYPE_ATRACX_8CH:
{
codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
input_format = av_find_input_format("oma");
break;
}
case CELL_ADEC_TYPE_MP3:
{
codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
input_format = av_find_input_format("mp3");
break;
}
default:
{
throw EXCEPTION("Unknown type (0x%x)", type);
}
}
if (!codec)
{
throw EXCEPTION("avcodec_find_decoder() failed");
}
if (!input_format)
{
throw EXCEPTION("av_find_input_format() failed");
}
fmt = avformat_alloc_context();
if (!fmt)
{
throw EXCEPTION("avformat_alloc_context() failed");
}
io_buf = (u8*)av_malloc(4096);
fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL);
if (!fmt->pb)
{
throw EXCEPTION("avio_alloc_context() failed");
}
}
AVCodec* codec;
AVInputFormat* input_format;
AVCodecContext* ctx;
AVFormatContext* fmt;
u8* io_buf;
AudioDecoder::~AudioDecoder()
{
// TODO: check finalization
AdecFrame af;
while (frames.try_pop(af))
struct AudioReader
{
av_frame_unref(af.data);
av_frame_free(&af.data);
}
if (ctx)
{
avcodec_close(ctx);
avformat_close_input(&fmt);
}
if (fmt)
{
if (io_buf)
u32 addr;
u32 size;
bool init;
bool has_ats;
AudioReader()
: init(false)
{
av_free(io_buf);
}
if (fmt->pb) av_free(fmt->pb);
avformat_free_context(fmt);
} reader;
squeue_t<AdecFrame> frames;
const s32 type;
const u32 memAddr;
const u32 memSize;
const vm::ptr<CellAdecCbMsg> cbFunc;
const u32 cbArg;
u32 memBias;
AdecTask task;
u64 last_pts, first_pts;
u32 ch_out;
u32 ch_cfg;
u32 frame_size;
u32 sample_rate;
bool use_ats_headers;
AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
: ppu_thread("HLE Audio Decoder")
, type(type)
, memAddr(addr)
, memSize(size)
, memBias(0)
, cbFunc(func)
, cbArg(arg)
, is_closed(false)
, is_finished(false)
, just_started(false)
, just_finished(false)
, codec(nullptr)
, input_format(nullptr)
, ctx(nullptr)
, fmt(nullptr)
{
av_register_all();
avcodec_register_all();
switch (type)
{
case CELL_ADEC_TYPE_ATRACX:
case CELL_ADEC_TYPE_ATRACX_2CH:
case CELL_ADEC_TYPE_ATRACX_6CH:
case CELL_ADEC_TYPE_ATRACX_8CH:
{
codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
input_format = av_find_input_format("oma");
break;
}
case CELL_ADEC_TYPE_MP3:
{
codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
input_format = av_find_input_format("mp3");
break;
}
default:
{
fmt::throw_exception("Unknown type (0x%x)" HERE, type);
}
}
if (!codec)
{
fmt::throw_exception("avcodec_find_decoder() failed" HERE);
}
if (!input_format)
{
fmt::throw_exception("av_find_input_format() failed" HERE);
}
fmt = avformat_alloc_context();
if (!fmt)
{
fmt::throw_exception("avformat_alloc_context() failed" HERE);
}
io_buf = (u8*)av_malloc(4096);
fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL);
if (!fmt->pb)
{
fmt::throw_exception("avio_alloc_context() failed" HERE);
}
}
}
~AudioDecoder()
{
// TODO: check finalization
AdecFrame af;
while (frames.try_pop(af))
{
av_frame_unref(af.data);
av_frame_free(&af.data);
}
if (ctx)
{
avcodec_close(ctx);
avformat_close_input(&fmt);
}
if (fmt)
{
if (io_buf)
{
av_free(io_buf);
}
if (fmt->pb) av_free(fmt->pb);
avformat_free_context(fmt);
}
}
virtual void cpu_task() override
{
while (true)
{
if (Emu.IsStopped() || is_closed)
{
break;
}
if (!job.pop(task, &is_closed))
{
break;
}
switch (task.type)
{
case adecStartSeq:
{
// TODO: reset data
cellAdec.warning("adecStartSeq:");
reader.addr = 0;
reader.size = 0;
reader.init = false;
reader.has_ats = false;
just_started = true;
if (adecIsAtracX(type))
{
ch_cfg = task.at3p.channel_config;
ch_out = task.at3p.channels;
frame_size = task.at3p.frame_size;
sample_rate = task.at3p.sample_rate;
use_ats_headers = task.at3p.ats_header == 1;
}
break;
}
case adecEndSeq:
{
// TODO: finalize
cellAdec.warning("adecEndSeq:");
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, cbArg);
just_finished = true;
break;
}
case adecDecodeAu:
{
int err = 0;
reader.addr = task.au.addr;
reader.size = task.au.size;
reader.has_ats = use_ats_headers;
//LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);
if (just_started)
{
first_pts = task.au.pts;
last_pts = task.au.pts;
if (adecIsAtracX(type)) last_pts -= 0x10000; // hack
}
struct AVPacketHolder : AVPacket
{
AVPacketHolder(u32 size)
{
av_init_packet(this);
if (size)
{
data = (u8*)av_calloc(1, size + FF_INPUT_BUFFER_PADDING_SIZE);
this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
}
else
{
data = NULL;
size = 0;
}
}
~AVPacketHolder()
{
av_free(data);
}
} au(0);
if (just_started && just_finished)
{
avcodec_flush_buffers(ctx);
reader.init = true; // wrong
just_finished = false;
just_started = false;
}
else if (just_started) // deferred initialization
{
AVDictionary* opts = nullptr;
av_dict_set(&opts, "probesize", "96", 0);
err = avformat_open_input(&fmt, NULL, input_format, &opts);
if (err || opts)
{
fmt::throw_exception("avformat_open_input() failed (err=0x%x, opts=%d)" HERE, err, opts ? 1 : 0);
}
//err = avformat_find_stream_info(fmt, NULL);
//if (err || !fmt->nb_streams)
//{
// ADEC_ERROR("adecDecodeAu: avformat_find_stream_info() failed (err=0x%x, nb_streams=%d)", err, fmt->nb_streams);
//}
if (!avformat_new_stream(fmt, codec))
{
fmt::throw_exception("avformat_new_stream() failed" HERE);
}
ctx = fmt->streams[0]->codec; // TODO: check data
opts = nullptr;
av_dict_set(&opts, "refcounted_frames", "1", 0);
{
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
// not multithread-safe (???)
err = avcodec_open2(ctx, codec, &opts);
}
if (err || opts)
{
fmt::throw_exception("avcodec_open2() failed (err=0x%x, opts=%d)" HERE, err, opts ? 1 : 0);
}
just_started = false;
}
bool last_frame = false;
while (true)
{
if (Emu.IsStopped() || is_closed)
{
if (Emu.IsStopped()) cellAdec.warning("adecDecodeAu: aborted");
break;
}
last_frame = av_read_frame(fmt, &au) < 0;
if (last_frame)
{
//break;
av_free(au.data);
au.data = NULL;
au.size = 0;
}
struct AdecFrameHolder : AdecFrame
{
AdecFrameHolder()
{
data = av_frame_alloc();
}
~AdecFrameHolder()
{
if (data)
{
av_frame_unref(data);
av_frame_free(&data);
}
}
} frame;
if (!frame.data)
{
fmt::throw_exception("av_frame_alloc() failed" HERE);
}
int got_frame = 0;
int decode = avcodec_decode_audio4(ctx, frame.data, &got_frame, &au);
if (decode <= 0)
{
if (decode < 0)
{
cellAdec.error("adecDecodeAu: AU decoding error(0x%x)", decode);
}
if (!got_frame && reader.size == 0) break;
}
if (got_frame)
{
//u64 ts = av_frame_get_best_effort_timestamp(frame.data);
//if (ts != AV_NOPTS_VALUE)
//{
// frame.pts = ts/* - first_pts*/;
// last_pts = frame.pts;
//}
last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate;
frame.pts = last_pts;
s32 nbps = av_get_bytes_per_sample((AVSampleFormat)frame.data->format);
switch (frame.data->format)
{
case AV_SAMPLE_FMT_FLTP: break;
case AV_SAMPLE_FMT_S16P: break;
default:
{
fmt::throw_exception("Unsupported frame format(%d)" HERE, frame.data->format);
}
}
frame.auAddr = task.au.addr;
frame.auSize = task.au.size;
frame.userdata = task.au.userdata;
frame.size = frame.data->nb_samples * frame.data->channels * nbps;
//LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps);
if (frames.push(frame, &is_closed))
{
frame.data = nullptr; // to prevent destruction
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, cbArg);
}
}
}
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, cbArg);
break;
}
case adecClose:
{
break;
}
default:
{
fmt::throw_exception("Unknown task(%d)" HERE, (u32)task.type);
}
}
}
is_finished = true;
}
};
int adecRead(void* opaque, u8* buf, int buf_size)
{
@@ -162,16 +454,16 @@ next:
buf_size = adec.reader.size;
}
break;
case adecDecodeAu:
{
std::memcpy(buf, vm::base(adec.reader.addr), adec.reader.size);
buf += adec.reader.size;
buf_size -= adec.reader.size;
res += adec.reader.size;
adec.cbFunc(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
adec.cbFunc(adec, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
adec.job.pop(adec.task);
@@ -181,10 +473,10 @@ next:
//LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts);
}
break;
default:
{
cellAdec.error("adecRawRead(): unknown task (%d)", task.type);
cellAdec.error("adecRawRead(): unknown task (%d)", (u32)task.type);
Emu.Pause();
return -1;
}
@@ -212,267 +504,6 @@ next:
}
}
void adecOpen(u32 adec_id) // TODO: call from the constructor
{
const auto sptr = idm::get<AudioDecoder>(adec_id);
AudioDecoder& adec = *sptr;
adec.id = adec_id;
adec.adecCb = idm::make_ptr<PPUThread>(fmt::format("Demuxer[0x%x] Thread", adec_id));
adec.adecCb->prio = 1001;
adec.adecCb->stack_size = 0x10000;
adec.adecCb->custom_task = [sptr](PPUThread& CPU)
{
AudioDecoder& adec = *sptr;
AdecTask& task = adec.task;
while (true)
{
if (Emu.IsStopped() || adec.is_closed)
{
break;
}
if (!adec.job.pop(task, &adec.is_closed))
{
break;
}
switch (task.type)
{
case adecStartSeq:
{
// TODO: reset data
cellAdec.warning("adecStartSeq:");
adec.reader.addr = 0;
adec.reader.size = 0;
adec.reader.init = false;
adec.reader.has_ats = false;
adec.just_started = true;
if (adecIsAtracX(adec.type))
{
adec.ch_cfg = task.at3p.channel_config;
adec.ch_out = task.at3p.channels;
adec.frame_size = task.at3p.frame_size;
adec.sample_rate = task.at3p.sample_rate;
adec.use_ats_headers = task.at3p.ats_header == 1;
}
break;
}
case adecEndSeq:
{
// TODO: finalize
cellAdec.warning("adecEndSeq:");
adec.cbFunc(CPU, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
adec.just_finished = true;
break;
}
case adecDecodeAu:
{
int err = 0;
adec.reader.addr = task.au.addr;
adec.reader.size = task.au.size;
adec.reader.has_ats = adec.use_ats_headers;
//LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);
if (adec.just_started)
{
adec.first_pts = task.au.pts;
adec.last_pts = task.au.pts;
if (adecIsAtracX(adec.type)) adec.last_pts -= 0x10000; // hack
}
struct AVPacketHolder : AVPacket
{
AVPacketHolder(u32 size)
{
av_init_packet(this);
if (size)
{
data = (u8*)av_calloc(1, size + FF_INPUT_BUFFER_PADDING_SIZE);
this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
}
else
{
data = NULL;
size = 0;
}
}
~AVPacketHolder()
{
av_free(data);
}
} au(0);
if (adec.just_started && adec.just_finished)
{
avcodec_flush_buffers(adec.ctx);
adec.reader.init = true; // wrong
adec.just_finished = false;
adec.just_started = false;
}
else if (adec.just_started) // deferred initialization
{
AVDictionary* opts = nullptr;
av_dict_set(&opts, "probesize", "96", 0);
err = avformat_open_input(&adec.fmt, NULL, adec.input_format, &opts);
if (err || opts)
{
throw EXCEPTION("avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
}
//err = avformat_find_stream_info(adec.fmt, NULL);
//if (err || !adec.fmt->nb_streams)
//{
// ADEC_ERROR("adecDecodeAu: avformat_find_stream_info() failed (err=0x%x, nb_streams=%d)", err, adec.fmt->nb_streams);
//}
if (!avformat_new_stream(adec.fmt, adec.codec))
{
throw EXCEPTION("avformat_new_stream() failed");
}
adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data
opts = nullptr;
av_dict_set(&opts, "refcounted_frames", "1", 0);
{
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
// not multithread-safe (???)
err = avcodec_open2(adec.ctx, adec.codec, &opts);
}
if (err || opts)
{
throw EXCEPTION("avcodec_open2() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
}
adec.just_started = false;
}
bool last_frame = false;
while (true)
{
if (Emu.IsStopped() || adec.is_closed)
{
if (Emu.IsStopped()) cellAdec.warning("adecDecodeAu: aborted");
break;
}
last_frame = av_read_frame(adec.fmt, &au) < 0;
if (last_frame)
{
//break;
av_free(au.data);
au.data = NULL;
au.size = 0;
}
struct AdecFrameHolder : AdecFrame
{
AdecFrameHolder()
{
data = av_frame_alloc();
}
~AdecFrameHolder()
{
if (data)
{
av_frame_unref(data);
av_frame_free(&data);
}
}
} frame;
if (!frame.data)
{
throw EXCEPTION("av_frame_alloc() failed");
}
int got_frame = 0;
int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au);
if (decode <= 0)
{
if (decode < 0)
{
cellAdec.error("adecDecodeAu: AU decoding error(0x%x)", decode);
}
if (!got_frame && adec.reader.size == 0) break;
}
if (got_frame)
{
//u64 ts = av_frame_get_best_effort_timestamp(frame.data);
//if (ts != AV_NOPTS_VALUE)
//{
// frame.pts = ts/* - adec.first_pts*/;
// adec.last_pts = frame.pts;
//}
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate;
frame.pts = adec.last_pts;
s32 nbps = av_get_bytes_per_sample((AVSampleFormat)frame.data->format);
switch (frame.data->format)
{
case AV_SAMPLE_FMT_FLTP: break;
case AV_SAMPLE_FMT_S16P: break;
default:
{
throw EXCEPTION("Unsupported frame format(%d)", frame.data->format);
}
}
frame.auAddr = task.au.addr;
frame.auSize = task.au.size;
frame.userdata = task.au.userdata;
frame.size = frame.data->nb_samples * frame.data->channels * nbps;
//LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps);
if (adec.frames.push(frame, &adec.is_closed))
{
frame.data = nullptr; // to prevent destruction
adec.cbFunc(CPU, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
}
}
}
adec.cbFunc(CPU, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
break;
}
case adecClose:
{
break;
}
default:
{
throw EXCEPTION("Unknown task(%d)", task.type);
}
}
}
adec.is_finished = true;
};
adec.adecCb->cpu_init();
adec.adecCb->state -= cpu_state::stop;
(*adec.adecCb)->lock_notify();
}
bool adecCheckType(s32 type)
{
switch (type)
@@ -527,7 +558,11 @@ s32 cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::
return CELL_ADEC_ERROR_ARG;
}
adecOpen(*handle = idm::make<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
*handle = adec->id;
adec->run();
return CELL_OK;
}
@@ -541,7 +576,11 @@ s32 cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res,
return CELL_ADEC_ERROR_ARG;
}
adecOpen(*handle = idm::make<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
*handle = adec->id;
adec->run();
return CELL_OK;
}
@@ -574,8 +613,7 @@ s32 cellAdecClose(u32 handle)
std::this_thread::sleep_for(1ms); // hack
}
idm::remove<PPUThread>(adec->adecCb->id);
idm::remove<AudioDecoder>(handle);
idm::remove<ppu_thread>(handle);
return CELL_OK;
}
@@ -779,7 +817,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
}
else
{
throw EXCEPTION("Unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format);
fmt::throw_exception("Unsupported frame format (channels=%d, format=%d)" HERE, frame->channels, frame->format);
}
}
+1 -56
View File
@@ -1043,7 +1043,7 @@ struct AdecTask
struct AdecFrame
{
AVFrame* data;
struct AVFrame* data;
u64 pts;
u64 userdata;
u32 auAddr;
@@ -1096,58 +1096,3 @@ struct OMAHeader // OMA Header
};
CHECK_SIZE(OMAHeader, 96);
class AudioDecoder
{
public:
squeue_t<AdecTask> job;
u32 id;
volatile bool is_closed;
volatile bool is_finished;
bool just_started;
bool just_finished;
AVCodec* codec;
AVInputFormat* input_format;
AVCodecContext* ctx;
AVFormatContext* fmt;
u8* io_buf;
struct AudioReader
{
u32 addr;
u32 size;
bool init;
bool has_ats;
AudioReader()
: init(false)
{
}
} reader;
squeue_t<AdecFrame> frames;
const s32 type;
const u32 memAddr;
const u32 memSize;
const vm::ptr<CellAdecCbMsg> cbFunc;
const u32 cbArg;
u32 memBias;
AdecTask task;
u64 last_pts, first_pts;
u32 ch_out;
u32 ch_cfg;
u32 frame_size;
u32 sample_rate;
bool use_ats_headers;
std::shared_ptr<PPUThread> adecCb;
AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg);
~AudioDecoder();
};

Some files were not shown because too many files have changed in this diff Show More