Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3352e235b6 | |||
| 816169fe9e |
@@ -1,33 +0,0 @@
|
||||
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
|
||||
@@ -1,7 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{h,cpp,hpp}]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
+1
-7
@@ -12,7 +12,7 @@
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
url = https://github.com/llvm-mirror/llvm
|
||||
branch = release_39
|
||||
branch = release_36
|
||||
[submodule "rsx_program_decompiler"]
|
||||
path = rsx_program_decompiler
|
||||
url = https://github.com/RPCS3/rsx_program_decompiler
|
||||
@@ -35,9 +35,3 @@
|
||||
[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
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"userBlacklist": ["AlexAltea", "tambry", "DHrpcs3"]
|
||||
"userBlacklist": ["AlexAltea", "tambry"]
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 Utilities/yaml-cpp 3rdparty/cereal
|
||||
- git submodule update --init rsx_program_decompiler asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp
|
||||
- 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
-1
Submodule 3rdparty/cereal deleted from 42a45b6e15
Vendored
+4571
-1156
File diff suppressed because it is too large
Load Diff
Vendored
+3138
-777
File diff suppressed because it is too large
Load Diff
Vendored
+651
-46
@@ -33,14 +33,20 @@ typedef interface ID2D1Device1 ID2D1Device1;
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the extent to which D2D will throttle work sent to the GPU.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_RENDERING_PRIORITY
|
||||
//
|
||||
// Synopsis:
|
||||
// Specifies the extent to which D2D will throttle work sent to the GPU.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
@@ -48,25 +54,32 @@ typedef enum D2D1_RENDERING_PRIORITY
|
||||
#ifndef D2D_USE_C_DEFINITIONS
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a device- and transform-dependent representation of a filled or
|
||||
/// stroked geometry.
|
||||
/// </summary>
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1GeometryRealization
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
interface DX_DECLARE_INTERFACE("a16907d7-bc02-4801-99e8-8cf7f485f774") ID2D1GeometryRealization : public ID2D1Resource
|
||||
{
|
||||
}; // interface ID2D1GeometryRealization
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enables creation and drawing of geometry realization objects.
|
||||
/// </summary>
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1DeviceContext1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1DeviceContext1 : public ID2D1DeviceContext
|
||||
{
|
||||
|
||||
STDMETHOD(CreateFilledGeometryRealization)(
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
_COM_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateStrokedGeometryRealization)(
|
||||
@@ -74,7 +87,7 @@ interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1Devi
|
||||
FLOAT flatteningTolerance,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle,
|
||||
_COM_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, DrawGeometryRealization)(
|
||||
@@ -84,69 +97,82 @@ interface DX_DECLARE_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") ID2D1Devi
|
||||
}; // interface ID2D1DeviceContext1
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a resource domain whose objects and device contexts can be used
|
||||
/// together.
|
||||
/// </summary>
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1Device1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
interface DX_DECLARE_INTERFACE("d21768e1-23a4-4823-a14b-7c3eba85d658") ID2D1Device1 : public ID2D1Device
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the rendering priority currently set on the device.
|
||||
/// </summary>
|
||||
|
||||
//
|
||||
// Retrieves the rendering priority currently set on the device.
|
||||
//
|
||||
STDMETHOD_(D2D1_RENDERING_PRIORITY, GetRenderingPriority)(
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the rendering priority of the device.
|
||||
/// </summary>
|
||||
|
||||
//
|
||||
// Sets the rendering priority of the device.
|
||||
//
|
||||
STDMETHOD_(void, SetRenderingPriority)(
|
||||
D2D1_RENDERING_PRIORITY renderingPriority
|
||||
) PURE;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new device context with no initially assigned target.
|
||||
/// </summary>
|
||||
|
||||
//
|
||||
// Creates a new device context with no initially assigned target.
|
||||
//
|
||||
STDMETHOD(CreateDeviceContext)(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS options,
|
||||
_COM_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
) PURE;
|
||||
|
||||
using ID2D1Device::CreateDeviceContext;
|
||||
}; // interface ID2D1Device1
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates Direct2D resources. This interface also enables the creation of
|
||||
/// ID2D1Device1 objects.
|
||||
/// </summary>
|
||||
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Interface:
|
||||
// ID2D1Factory2
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
interface DX_DECLARE_INTERFACE("94f81a73-9212-4376-9c58-b16a3a0d3992") ID2D1Factory2 : public ID2D1Factory1
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This creates a new Direct2D device from the given IDXGIDevice.
|
||||
/// </summary>
|
||||
|
||||
//
|
||||
// This creates a new Direct2D device from the given IDXGIDevice.
|
||||
//
|
||||
STDMETHOD(CreateDevice)(
|
||||
_In_ IDXGIDevice *dxgiDevice,
|
||||
_COM_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
) PURE;
|
||||
|
||||
using ID2D1Factory1::CreateDevice;
|
||||
}; // interface ID2D1Factory2
|
||||
|
||||
|
||||
/// <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:
|
||||
// ID2D1CommandSink1
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
interface DX_DECLARE_INTERFACE("9eb767fd-4269-4467-b8c2-eb30cb305743") ID2D1CommandSink1 : public ID2D1CommandSink
|
||||
{
|
||||
|
||||
/// <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>
|
||||
|
||||
//
|
||||
// This method is called if primitiveBlend value was added after Windows 8.
|
||||
// SetPrimitiveBlend method is used for Win8 values (_SOURCE_OVER and _COPY).
|
||||
//
|
||||
STDMETHOD(SetPrimitiveBlend1)(
|
||||
D2D1_PRIMITIVE_BLEND primitiveBlend
|
||||
) PURE;
|
||||
@@ -169,14 +195,593 @@ EXTERN_C CONST IID IID_ID2D1CommandSink1;
|
||||
|
||||
typedef interface ID2D1GeometryRealization ID2D1GeometryRealization;
|
||||
|
||||
typedef struct ID2D1GeometryRealizationVtbl
|
||||
{
|
||||
|
||||
ID2D1ResourceVtbl Base;
|
||||
|
||||
} ID2D1GeometryRealizationVtbl;
|
||||
|
||||
interface ID2D1GeometryRealization
|
||||
{
|
||||
CONST struct ID2D1GeometryRealizationVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1GeometryRealization_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1GeometryRealization_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1GeometryRealization_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1GeometryRealization_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
typedef interface ID2D1DeviceContext1 ID2D1DeviceContext1;
|
||||
|
||||
typedef struct ID2D1DeviceContext1Vtbl
|
||||
{
|
||||
|
||||
ID2D1DeviceContextVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(CreateFilledGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateStrokedGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1Geometry *geometry,
|
||||
FLOAT flatteningTolerance,
|
||||
FLOAT strokeWidth,
|
||||
_In_opt_ ID2D1StrokeStyle *strokeStyle,
|
||||
_Outptr_ ID2D1GeometryRealization **geometryRealization
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, DrawGeometryRealization)(
|
||||
ID2D1DeviceContext1 *This,
|
||||
_In_ ID2D1GeometryRealization *geometryRealization,
|
||||
_In_ ID2D1Brush *brush
|
||||
) PURE;
|
||||
} ID2D1DeviceContext1Vtbl;
|
||||
|
||||
interface ID2D1DeviceContext1
|
||||
{
|
||||
CONST struct ID2D1DeviceContext1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1DeviceContext1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1DeviceContext1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.Base.Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateSharedBitmap(This, riid, data, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.Base.CreateSharedBitmap((ID2D1RenderTarget *)This, riid, data, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateSolidColorBrush(This, color, brushProperties, solidColorBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateSolidColorBrush((ID2D1RenderTarget *)This, color, brushProperties, solidColorBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateLinearGradientBrush(This, linearGradientBrushProperties, brushProperties, gradientStopCollection, linearGradientBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateLinearGradientBrush((ID2D1RenderTarget *)This, linearGradientBrushProperties, brushProperties, gradientStopCollection, linearGradientBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateRadialGradientBrush(This, radialGradientBrushProperties, brushProperties, gradientStopCollection, radialGradientBrush) \
|
||||
((This)->lpVtbl->Base.Base.CreateRadialGradientBrush((ID2D1RenderTarget *)This, radialGradientBrushProperties, brushProperties, gradientStopCollection, radialGradientBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateCompatibleRenderTarget(This, desiredSize, desiredPixelSize, desiredFormat, options, bitmapRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateCompatibleRenderTarget((ID2D1RenderTarget *)This, desiredSize, desiredPixelSize, desiredFormat, options, bitmapRenderTarget))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateLayer(This, size, layer) \
|
||||
((This)->lpVtbl->Base.Base.CreateLayer((ID2D1RenderTarget *)This, size, layer))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateMesh(This, mesh) \
|
||||
((This)->lpVtbl->Base.Base.CreateMesh((ID2D1RenderTarget *)This, mesh))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawLine(This, point0, point1, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawLine((ID2D1RenderTarget *)This, point0, point1, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawRectangle(This, rect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawRectangle((ID2D1RenderTarget *)This, rect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillRectangle(This, rect, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillRectangle((ID2D1RenderTarget *)This, rect, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawRoundedRectangle(This, roundedRect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawRoundedRectangle((ID2D1RenderTarget *)This, roundedRect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillRoundedRectangle(This, roundedRect, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillRoundedRectangle((ID2D1RenderTarget *)This, roundedRect, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawEllipse(This, ellipse, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawEllipse((ID2D1RenderTarget *)This, ellipse, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillEllipse(This, ellipse, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillEllipse((ID2D1RenderTarget *)This, ellipse, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGeometry(This, geometry, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.Base.DrawGeometry((ID2D1RenderTarget *)This, geometry, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1DeviceContext1_FillGeometry(This, geometry, brush, opacityBrush) \
|
||||
((This)->lpVtbl->Base.Base.FillGeometry((ID2D1RenderTarget *)This, geometry, brush, opacityBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_FillMesh(This, mesh, brush) \
|
||||
((This)->lpVtbl->Base.Base.FillMesh((ID2D1RenderTarget *)This, mesh, brush))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawText(This, string, stringLength, textFormat, layoutRect, defaultForegroundBrush, options, measuringMode) \
|
||||
((This)->lpVtbl->Base.Base.DrawText((ID2D1RenderTarget *)This, string, stringLength, textFormat, layoutRect, defaultForegroundBrush, options, measuringMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawTextLayout(This, origin, textLayout, defaultForegroundBrush, options) \
|
||||
((This)->lpVtbl->Base.Base.DrawTextLayout((ID2D1RenderTarget *)This, origin, textLayout, defaultForegroundBrush, options))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.Base.SetTransform((ID2D1RenderTarget *)This, transform))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.Base.GetTransform((ID2D1RenderTarget *)This, transform))
|
||||
|
||||
#define ID2D1DeviceContext1_SetAntialiasMode(This, antialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.SetAntialiasMode((ID2D1RenderTarget *)This, antialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetAntialiasMode(This) \
|
||||
((This)->lpVtbl->Base.Base.GetAntialiasMode((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTextAntialiasMode(This, textAntialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.SetTextAntialiasMode((ID2D1RenderTarget *)This, textAntialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTextAntialiasMode(This) \
|
||||
((This)->lpVtbl->Base.Base.GetTextAntialiasMode((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.Base.SetTextRenderingParams((ID2D1RenderTarget *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.Base.GetTextRenderingParams((ID2D1RenderTarget *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.SetTags((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.GetTags((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_PopLayer(This) \
|
||||
((This)->lpVtbl->Base.Base.PopLayer((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Flush(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.Flush((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_SaveDrawingState(This, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.Base.SaveDrawingState((ID2D1RenderTarget *)This, drawingStateBlock))
|
||||
|
||||
#define ID2D1DeviceContext1_RestoreDrawingState(This, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.Base.RestoreDrawingState((ID2D1RenderTarget *)This, drawingStateBlock))
|
||||
|
||||
#define ID2D1DeviceContext1_PushAxisAlignedClip(This, clipRect, antialiasMode) \
|
||||
((This)->lpVtbl->Base.Base.PushAxisAlignedClip((ID2D1RenderTarget *)This, clipRect, antialiasMode))
|
||||
|
||||
#define ID2D1DeviceContext1_PopAxisAlignedClip(This) \
|
||||
((This)->lpVtbl->Base.Base.PopAxisAlignedClip((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_Clear(This, clearColor) \
|
||||
((This)->lpVtbl->Base.Base.Clear((ID2D1RenderTarget *)This, clearColor))
|
||||
|
||||
#define ID2D1DeviceContext1_BeginDraw(This) \
|
||||
((This)->lpVtbl->Base.Base.BeginDraw((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_EndDraw(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.Base.EndDraw((ID2D1RenderTarget *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPixelFormat(This) \
|
||||
((This)->lpVtbl->Base.Base.GetPixelFormat((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.SetDpi((ID2D1RenderTarget *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1DeviceContext1_GetDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.GetDpi((ID2D1RenderTarget *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1DeviceContext1_GetSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPixelSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetPixelSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_GetMaximumBitmapSize(This) \
|
||||
((This)->lpVtbl->Base.Base.GetMaximumBitmapSize((ID2D1RenderTarget *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_IsSupported(This, renderTargetProperties) \
|
||||
((This)->lpVtbl->Base.Base.IsSupported((ID2D1RenderTarget *)This, renderTargetProperties))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmap(This, size, sourceData, pitch, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmap((ID2D1DeviceContext *)This, size, sourceData, pitch, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapFromWicBitmap(This, wicBitmapSource, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmapFromWicBitmap((ID2D1DeviceContext *)This, wicBitmapSource, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContext(This, space, profile, profileSize, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContext((ID2D1DeviceContext *)This, space, profile, profileSize, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContextFromFilename(This, filename, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContextFromFilename((ID2D1DeviceContext *)This, filename, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateColorContextFromWicColorContext(This, wicColorContext, colorContext) \
|
||||
((This)->lpVtbl->Base.CreateColorContextFromWicColorContext((ID2D1DeviceContext *)This, wicColorContext, colorContext))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapFromDxgiSurface(This, surface, bitmapProperties, bitmap) \
|
||||
((This)->lpVtbl->Base.CreateBitmapFromDxgiSurface((ID2D1DeviceContext *)This, surface, bitmapProperties, bitmap))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateEffect(This, effectId, effect) \
|
||||
((This)->lpVtbl->Base.CreateEffect((ID2D1DeviceContext *)This, effectId, effect))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateGradientStopCollection(This, straightAlphaGradientStops, straightAlphaGradientStopsCount, preInterpolationSpace, postInterpolationSpace, bufferPrecision, extendMode, colorInterpolationMode, gradientStopCollection1) \
|
||||
((This)->lpVtbl->Base.CreateGradientStopCollection((ID2D1DeviceContext *)This, straightAlphaGradientStops, straightAlphaGradientStopsCount, preInterpolationSpace, postInterpolationSpace, bufferPrecision, extendMode, colorInterpolationMode, gradientStopCollection1))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateImageBrush(This, image, imageBrushProperties, brushProperties, imageBrush) \
|
||||
((This)->lpVtbl->Base.CreateImageBrush((ID2D1DeviceContext *)This, image, imageBrushProperties, brushProperties, imageBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateBitmapBrush(This, bitmap, bitmapBrushProperties, brushProperties, bitmapBrush) \
|
||||
((This)->lpVtbl->Base.CreateBitmapBrush((ID2D1DeviceContext *)This, bitmap, bitmapBrushProperties, brushProperties, bitmapBrush))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateCommandList(This, commandList) \
|
||||
((This)->lpVtbl->Base.CreateCommandList((ID2D1DeviceContext *)This, commandList))
|
||||
|
||||
#define ID2D1DeviceContext1_IsDxgiFormatSupported(This, format) \
|
||||
((This)->lpVtbl->Base.IsDxgiFormatSupported((ID2D1DeviceContext *)This, format))
|
||||
|
||||
#define ID2D1DeviceContext1_IsBufferPrecisionSupported(This, bufferPrecision) \
|
||||
((This)->lpVtbl->Base.IsBufferPrecisionSupported((ID2D1DeviceContext *)This, bufferPrecision))
|
||||
|
||||
#define ID2D1DeviceContext1_GetImageLocalBounds(This, image, localBounds) \
|
||||
((This)->lpVtbl->Base.GetImageLocalBounds((ID2D1DeviceContext *)This, image, localBounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetImageWorldBounds(This, image, worldBounds) \
|
||||
((This)->lpVtbl->Base.GetImageWorldBounds((ID2D1DeviceContext *)This, image, worldBounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetGlyphRunWorldBounds(This, baselineOrigin, glyphRun, measuringMode, bounds) \
|
||||
((This)->lpVtbl->Base.GetGlyphRunWorldBounds((ID2D1DeviceContext *)This, baselineOrigin, glyphRun, measuringMode, bounds))
|
||||
|
||||
#define ID2D1DeviceContext1_GetDevice(This, device) \
|
||||
((This)->lpVtbl->Base.GetDevice((ID2D1DeviceContext *)This, device))
|
||||
|
||||
#define ID2D1DeviceContext1_SetTarget(This, image) \
|
||||
((This)->lpVtbl->Base.SetTarget((ID2D1DeviceContext *)This, image))
|
||||
|
||||
#define ID2D1DeviceContext1_GetTarget(This, image) \
|
||||
((This)->lpVtbl->Base.GetTarget((ID2D1DeviceContext *)This, image))
|
||||
|
||||
#define ID2D1DeviceContext1_SetRenderingControls(This, renderingControls) \
|
||||
((This)->lpVtbl->Base.SetRenderingControls((ID2D1DeviceContext *)This, renderingControls))
|
||||
|
||||
#define ID2D1DeviceContext1_GetRenderingControls(This, renderingControls) \
|
||||
((This)->lpVtbl->Base.GetRenderingControls((ID2D1DeviceContext *)This, renderingControls))
|
||||
|
||||
#define ID2D1DeviceContext1_SetPrimitiveBlend(This, primitiveBlend) \
|
||||
((This)->lpVtbl->Base.SetPrimitiveBlend((ID2D1DeviceContext *)This, primitiveBlend))
|
||||
|
||||
#define ID2D1DeviceContext1_GetPrimitiveBlend(This) \
|
||||
((This)->lpVtbl->Base.GetPrimitiveBlend((ID2D1DeviceContext *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_SetUnitMode(This, unitMode) \
|
||||
((This)->lpVtbl->Base.SetUnitMode((ID2D1DeviceContext *)This, unitMode))
|
||||
|
||||
#define ID2D1DeviceContext1_GetUnitMode(This) \
|
||||
((This)->lpVtbl->Base.GetUnitMode((ID2D1DeviceContext *)This))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGlyphRun(This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode) \
|
||||
((This)->lpVtbl->Base.DrawGlyphRun((ID2D1DeviceContext *)This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawImage(This, image, targetOffset, imageRectangle, interpolationMode, compositeMode) \
|
||||
((This)->lpVtbl->Base.DrawImage((ID2D1DeviceContext *)This, image, targetOffset, imageRectangle, interpolationMode, compositeMode))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGdiMetafile(This, gdiMetafile, targetOffset) \
|
||||
((This)->lpVtbl->Base.DrawGdiMetafile((ID2D1DeviceContext *)This, gdiMetafile, targetOffset))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawBitmap(This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform) \
|
||||
((This)->lpVtbl->Base.DrawBitmap((ID2D1DeviceContext *)This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform))
|
||||
|
||||
#define ID2D1DeviceContext1_PushLayer(This, layerParameters, layer) \
|
||||
((This)->lpVtbl->Base.PushLayer((ID2D1DeviceContext *)This, layerParameters, layer))
|
||||
|
||||
#define ID2D1DeviceContext1_InvalidateEffectInputRectangle(This, effect, input, inputRectangle) \
|
||||
((This)->lpVtbl->Base.InvalidateEffectInputRectangle((ID2D1DeviceContext *)This, effect, input, inputRectangle))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectInvalidRectangleCount(This, effect, rectangleCount) \
|
||||
((This)->lpVtbl->Base.GetEffectInvalidRectangleCount((ID2D1DeviceContext *)This, effect, rectangleCount))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectInvalidRectangles(This, effect, rectangles, rectanglesCount) \
|
||||
((This)->lpVtbl->Base.GetEffectInvalidRectangles((ID2D1DeviceContext *)This, effect, rectangles, rectanglesCount))
|
||||
|
||||
#define ID2D1DeviceContext1_GetEffectRequiredInputRectangles(This, renderEffect, renderImageRectangle, inputDescriptions, requiredInputRects, inputCount) \
|
||||
((This)->lpVtbl->Base.GetEffectRequiredInputRectangles((ID2D1DeviceContext *)This, renderEffect, renderImageRectangle, inputDescriptions, requiredInputRects, inputCount))
|
||||
|
||||
#define ID2D1DeviceContext1_FillOpacityMask(This, opacityMask, brush, destinationRectangle, sourceRectangle) \
|
||||
((This)->lpVtbl->Base.FillOpacityMask((ID2D1DeviceContext *)This, opacityMask, brush, destinationRectangle, sourceRectangle))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateFilledGeometryRealization(This, geometry, flatteningTolerance, geometryRealization) \
|
||||
((This)->lpVtbl->CreateFilledGeometryRealization(This, geometry, flatteningTolerance, geometryRealization))
|
||||
|
||||
#define ID2D1DeviceContext1_CreateStrokedGeometryRealization(This, geometry, flatteningTolerance, strokeWidth, strokeStyle, geometryRealization) \
|
||||
((This)->lpVtbl->CreateStrokedGeometryRealization(This, geometry, flatteningTolerance, strokeWidth, strokeStyle, geometryRealization))
|
||||
|
||||
#define ID2D1DeviceContext1_DrawGeometryRealization(This, geometryRealization, brush) \
|
||||
((This)->lpVtbl->DrawGeometryRealization(This, geometryRealization, brush))
|
||||
|
||||
typedef interface ID2D1Device1 ID2D1Device1;
|
||||
|
||||
typedef struct ID2D1Device1Vtbl
|
||||
{
|
||||
|
||||
ID2D1DeviceVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD_(D2D1_RENDERING_PRIORITY, GetRenderingPriority)(
|
||||
ID2D1Device1 *This
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(void, SetRenderingPriority)(
|
||||
ID2D1Device1 *This,
|
||||
D2D1_RENDERING_PRIORITY renderingPriority
|
||||
) PURE;
|
||||
|
||||
STDMETHOD(CreateDeviceContext)(
|
||||
ID2D1Device1 *This,
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS options,
|
||||
_Outptr_ ID2D1DeviceContext1 **deviceContext1
|
||||
) PURE;
|
||||
} ID2D1Device1Vtbl;
|
||||
|
||||
interface ID2D1Device1
|
||||
{
|
||||
CONST struct ID2D1Device1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1Device1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1Device1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1Device1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1Device1_GetFactory(This, factory) \
|
||||
((This)->lpVtbl->Base.Base.GetFactory((ID2D1Resource *)This, factory))
|
||||
|
||||
#define ID2D1Device1_CreatePrintControl(This, wicFactory, documentTarget, printControlProperties, printControl) \
|
||||
((This)->lpVtbl->Base.CreatePrintControl((ID2D1Device *)This, wicFactory, documentTarget, printControlProperties, printControl))
|
||||
|
||||
#define ID2D1Device1_SetMaximumTextureMemory(This, maximumInBytes) \
|
||||
((This)->lpVtbl->Base.SetMaximumTextureMemory((ID2D1Device *)This, maximumInBytes))
|
||||
|
||||
#define ID2D1Device1_GetMaximumTextureMemory(This) \
|
||||
((This)->lpVtbl->Base.GetMaximumTextureMemory((ID2D1Device *)This))
|
||||
|
||||
#define ID2D1Device1_ClearResources(This, millisecondsSinceUse) \
|
||||
((This)->lpVtbl->Base.ClearResources((ID2D1Device *)This, millisecondsSinceUse))
|
||||
|
||||
#define ID2D1Device1_GetRenderingPriority(This) \
|
||||
((This)->lpVtbl->GetRenderingPriority(This))
|
||||
|
||||
#define ID2D1Device1_SetRenderingPriority(This, renderingPriority) \
|
||||
((This)->lpVtbl->SetRenderingPriority(This, renderingPriority))
|
||||
|
||||
#define ID2D1Device1_CreateDeviceContext(This, options, deviceContext1) \
|
||||
((This)->lpVtbl->CreateDeviceContext(This, options, deviceContext1))
|
||||
|
||||
typedef interface ID2D1Factory2 ID2D1Factory2;
|
||||
|
||||
typedef struct ID2D1Factory2Vtbl
|
||||
{
|
||||
|
||||
ID2D1Factory1Vtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(CreateDevice)(
|
||||
ID2D1Factory2 *This,
|
||||
_In_ IDXGIDevice *dxgiDevice,
|
||||
_Outptr_ ID2D1Device1 **d2dDevice1
|
||||
) PURE;
|
||||
} ID2D1Factory2Vtbl;
|
||||
|
||||
interface ID2D1Factory2
|
||||
{
|
||||
CONST struct ID2D1Factory2Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1Factory2_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1Factory2_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1Factory2_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1Factory2_ReloadSystemMetrics(This) \
|
||||
((This)->lpVtbl->Base.Base.ReloadSystemMetrics((ID2D1Factory *)This))
|
||||
|
||||
#define ID2D1Factory2_GetDesktopDpi(This, dpiX, dpiY) \
|
||||
((This)->lpVtbl->Base.Base.GetDesktopDpi((ID2D1Factory *)This, dpiX, dpiY))
|
||||
|
||||
#define ID2D1Factory2_CreateRectangleGeometry(This, rectangle, rectangleGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateRectangleGeometry((ID2D1Factory *)This, rectangle, rectangleGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateRoundedRectangleGeometry(This, roundedRectangle, roundedRectangleGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateRoundedRectangleGeometry((ID2D1Factory *)This, roundedRectangle, roundedRectangleGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateEllipseGeometry(This, ellipse, ellipseGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateEllipseGeometry((ID2D1Factory *)This, ellipse, ellipseGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateGeometryGroup(This, fillMode, geometries, geometriesCount, geometryGroup) \
|
||||
((This)->lpVtbl->Base.Base.CreateGeometryGroup((ID2D1Factory *)This, fillMode, geometries, geometriesCount, geometryGroup))
|
||||
|
||||
#define ID2D1Factory2_CreateTransformedGeometry(This, sourceGeometry, transform, transformedGeometry) \
|
||||
((This)->lpVtbl->Base.Base.CreateTransformedGeometry((ID2D1Factory *)This, sourceGeometry, transform, transformedGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateWicBitmapRenderTarget(This, target, renderTargetProperties, renderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateWicBitmapRenderTarget((ID2D1Factory *)This, target, renderTargetProperties, renderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateHwndRenderTarget(This, renderTargetProperties, hwndRenderTargetProperties, hwndRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateHwndRenderTarget((ID2D1Factory *)This, renderTargetProperties, hwndRenderTargetProperties, hwndRenderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateDxgiSurfaceRenderTarget(This, dxgiSurface, renderTargetProperties, renderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateDxgiSurfaceRenderTarget((ID2D1Factory *)This, dxgiSurface, renderTargetProperties, renderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateDCRenderTarget(This, renderTargetProperties, dcRenderTarget) \
|
||||
((This)->lpVtbl->Base.Base.CreateDCRenderTarget((ID2D1Factory *)This, renderTargetProperties, dcRenderTarget))
|
||||
|
||||
#define ID2D1Factory2_CreateStrokeStyle(This, strokeStyleProperties, dashes, dashesCount, strokeStyle) \
|
||||
((This)->lpVtbl->Base.CreateStrokeStyle((ID2D1Factory1 *)This, strokeStyleProperties, dashes, dashesCount, strokeStyle))
|
||||
|
||||
#define ID2D1Factory2_CreatePathGeometry(This, pathGeometry) \
|
||||
((This)->lpVtbl->Base.CreatePathGeometry((ID2D1Factory1 *)This, pathGeometry))
|
||||
|
||||
#define ID2D1Factory2_CreateDrawingStateBlock(This, drawingStateDescription, textRenderingParams, drawingStateBlock) \
|
||||
((This)->lpVtbl->Base.CreateDrawingStateBlock((ID2D1Factory1 *)This, drawingStateDescription, textRenderingParams, drawingStateBlock))
|
||||
|
||||
#define ID2D1Factory2_CreateGdiMetafile(This, metafileStream, metafile) \
|
||||
((This)->lpVtbl->Base.CreateGdiMetafile((ID2D1Factory1 *)This, metafileStream, metafile))
|
||||
|
||||
#define ID2D1Factory2_RegisterEffectFromStream(This, classId, propertyXml, bindings, bindingsCount, effectFactory) \
|
||||
((This)->lpVtbl->Base.RegisterEffectFromStream((ID2D1Factory1 *)This, classId, propertyXml, bindings, bindingsCount, effectFactory))
|
||||
|
||||
#define ID2D1Factory2_RegisterEffectFromString(This, classId, propertyXml, bindings, bindingsCount, effectFactory) \
|
||||
((This)->lpVtbl->Base.RegisterEffectFromString((ID2D1Factory1 *)This, classId, propertyXml, bindings, bindingsCount, effectFactory))
|
||||
|
||||
#define ID2D1Factory2_UnregisterEffect(This, classId) \
|
||||
((This)->lpVtbl->Base.UnregisterEffect((ID2D1Factory1 *)This, classId))
|
||||
|
||||
#define ID2D1Factory2_GetRegisteredEffects(This, effects, effectsCount, effectsReturned, effectsRegistered) \
|
||||
((This)->lpVtbl->Base.GetRegisteredEffects((ID2D1Factory1 *)This, effects, effectsCount, effectsReturned, effectsRegistered))
|
||||
|
||||
#define ID2D1Factory2_GetEffectProperties(This, effectId, properties) \
|
||||
((This)->lpVtbl->Base.GetEffectProperties((ID2D1Factory1 *)This, effectId, properties))
|
||||
|
||||
#define ID2D1Factory2_CreateDevice(This, dxgiDevice, d2dDevice1) \
|
||||
((This)->lpVtbl->CreateDevice(This, dxgiDevice, d2dDevice1))
|
||||
|
||||
typedef interface ID2D1CommandSink1 ID2D1CommandSink1;
|
||||
|
||||
typedef struct ID2D1CommandSink1Vtbl
|
||||
{
|
||||
|
||||
ID2D1CommandSinkVtbl Base;
|
||||
|
||||
|
||||
STDMETHOD(SetPrimitiveBlend1)(
|
||||
ID2D1CommandSink1 *This,
|
||||
D2D1_PRIMITIVE_BLEND primitiveBlend
|
||||
) PURE;
|
||||
} ID2D1CommandSink1Vtbl;
|
||||
|
||||
interface ID2D1CommandSink1
|
||||
{
|
||||
CONST struct ID2D1CommandSink1Vtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
#define ID2D1CommandSink1_QueryInterface(This, riid, ppv) \
|
||||
((This)->lpVtbl->Base.Base.QueryInterface((IUnknown *)This, riid, ppv))
|
||||
|
||||
#define ID2D1CommandSink1_AddRef(This) \
|
||||
((This)->lpVtbl->Base.Base.AddRef((IUnknown *)This))
|
||||
|
||||
#define ID2D1CommandSink1_Release(This) \
|
||||
((This)->lpVtbl->Base.Base.Release((IUnknown *)This))
|
||||
|
||||
#define ID2D1CommandSink1_BeginDraw(This) \
|
||||
((This)->lpVtbl->Base.BeginDraw((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_EndDraw(This) \
|
||||
((This)->lpVtbl->Base.EndDraw((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_SetAntialiasMode(This, antialiasMode) \
|
||||
((This)->lpVtbl->Base.SetAntialiasMode((ID2D1CommandSink *)This, antialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_SetTags(This, tag1, tag2) \
|
||||
((This)->lpVtbl->Base.SetTags((ID2D1CommandSink *)This, tag1, tag2))
|
||||
|
||||
#define ID2D1CommandSink1_SetTextAntialiasMode(This, textAntialiasMode) \
|
||||
((This)->lpVtbl->Base.SetTextAntialiasMode((ID2D1CommandSink *)This, textAntialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_SetTextRenderingParams(This, textRenderingParams) \
|
||||
((This)->lpVtbl->Base.SetTextRenderingParams((ID2D1CommandSink *)This, textRenderingParams))
|
||||
|
||||
#define ID2D1CommandSink1_SetTransform(This, transform) \
|
||||
((This)->lpVtbl->Base.SetTransform((ID2D1CommandSink *)This, transform))
|
||||
|
||||
#define ID2D1CommandSink1_SetPrimitiveBlend(This, primitiveBlend) \
|
||||
((This)->lpVtbl->Base.SetPrimitiveBlend((ID2D1CommandSink *)This, primitiveBlend))
|
||||
|
||||
#define ID2D1CommandSink1_SetUnitMode(This, unitMode) \
|
||||
((This)->lpVtbl->Base.SetUnitMode((ID2D1CommandSink *)This, unitMode))
|
||||
|
||||
#define ID2D1CommandSink1_Clear(This, color) \
|
||||
((This)->lpVtbl->Base.Clear((ID2D1CommandSink *)This, color))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGlyphRun(This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode) \
|
||||
((This)->lpVtbl->Base.DrawGlyphRun((ID2D1CommandSink *)This, baselineOrigin, glyphRun, glyphRunDescription, foregroundBrush, measuringMode))
|
||||
|
||||
#define ID2D1CommandSink1_DrawLine(This, point0, point1, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawLine((ID2D1CommandSink *)This, point0, point1, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGeometry(This, geometry, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawGeometry((ID2D1CommandSink *)This, geometry, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawRectangle(This, rect, brush, strokeWidth, strokeStyle) \
|
||||
((This)->lpVtbl->Base.DrawRectangle((ID2D1CommandSink *)This, rect, brush, strokeWidth, strokeStyle))
|
||||
|
||||
#define ID2D1CommandSink1_DrawBitmap(This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform) \
|
||||
((This)->lpVtbl->Base.DrawBitmap((ID2D1CommandSink *)This, bitmap, destinationRectangle, opacity, interpolationMode, sourceRectangle, perspectiveTransform))
|
||||
|
||||
#define ID2D1CommandSink1_DrawImage(This, image, targetOffset, imageRectangle, interpolationMode, compositeMode) \
|
||||
((This)->lpVtbl->Base.DrawImage((ID2D1CommandSink *)This, image, targetOffset, imageRectangle, interpolationMode, compositeMode))
|
||||
|
||||
#define ID2D1CommandSink1_DrawGdiMetafile(This, gdiMetafile, targetOffset) \
|
||||
((This)->lpVtbl->Base.DrawGdiMetafile((ID2D1CommandSink *)This, gdiMetafile, targetOffset))
|
||||
|
||||
#define ID2D1CommandSink1_FillMesh(This, mesh, brush) \
|
||||
((This)->lpVtbl->Base.FillMesh((ID2D1CommandSink *)This, mesh, brush))
|
||||
|
||||
#define ID2D1CommandSink1_FillOpacityMask(This, opacityMask, brush, destinationRectangle, sourceRectangle) \
|
||||
((This)->lpVtbl->Base.FillOpacityMask((ID2D1CommandSink *)This, opacityMask, brush, destinationRectangle, sourceRectangle))
|
||||
|
||||
#define ID2D1CommandSink1_FillGeometry(This, geometry, brush, opacityBrush) \
|
||||
((This)->lpVtbl->Base.FillGeometry((ID2D1CommandSink *)This, geometry, brush, opacityBrush))
|
||||
|
||||
#define ID2D1CommandSink1_FillRectangle(This, rect, brush) \
|
||||
((This)->lpVtbl->Base.FillRectangle((ID2D1CommandSink *)This, rect, brush))
|
||||
|
||||
#define ID2D1CommandSink1_PushAxisAlignedClip(This, clipRect, antialiasMode) \
|
||||
((This)->lpVtbl->Base.PushAxisAlignedClip((ID2D1CommandSink *)This, clipRect, antialiasMode))
|
||||
|
||||
#define ID2D1CommandSink1_PushLayer(This, layerParameters1, layer) \
|
||||
((This)->lpVtbl->Base.PushLayer((ID2D1CommandSink *)This, layerParameters1, layer))
|
||||
|
||||
#define ID2D1CommandSink1_PopAxisAlignedClip(This) \
|
||||
((This)->lpVtbl->Base.PopAxisAlignedClip((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_PopLayer(This) \
|
||||
((This)->lpVtbl->Base.PopLayer((ID2D1CommandSink *)This))
|
||||
|
||||
#define ID2D1CommandSink1_SetPrimitiveBlend1(This, primitiveBlend) \
|
||||
((This)->lpVtbl->SetPrimitiveBlend1(This, primitiveBlend))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Vendored
+1582
-853
File diff suppressed because it is too large
Load Diff
-10
@@ -215,16 +215,6 @@ 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) */
|
||||
|
||||
+1865
-1464
File diff suppressed because it is too large
Load Diff
+55
-35
@@ -25,53 +25,73 @@
|
||||
// Built in effect CLSIDs
|
||||
DEFINE_GUID(CLSID_D2D1YCbCr, 0x99503cc1, 0x66c7, 0x45c9, 0xa8, 0x75, 0x8a, 0xd8, 0xa7, 0x91, 0x44, 0x01);
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the YCbCr effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_YCBCR_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the YCbCr effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_YCBCR_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} 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;
|
||||
|
||||
|
||||
+431
-372
@@ -41,494 +41,553 @@ 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
|
||||
|
||||
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>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_CONTRAST_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Contrast effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_CONTRAST_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_CONTRAST_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the RgbToHue effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_RGBTOHUE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the RgbToHue effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_RGBTOHUE_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// Property Name: "OutputColorSpace"
|
||||
// Property Type: D2D1_RGBTOHUE_OUTPUT_COLOR_SPACE
|
||||
//
|
||||
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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the HueToRgb effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HUETORGB_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the HueToRgb effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_HUETORGB_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// Property Name: "InputColorSpace"
|
||||
// Property Type: D2D1_HUETORGB_INPUT_COLOR_SPACE
|
||||
//
|
||||
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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Chroma Key effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_CHROMAKEY_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Chroma Key effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_CHROMAKEY_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_CHROMAKEY_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Emboss effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EMBOSS_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Emboss effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_EMBOSS_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_EMBOSS_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Exposure effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EXPOSURE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Exposure effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_EXPOSURE_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ExposureValue"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_EXPOSURE_PROP_EXPOSURE_VALUE = 0,
|
||||
D2D1_EXPOSURE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
//
|
||||
// Property Name: "ExposureValue"
|
||||
// Property Type: FLOAT
|
||||
//
|
||||
D2D1_EXPOSURE_PROP_EXPOSURE_VALUE = 0,
|
||||
D2D1_EXPOSURE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_EXPOSURE_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Posterize effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_POSTERIZE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Posterize effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_POSTERIZE_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_POSTERIZE_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Sepia effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_SEPIA_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Sepia effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_SEPIA_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_SEPIA_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Sharpen effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_SHARPEN_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Sharpen effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_SHARPEN_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_SHARPEN_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Straighten effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_STRAIGHTEN_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Straighten effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_STRAIGHTEN_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} 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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Temperature And Tint effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_TEMPERATUREANDTINT_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Temperature And Tint effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_TEMPERATUREANDTINT_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_TEMPERATUREANDTINT_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Vignette effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_VIGNETTE_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Vignette effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_VIGNETTE_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_VIGNETTE_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Edge Detection effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_EDGEDETECTION_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Edge Detection effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_EDGEDETECTION_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} 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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Highlights and Shadows effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_HIGHLIGHTSANDSHADOWS_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Highlights and Shadows effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_HIGHLIGHTSANDSHADOWS_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} 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;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Lookup Table 3D effect's top level properties.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_LOOKUPTABLE3D_PROP
|
||||
//
|
||||
// Synopsis:
|
||||
// The enumeration of the Lookup Table 3D effect's top level properties.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_LOOKUPTABLE3D_PROP
|
||||
{
|
||||
|
||||
/// <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
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
} D2D1_LOOKUPTABLE3D_PROP;
|
||||
|
||||
|
||||
#if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Opacity effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_OPACITY_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Opacity"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_OPACITY_PROP_OPACITY = 0,
|
||||
D2D1_OPACITY_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_OPACITY_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Cross Fade effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_CROSSFADE_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Weight"
|
||||
/// Property Type: FLOAT
|
||||
/// </summary>
|
||||
D2D1_CROSSFADE_PROP_WEIGHT = 0,
|
||||
D2D1_CROSSFADE_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_CROSSFADE_PROP;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of the Tint effect's top level properties.
|
||||
/// </summary>
|
||||
typedef enum D2D1_TINT_PROP
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "Color"
|
||||
/// Property Type: D2D1_VECTOR_4F
|
||||
/// </summary>
|
||||
D2D1_TINT_PROP_COLOR = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Property Name: "ClampOutput"
|
||||
/// Property Type: BOOL
|
||||
/// </summary>
|
||||
D2D1_TINT_PROP_CLAMP_OUTPUT = 1,
|
||||
D2D1_TINT_PROP_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_TINT_PROP;
|
||||
|
||||
|
||||
#endif // #if NTDDI_VERSION >= NTDDI_WIN10_RS1
|
||||
|
||||
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
|
||||
#pragma endregion
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+3
-8
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -7306,8 +7306,7 @@ 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_D3D11_OPTIONS4 = ( D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT + 1 )
|
||||
D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT = ( D3D11_FEATURE_D3D11_OPTIONS3 + 1 )
|
||||
} D3D11_FEATURE;
|
||||
|
||||
typedef struct D3D11_FEATURE_DATA_THREADING
|
||||
@@ -9662,9 +9661,6 @@ 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;
|
||||
@@ -9933,8 +9929,7 @@ 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_METADATA_HDR10 = 0x800
|
||||
D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_SHADER_USAGE = 0x400
|
||||
} D3D11_VIDEO_PROCESSOR_FEATURE_CAPS;
|
||||
|
||||
typedef
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
-2233
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+28
-977
File diff suppressed because it is too large
Load Diff
+23
-485
@@ -8,7 +8,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
|
||||
|
||||
|
||||
@@ -50,20 +50,6 @@ 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;
|
||||
@@ -78,13 +64,6 @@ 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;
|
||||
@@ -197,106 +176,18 @@ EXTERN_C const IID IID_ID3D12Debug;
|
||||
#endif /* __ID3D12Debug_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#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 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0001 */
|
||||
/* [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
|
||||
{
|
||||
@@ -307,163 +198,10 @@ 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_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__ */
|
||||
|
||||
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;
|
||||
|
||||
#ifndef __ID3D12DebugDevice_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugDevice_INTERFACE_DEFINED__
|
||||
@@ -562,14 +300,14 @@ EXTERN_C const IID IID_ID3D12DebugDevice;
|
||||
#endif /* __ID3D12DebugDevice_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0004 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0002 */
|
||||
/* [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_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_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0002_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __ID3D12DebugCommandQueue_INTERFACE_DEFINED__
|
||||
#define __ID3D12DebugCommandQueue_INTERFACE_DEFINED__
|
||||
@@ -654,136 +392,6 @@ 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__
|
||||
|
||||
@@ -885,7 +493,7 @@ EXTERN_C const IID IID_ID3D12DebugCommandList;
|
||||
#endif /* __ID3D12DebugCommandList_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0007 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0004 */
|
||||
/* [local] */
|
||||
|
||||
typedef
|
||||
@@ -1851,74 +1459,7 @@ 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_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_D3D12_MESSAGES_END = ( D3D12_MESSAGE_ID_NO_COMPUTE_API_SUPPORT + 1 )
|
||||
} D3D12_MESSAGE_ID;
|
||||
|
||||
typedef struct D3D12_MESSAGE
|
||||
@@ -1949,8 +1490,8 @@ typedef struct D3D12_INFO_QUEUE_FILTER
|
||||
#define D3D12_INFO_QUEUE_DEFAULT_MESSAGE_COUNT_LIMIT 1024
|
||||
|
||||
|
||||
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;
|
||||
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 __ID3D12InfoQueue_INTERFACE_DEFINED__
|
||||
#define __ID3D12InfoQueue_INTERFACE_DEFINED__
|
||||
@@ -2357,23 +1898,20 @@ EXTERN_C const IID IID_ID3D12InfoQueue;
|
||||
#endif /* __ID3D12InfoQueue_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0008 */
|
||||
/* interface __MIDL_itf_d3d12sdklayers_0000_0005 */
|
||||
/* [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_0008_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0008_v0_0_s_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3d12sdklayers_0000_0005_v0_0_s_ifspec;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
+3
-123
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -46,13 +46,6 @@ 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"
|
||||
@@ -449,119 +442,6 @@ 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
|
||||
{
|
||||
@@ -986,8 +866,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_0002_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_d3dcommon_0000_0002_v0_0_s_ifspec;
|
||||
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;
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
|
||||
Vendored
+48
-277
@@ -3,7 +3,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Abstract:
|
||||
// Public API definitions shared by DWrite, D2D, and DImage.
|
||||
// Public API definitions for DWrite, D2D and DImage.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#pragma once
|
||||
@@ -21,72 +21,84 @@
|
||||
#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
|
||||
//
|
||||
struct IDXGISurface;
|
||||
interface IDXGISurface;
|
||||
|
||||
/// <summary>
|
||||
/// The measuring method used for text layout.
|
||||
/// </summary>
|
||||
//+----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// DWRITE_MEASURING_MODE
|
||||
//
|
||||
// Synopsis:
|
||||
// The measuring method used for text layout.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
typedef enum DWRITE_MEASURING_MODE
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
//
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
//
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Qualifies how alpha is to be treated in a bitmap or render target containing
|
||||
/// alpha.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Enum:
|
||||
// D2D1_ALPHA_MODE
|
||||
//
|
||||
// Synopsis:
|
||||
// Qualifies how alpha is to be treated in a bitmap or render target containing
|
||||
// alpha.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef enum D2D1_ALPHA_MODE
|
||||
{
|
||||
|
||||
/// <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>
|
||||
//
|
||||
// Alpha mode should be determined implicitly. Some target surfaces do not supply
|
||||
// or imply this information in which case alpha must be specified.
|
||||
//
|
||||
D2D1_ALPHA_MODE_UNKNOWN = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Treat the alpha as premultipled.
|
||||
/// </summary>
|
||||
//
|
||||
// Treat the alpha as premultipled.
|
||||
//
|
||||
D2D1_ALPHA_MODE_PREMULTIPLIED = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Opacity is in the 'A' component only.
|
||||
/// </summary>
|
||||
//
|
||||
// Opacity is in the 'A' component only.
|
||||
//
|
||||
D2D1_ALPHA_MODE_STRAIGHT = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Ignore any alpha channel information.
|
||||
/// </summary>
|
||||
//
|
||||
// Ignore any alpha channel information.
|
||||
//
|
||||
D2D1_ALPHA_MODE_IGNORE = 3,
|
||||
|
||||
D2D1_ALPHA_MODE_FORCE_DWORD = 0xffffffff
|
||||
|
||||
} D2D1_ALPHA_MODE;
|
||||
|
||||
/// <summary>
|
||||
/// Description of a pixel format.
|
||||
/// </summary>
|
||||
//+-----------------------------------------------------------------------------
|
||||
//
|
||||
// Struct:
|
||||
// D2D1_PIXEL_FORMAT
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct D2D1_PIXEL_FORMAT
|
||||
{
|
||||
DXGI_FORMAT format;
|
||||
@@ -94,245 +106,4 @@ typedef struct D2D1_PIXEL_FORMAT
|
||||
|
||||
} D2D1_PIXEL_FORMAT;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an x-coordinate and y-coordinate pair in two-dimensional space.
|
||||
/// </summary>
|
||||
typedef struct D2D_POINT_2U
|
||||
{
|
||||
UINT32 x;
|
||||
UINT32 y;
|
||||
|
||||
} D2D_POINT_2U;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an x-coordinate and y-coordinate pair in two-dimensional space.
|
||||
/// </summary>
|
||||
typedef struct D2D_POINT_2F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
|
||||
} D2D_POINT_2F;
|
||||
|
||||
typedef POINT D2D_POINT_2L;
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 2 FLOAT values (x, y).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_2F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
|
||||
} D2D_VECTOR_2F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 3 FLOAT values (x, y, z).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_3F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
FLOAT z;
|
||||
|
||||
} D2D_VECTOR_3F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A vector of 4 FLOAT values (x, y, z, w).
|
||||
/// </summary>
|
||||
typedef struct D2D_VECTOR_4F
|
||||
{
|
||||
FLOAT x;
|
||||
FLOAT y;
|
||||
FLOAT z;
|
||||
FLOAT w;
|
||||
|
||||
} D2D_VECTOR_4F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle defined by the coordinates of the upper-left corner
|
||||
/// (left, top) and the coordinates of the lower-right corner (right, bottom).
|
||||
/// </summary>
|
||||
typedef struct D2D_RECT_F
|
||||
{
|
||||
FLOAT left;
|
||||
FLOAT top;
|
||||
FLOAT right;
|
||||
FLOAT bottom;
|
||||
|
||||
} D2D_RECT_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle defined by the coordinates of the upper-left corner
|
||||
/// (left, top) and the coordinates of the lower-right corner (right, bottom).
|
||||
/// </summary>
|
||||
typedef struct D2D_RECT_U
|
||||
{
|
||||
UINT32 left;
|
||||
UINT32 top;
|
||||
UINT32 right;
|
||||
UINT32 bottom;
|
||||
|
||||
} D2D_RECT_U;
|
||||
|
||||
typedef RECT D2D_RECT_L;
|
||||
|
||||
/// <summary>
|
||||
/// Stores an ordered pair of floats, typically the width and height of a rectangle.
|
||||
/// </summary>
|
||||
typedef struct D2D_SIZE_F
|
||||
{
|
||||
FLOAT width;
|
||||
FLOAT height;
|
||||
|
||||
} D2D_SIZE_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stores an ordered pair of integers, typically the width and height of a
|
||||
/// rectangle.
|
||||
/// </summary>
|
||||
typedef struct D2D_SIZE_U
|
||||
{
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
|
||||
} D2D_SIZE_U;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 3-by-2 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_3X2_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Horizontal scaling / cosine of rotation
|
||||
/// </summary>
|
||||
FLOAT m11;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical shear / sine of rotation
|
||||
/// </summary>
|
||||
FLOAT m12;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal shear / negative sine of rotation
|
||||
/// </summary>
|
||||
FLOAT m21;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical scaling / cosine of rotation
|
||||
/// </summary>
|
||||
FLOAT m22;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal shift (always orthogonal regardless of rotation)
|
||||
/// </summary>
|
||||
FLOAT dx;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical shift (always orthogonal regardless of rotation)
|
||||
/// </summary>
|
||||
FLOAT dy;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12;
|
||||
FLOAT _21, _22;
|
||||
FLOAT _31, _32;
|
||||
};
|
||||
|
||||
FLOAT m[3][2];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_3X2_F;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 4-by-3 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_4X3_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13;
|
||||
FLOAT _21, _22, _23;
|
||||
FLOAT _31, _32, _33;
|
||||
FLOAT _41, _42, _43;
|
||||
};
|
||||
|
||||
FLOAT m[4][3];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_4X3_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 4-by-4 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_4X4_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13, _14;
|
||||
FLOAT _21, _22, _23, _24;
|
||||
FLOAT _31, _32, _33, _34;
|
||||
FLOAT _41, _42, _43, _44;
|
||||
};
|
||||
|
||||
FLOAT m[4][4];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_4X4_F;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 5-by-4 matrix.
|
||||
/// </summary>
|
||||
typedef struct D2D_MATRIX_5X4_F
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
FLOAT _11, _12, _13, _14;
|
||||
FLOAT _21, _22, _23, _24;
|
||||
FLOAT _31, _32, _33, _34;
|
||||
FLOAT _41, _42, _43, _44;
|
||||
FLOAT _51, _52, _53, _54;
|
||||
};
|
||||
|
||||
FLOAT m[5][4];
|
||||
};
|
||||
|
||||
} D2D_MATRIX_5X4_F;
|
||||
|
||||
|
||||
typedef D2D_POINT_2F D2D1_POINT_2F;
|
||||
typedef D2D_POINT_2U D2D1_POINT_2U;
|
||||
typedef D2D_POINT_2L D2D1_POINT_2L;
|
||||
typedef D2D_RECT_F D2D1_RECT_F;
|
||||
typedef D2D_RECT_U D2D1_RECT_U;
|
||||
typedef D2D_RECT_L D2D1_RECT_L;
|
||||
typedef D2D_SIZE_F D2D1_SIZE_F;
|
||||
typedef D2D_SIZE_U D2D1_SIZE_U;
|
||||
typedef D2D_MATRIX_3X2_F D2D1_MATRIX_3X2_F;
|
||||
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif /* DCOMMON_H_INCLUDED */
|
||||
|
||||
Vendored
+11
-15
@@ -10,7 +10,9 @@
|
||||
#ifndef DWRITE_H_INCLUDED
|
||||
#define DWRITE_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef DWRITE_NO_WINDOWS_H
|
||||
|
||||
@@ -54,7 +56,7 @@ enum DWRITE_FONT_FILE_TYPE
|
||||
/// <summary>
|
||||
/// OpenType font that contains a TrueType collection.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION,
|
||||
DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION,
|
||||
|
||||
/// <summary>
|
||||
/// Type 1 PFM font.
|
||||
@@ -74,10 +76,7 @@ enum DWRITE_FONT_FILE_TYPE
|
||||
/// <summary>
|
||||
/// Bitmap .FON font.
|
||||
/// </summary>
|
||||
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,
|
||||
DWRITE_FONT_FILE_TYPE_BITMAP
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -98,9 +97,9 @@ enum DWRITE_FONT_FACE_TYPE
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE,
|
||||
|
||||
/// <summary>
|
||||
/// OpenType font face that is a part of a TrueType or CFF collection.
|
||||
/// OpenType font face that is a part of a TrueType collection.
|
||||
/// </summary>
|
||||
DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION,
|
||||
DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION,
|
||||
|
||||
/// <summary>
|
||||
/// A Type 1 font face.
|
||||
@@ -128,10 +127,7 @@ 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,
|
||||
|
||||
// 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,
|
||||
DWRITE_FONT_FACE_TYPE_RAW_CFF
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -2450,7 +2446,7 @@ enum DWRITE_NUMBER_SUBSTITUTION_METHOD
|
||||
/// <summary>
|
||||
/// Holds the appropriate digits and numeric punctuation for a given locale.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("14885CC9-BAB0-4f90-B6ED-5C366A2CD03D") IDWriteNumberSubstitution : public IUnknown
|
||||
interface DECLSPEC_UUID("14885CC9-BAB0-4f90-B6ED-5C366A2CD03D") DECLSPEC_NOVTABLE IDWriteNumberSubstitution : public IUnknown
|
||||
{
|
||||
};
|
||||
|
||||
@@ -2515,7 +2511,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 DWRITE_DECLARE_INTERFACE("688e1a58-5094-47c8-adc8-fbcea60ae92b") IDWriteTextAnalysisSource : public IUnknown
|
||||
interface DECLSPEC_UUID("688e1a58-5094-47c8-adc8-fbcea60ae92b") DECLSPEC_NOVTABLE IDWriteTextAnalysisSource : public IUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a block of text starting at the specified text position.
|
||||
@@ -2624,7 +2620,7 @@ interface DWRITE_DECLARE_INTERFACE("688e1a58-5094-47c8-adc8-fbcea60ae92b") IDWri
|
||||
/// 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 DWRITE_DECLARE_INTERFACE("5810cd44-0ca0-4701-b3fa-bec5182ae4f6") IDWriteTextAnalysisSink : public IUnknown
|
||||
interface DECLSPEC_UUID("5810cd44-0ca0-4701-b3fa-bec5182ae4f6") DECLSPEC_NOVTABLE IDWriteTextAnalysisSink : public IUnknown
|
||||
{
|
||||
/// <summary>
|
||||
/// Report script analysis for the text range.
|
||||
@@ -2922,7 +2918,7 @@ interface DWRITE_DECLARE_INTERFACE("b7e6163e-7f46-43b4-84b3-e4e6249c365d") IDWri
|
||||
_In_reads_(glyphCount) UINT16 const* glyphIndices,
|
||||
_In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProps,
|
||||
UINT32 glyphCount,
|
||||
_In_ IDWriteFontFace* fontFace,
|
||||
_In_ IDWriteFontFace * fontFace,
|
||||
FLOAT fontEmSize,
|
||||
BOOL isSideways,
|
||||
BOOL isRightToLeft,
|
||||
|
||||
Vendored
+2
-6
@@ -1101,8 +1101,6 @@ 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,
|
||||
@@ -1357,8 +1355,6 @@ 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.
|
||||
@@ -1718,7 +1714,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 DWRITE_DECLARE_INTERFACE("639CFAD8-0FB4-4B21-A58A-067920120009") IDWriteTextAnalysisSource1 : public IDWriteTextAnalysisSource
|
||||
interface DECLSPEC_UUID("{639CFAD8-0FB4-4B21-A58A-067920120009}") DECLSPEC_NOVTABLE IDWriteTextAnalysisSource1 : public IDWriteTextAnalysisSource
|
||||
{
|
||||
/// <summary>
|
||||
/// The text analyzer calls back to this to get the desired glyph
|
||||
@@ -1757,7 +1753,7 @@ interface DWRITE_DECLARE_INTERFACE("639CFAD8-0FB4-4B21-A58A-067920120009") IDWri
|
||||
/// The interface implemented by the client to receive the
|
||||
/// output of the text analyzers.
|
||||
/// </summary>
|
||||
interface DWRITE_DECLARE_INTERFACE("B0D941A0-85E7-4D8B-9FD3-5CED9934482A") IDWriteTextAnalysisSink1 : public IDWriteTextAnalysisSink
|
||||
interface DECLSPEC_UUID("B0D941A0-85E7-4D8B-9FD3-5CED9934482A") DECLSPEC_NOVTABLE IDWriteTextAnalysisSink1 : public IDWriteTextAnalysisSink
|
||||
{
|
||||
/// <summary>
|
||||
/// The text analyzer calls back to this to report the actual orientation
|
||||
|
||||
Vendored
+6
-10
@@ -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,
|
||||
_Out_range_(0, textLength) UINT32* mappedLength,
|
||||
_COM_Outptr_result_maybenull_ IDWriteFont** mappedFont,
|
||||
_Deref_out_range_(0, textLength) UINT32* mappedLength,
|
||||
_COM_Outptr_ IDWriteFont** mappedFont,
|
||||
_Out_ FLOAT* scale
|
||||
) PURE;
|
||||
};
|
||||
@@ -653,10 +653,8 @@ typedef D3DCOLORVALUE DWRITE_COLOR_F;
|
||||
interface DWRITE_DECLARE_INTERFACE("29748ed6-8c9c-4a6a-be0b-d912e8538944") IDWriteFont2 : public IDWriteFont1
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// Returns TRUE if the font contains color information (COLR and CPAL tables),
|
||||
/// or FALSE if not.
|
||||
/// </summary>
|
||||
STDMETHOD_(BOOL, IsColorFont)() PURE;
|
||||
};
|
||||
@@ -669,10 +667,8 @@ 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 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.
|
||||
/// Returns TRUE if the font contains color information (COLR and CPAL tables),
|
||||
/// or FALSE if not.
|
||||
/// </summary>
|
||||
STDMETHOD_(BOOL, IsColorFont)() PURE;
|
||||
|
||||
|
||||
Vendored
+3
-319
@@ -10,7 +10,9 @@
|
||||
#ifndef DWRITE_3_H_INCLUDED
|
||||
#define DWRITE_3_H_INCLUDED
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <DWrite_2.h>
|
||||
|
||||
@@ -1245,8 +1247,6 @@ 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,320 +1740,4 @@ interface DWRITE_DECLARE_INTERFACE("07DDCD52-020E-4DE8-AC33-6C953D83F92D") IDWri
|
||||
) PURE;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#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
|
||||
#endif /* DWRITE_3_H_INCLUDED */
|
||||
|
||||
Vendored
+2
-4
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
@@ -273,8 +273,7 @@ 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_ALLOW_TEARING = 2048
|
||||
DXGI_SWAP_CHAIN_FLAG_HW_PROTECTED = 1024
|
||||
} DXGI_SWAP_CHAIN_FLAG;
|
||||
|
||||
typedef struct DXGI_SWAP_CHAIN_DESC
|
||||
@@ -1685,7 +1684,6 @@ EXTERN_C const IID IID_IDXGIOutput;
|
||||
#define DXGI_PRESENT_STEREO_TEMPORARY_MONO 0x00000020UL
|
||||
#define DXGI_PRESENT_RESTRICT_TO_OUTPUT 0x00000040UL
|
||||
#define DXGI_PRESENT_USE_DURATION 0x00000100UL
|
||||
#define DXGI_PRESENT_ALLOW_TEARING 0x00000200UL
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_dxgi_0000_0008_v0_0_c_ifspec;
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 8.01.0618 */
|
||||
/* File created by MIDL compiler version 8.00.0613 */
|
||||
/* @@MIDL_FILE_HEADING( ) */
|
||||
|
||||
|
||||
|
||||
Vendored
-1533
File diff suppressed because it is too large
Load Diff
Vendored
-6
@@ -119,12 +119,6 @@ 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
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
sdkddkver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Master include file for versioning windows SDK/DDK.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_SDKDDKVER
|
||||
#define _INC_SDKDDKVER
|
||||
|
||||
#if (_MSC_VER >= 800)
|
||||
#if (_MSC_VER >= 1200)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4668) /* #if not_defined treated as #if 0 */
|
||||
#endif
|
||||
#pragma warning(disable:4001) /* nonstandard extension : single line comment */
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// _WIN32_WINNT version constants
|
||||
//
|
||||
#define _WIN32_WINNT_NT4 0x0400
|
||||
#define _WIN32_WINNT_WIN2K 0x0500
|
||||
#define _WIN32_WINNT_WINXP 0x0501
|
||||
#define _WIN32_WINNT_WS03 0x0502
|
||||
#define _WIN32_WINNT_WIN6 0x0600
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#define _WIN32_WINNT_WS08 0x0600
|
||||
#define _WIN32_WINNT_LONGHORN 0x0600
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||
#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* ABRACADABRA_THRESHOLD*/
|
||||
#define _WIN32_WINNT_WIN10 0x0A00 /* ABRACADABRA_THRESHOLD*/
|
||||
|
||||
//
|
||||
// _WIN32_IE_ version constants
|
||||
//
|
||||
#define _WIN32_IE_IE20 0x0200
|
||||
#define _WIN32_IE_IE30 0x0300
|
||||
#define _WIN32_IE_IE302 0x0302
|
||||
#define _WIN32_IE_IE40 0x0400
|
||||
#define _WIN32_IE_IE401 0x0401
|
||||
#define _WIN32_IE_IE50 0x0500
|
||||
#define _WIN32_IE_IE501 0x0501
|
||||
#define _WIN32_IE_IE55 0x0550
|
||||
#define _WIN32_IE_IE60 0x0600
|
||||
#define _WIN32_IE_IE60SP1 0x0601
|
||||
#define _WIN32_IE_IE60SP2 0x0603
|
||||
#define _WIN32_IE_IE70 0x0700
|
||||
#define _WIN32_IE_IE80 0x0800
|
||||
#define _WIN32_IE_IE90 0x0900
|
||||
#define _WIN32_IE_IE100 0x0A00
|
||||
#define _WIN32_IE_IE110 0x0A00 /* ABRACADABRA_THRESHOLD */
|
||||
|
||||
//
|
||||
// IE <-> OS version mapping
|
||||
//
|
||||
// NT4 supports IE versions 2.0 -> 6.0 SP1
|
||||
#define _WIN32_IE_NT4 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP1 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP2 _WIN32_IE_IE20
|
||||
#define _WIN32_IE_NT4SP3 _WIN32_IE_IE302
|
||||
#define _WIN32_IE_NT4SP4 _WIN32_IE_IE401
|
||||
#define _WIN32_IE_NT4SP5 _WIN32_IE_IE401
|
||||
#define _WIN32_IE_NT4SP6 _WIN32_IE_IE50
|
||||
// Win98 supports IE versions 4.01 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN98 _WIN32_IE_IE401
|
||||
// Win98SE supports IE versions 5.0 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN98SE _WIN32_IE_IE50
|
||||
// WinME supports IE versions 5.5 -> 6.0 SP1
|
||||
#define _WIN32_IE_WINME _WIN32_IE_IE55
|
||||
// Win2k supports IE versions 5.01 -> 6.0 SP1
|
||||
#define _WIN32_IE_WIN2K _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP1 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP2 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP3 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_WIN2KSP4 _WIN32_IE_IE501
|
||||
#define _WIN32_IE_XP _WIN32_IE_IE60
|
||||
#define _WIN32_IE_XPSP1 _WIN32_IE_IE60SP1
|
||||
#define _WIN32_IE_XPSP2 _WIN32_IE_IE60SP2
|
||||
#define _WIN32_IE_WS03 0x0602
|
||||
#define _WIN32_IE_WS03SP1 _WIN32_IE_IE60SP2
|
||||
#define _WIN32_IE_WIN6 _WIN32_IE_IE70
|
||||
#define _WIN32_IE_LONGHORN _WIN32_IE_IE70
|
||||
#define _WIN32_IE_WIN7 _WIN32_IE_IE80
|
||||
#define _WIN32_IE_WIN8 _WIN32_IE_IE100
|
||||
#define _WIN32_IE_WINBLUE _WIN32_IE_IE100
|
||||
#define _WIN32_IE_WINTHRESHOLD _WIN32_IE_IE110 /* ABRACADABRA_THRESHOLD */
|
||||
#define _WIN32_IE_WIN10 _WIN32_IE_IE110 /* ABRACADABRA_THRESHOLD */
|
||||
|
||||
|
||||
//
|
||||
// NTDDI version constants
|
||||
//
|
||||
#define NTDDI_WIN2K 0x05000000
|
||||
#define NTDDI_WIN2KSP1 0x05000100
|
||||
#define NTDDI_WIN2KSP2 0x05000200
|
||||
#define NTDDI_WIN2KSP3 0x05000300
|
||||
#define NTDDI_WIN2KSP4 0x05000400
|
||||
|
||||
#define NTDDI_WINXP 0x05010000
|
||||
#define NTDDI_WINXPSP1 0x05010100
|
||||
#define NTDDI_WINXPSP2 0x05010200
|
||||
#define NTDDI_WINXPSP3 0x05010300
|
||||
#define NTDDI_WINXPSP4 0x05010400
|
||||
|
||||
#define NTDDI_WS03 0x05020000
|
||||
#define NTDDI_WS03SP1 0x05020100
|
||||
#define NTDDI_WS03SP2 0x05020200
|
||||
#define NTDDI_WS03SP3 0x05020300
|
||||
#define NTDDI_WS03SP4 0x05020400
|
||||
|
||||
#define NTDDI_WIN6 0x06000000
|
||||
#define NTDDI_WIN6SP1 0x06000100
|
||||
#define NTDDI_WIN6SP2 0x06000200
|
||||
#define NTDDI_WIN6SP3 0x06000300
|
||||
#define NTDDI_WIN6SP4 0x06000400
|
||||
|
||||
#define NTDDI_VISTA NTDDI_WIN6
|
||||
#define NTDDI_VISTASP1 NTDDI_WIN6SP1
|
||||
#define NTDDI_VISTASP2 NTDDI_WIN6SP2
|
||||
#define NTDDI_VISTASP3 NTDDI_WIN6SP3
|
||||
#define NTDDI_VISTASP4 NTDDI_WIN6SP4
|
||||
|
||||
#define NTDDI_LONGHORN NTDDI_VISTA
|
||||
|
||||
#define NTDDI_WS08 NTDDI_WIN6SP1
|
||||
#define NTDDI_WS08SP2 NTDDI_WIN6SP2
|
||||
#define NTDDI_WS08SP3 NTDDI_WIN6SP3
|
||||
#define NTDDI_WS08SP4 NTDDI_WIN6SP4
|
||||
|
||||
#define NTDDI_WIN7 0x06010000
|
||||
#define NTDDI_WIN8 0x06020000
|
||||
#define NTDDI_WINBLUE 0x06030000
|
||||
#define NTDDI_WINTHRESHOLD 0x0A000000 /* ABRACADABRA_THRESHOLD */
|
||||
#define NTDDI_WIN10 0x0A000000 /* ABRACADABRA_THRESHOLD */
|
||||
#define NTDDI_WIN10_TH2 0x0A000001 /* ABRACADABRA_WIN10_TH2 */
|
||||
#define NTDDI_WIN10_RS1 0x0A000002 /* ABRACADABRA_WIN10_RS1 */
|
||||
|
||||
//
|
||||
// masks for version macros
|
||||
//
|
||||
#define OSVERSION_MASK 0xFFFF0000
|
||||
#define SPVERSION_MASK 0x0000FF00
|
||||
#define SUBVERSION_MASK 0x000000FF
|
||||
|
||||
|
||||
//
|
||||
// macros to extract various version fields from the NTDDI version
|
||||
//
|
||||
#define OSVER(Version) ((Version) & OSVERSION_MASK)
|
||||
#define SPVER(Version) (((Version) & SPVERSION_MASK) >> 8)
|
||||
#define SUBVER(Version) (((Version) & SUBVERSION_MASK) )
|
||||
|
||||
|
||||
#if defined(DECLSPEC_DEPRECATED_DDK)
|
||||
|
||||
// deprecate in 2k or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN2K)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2K DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2K
|
||||
#endif
|
||||
|
||||
// deprecate in XP or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WINXP)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WINXP DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WINXP
|
||||
#endif
|
||||
|
||||
// deprecate in WS03 or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WS03)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2003 DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN2003
|
||||
#endif
|
||||
|
||||
// deprecate in WIN6 or later
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN6)
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN6 DECLSPEC_DEPRECATED_DDK
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED_DDK_WIN6
|
||||
#endif
|
||||
|
||||
#define DECLSPEC_DEPRECATED_DDK_LONGHORN DECLSPEC_DEPRECATED_DDK_WIN6
|
||||
|
||||
#endif // defined(DECLSPEC_DEPRECATED_DDK)
|
||||
|
||||
|
||||
//
|
||||
// if versions aren't already defined, default to most current
|
||||
//
|
||||
|
||||
#define NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
|
||||
#define NTDDI_VERSION_FROM_WIN32_WINNT(ver) NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
|
||||
|
||||
#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
|
||||
#define _WIN32_WINNT 0x0A00
|
||||
#endif
|
||||
|
||||
#ifndef NTDDI_VERSION
|
||||
#ifdef _WIN32_WINNT
|
||||
// set NTDDI_VERSION based on _WIN32_WINNT
|
||||
#define NTDDI_VERSION NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
|
||||
#else
|
||||
#define NTDDI_VERSION 0x0A000002
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
#ifdef _WIN32_WINNT
|
||||
// set WINVER based on _WIN32_WINNT
|
||||
#define WINVER _WIN32_WINNT
|
||||
#else
|
||||
#define WINVER 0x0A00
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE
|
||||
#ifdef _WIN32_WINNT
|
||||
// set _WIN32_IE based on _WIN32_WINNT
|
||||
#if (_WIN32_WINNT <= _WIN32_WINNT_NT4)
|
||||
#define _WIN32_IE _WIN32_IE_IE50
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
|
||||
#define _WIN32_IE _WIN32_IE_IE501
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WINXP)
|
||||
#define _WIN32_IE _WIN32_IE_IE60
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WS03)
|
||||
#define _WIN32_IE _WIN32_IE_WS03
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_VISTA)
|
||||
#define _WIN32_IE _WIN32_IE_LONGHORN
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN7)
|
||||
#define _WIN32_IE _WIN32_IE_WIN7
|
||||
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN8)
|
||||
#define _WIN32_IE _WIN32_IE_WIN8
|
||||
#else
|
||||
#define _WIN32_IE 0x0A00
|
||||
#endif
|
||||
#else
|
||||
#define _WIN32_IE 0x0A00
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// Sanity check for compatible versions
|
||||
//
|
||||
#if defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(RC_INVOKED)
|
||||
|
||||
#if (defined(WINVER) && (WINVER < 0x0400) && (_WIN32_WINNT > 0x0400))
|
||||
#error WINVER setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WIN2K) && (_WIN32_WINNT != _WIN32_WINNT_WIN2K))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WINXP) && (_WIN32_WINNT != _WIN32_WINNT_WINXP))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WS03) && (_WIN32_WINNT != _WIN32_WINNT_WS03))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_VISTA) && (_WIN32_WINNT != _WIN32_WINNT_VISTA))
|
||||
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
|
||||
#endif
|
||||
|
||||
#if ((_WIN32_WINNT < _WIN32_WINNT_WIN2K) && (_WIN32_IE > _WIN32_IE_IE60SP1))
|
||||
#error _WIN32_WINNT settings conflicts with _WIN32_IE setting
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(_WINRESRC_)
|
||||
|
||||
#if (_MSC_VER >= 800)
|
||||
#if (_MSC_VER >= 1200)
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#pragma warning(default:4001) /* nonstandard extension : single line comment */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_SDKDDKVER */
|
||||
|
||||
Vendored
-1158
File diff suppressed because it is too large
Load Diff
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -22,8 +22,6 @@ 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")
|
||||
|
||||
@@ -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+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691))
|
||||
* GCC 5.1+ or Clang 3.5.0+
|
||||
* 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,3 +55,6 @@ 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)
|
||||
|
||||
+41
-96
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "Platform.h"
|
||||
|
||||
// Helper class, provides access to compiler-specific atomic intrinsics
|
||||
template<typename T, std::size_t Size>
|
||||
@@ -142,38 +143,26 @@ 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)
|
||||
{
|
||||
return atomic_storage<T>::test_and_set(dest, static_cast<T>(1) << bit);
|
||||
const T mask = static_cast<T>(1) << bit;
|
||||
return (atomic_storage<T>::fetch_or(dest, mask) & mask) != 0;
|
||||
}
|
||||
|
||||
static inline bool btr(T& dest, uint bit)
|
||||
{
|
||||
return atomic_storage<T>::test_and_reset(dest, static_cast<T>(1) << bit);
|
||||
const T mask = static_cast<T>(1) << bit;
|
||||
return (atomic_storage<T>::fetch_and(dest, ~mask) & mask) != 0;
|
||||
}
|
||||
|
||||
static inline bool btc(T& dest, uint bit)
|
||||
{
|
||||
return atomic_storage<T>::test_and_complement(dest, static_cast<T>(1) << bit);
|
||||
const T mask = static_cast<T>(1) << bit;
|
||||
return (atomic_storage<T>::fetch_xor(dest, mask) & mask) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* The rest: ugly MSVC intrinsics + inline asm implementations */
|
||||
/* The rest: ugly MSVC intrinsics + possibly __asm__ implementations (TODO) */
|
||||
|
||||
template<typename T>
|
||||
struct atomic_storage<T, 1> : atomic_storage<T, 0>
|
||||
@@ -296,27 +285,6 @@ 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
|
||||
};
|
||||
|
||||
@@ -395,27 +363,6 @@ 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
|
||||
};
|
||||
|
||||
@@ -494,27 +441,6 @@ 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
|
||||
};
|
||||
|
||||
@@ -552,8 +478,6 @@ struct atomic_storage<T, 16> : atomic_storage<T, 0>
|
||||
return *(T*)+cmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename>
|
||||
@@ -706,16 +630,21 @@ struct atomic_test_and_set
|
||||
{
|
||||
bool operator()(T1& lhs, const T2& rhs) const
|
||||
{
|
||||
return test_and_set(lhs, rhs);
|
||||
return lhs.test_and_set(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 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;
|
||||
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;
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename>
|
||||
@@ -723,16 +652,21 @@ struct atomic_test_and_reset
|
||||
{
|
||||
bool operator()(T1& lhs, const T2& rhs) const
|
||||
{
|
||||
return test_and_reset(lhs, rhs);
|
||||
return lhs.test_and_reset(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 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;
|
||||
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;
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, typename>
|
||||
@@ -740,16 +674,21 @@ struct atomic_test_and_complement
|
||||
{
|
||||
bool operator()(T1& lhs, const T2& rhs) const
|
||||
{
|
||||
return test_and_complement(lhs, rhs);
|
||||
return lhs.test_and_complement(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 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;
|
||||
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;
|
||||
};
|
||||
|
||||
// Atomic type with lock-free and standard layout guarantees (and appropriate limitations)
|
||||
@@ -1015,6 +954,12 @@ 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)
|
||||
{
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "Emu/System.h"
|
||||
#include "AutoPause.h"
|
||||
|
||||
cfg::bool_entry g_cfg_debug_autopause_syscall(cfg::root.misc, "Automatically pause at system call");
|
||||
cfg::bool_entry g_cfg_debug_autopause_func_call(cfg::root.misc, "Automatically pause at function call");
|
||||
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");
|
||||
|
||||
debug::autopause& debug::autopause::get_instance()
|
||||
{
|
||||
|
||||
+361
-236
@@ -1,58 +1,56 @@
|
||||
#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;
|
||||
|
||||
@@ -82,7 +80,7 @@ union alignas(16) v128
|
||||
return (data & mask) != 0;
|
||||
}
|
||||
|
||||
bit_element& operator=(const bool right)
|
||||
bit_element& operator =(const bool right)
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
@@ -95,7 +93,7 @@ union alignas(16) v128
|
||||
return *this;
|
||||
}
|
||||
|
||||
bit_element& operator=(const bit_element& right)
|
||||
bit_element& operator =(const bit_element& right)
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
@@ -110,7 +108,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));
|
||||
@@ -118,13 +116,14 @@ 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)
|
||||
{
|
||||
@@ -278,12 +277,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];
|
||||
}
|
||||
@@ -299,69 +298,43 @@ 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]);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t Align, std::size_t Size>
|
||||
#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)>
|
||||
struct se_storage
|
||||
{
|
||||
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;
|
||||
}
|
||||
static_assert(!Size, "Bad se_storage<> type");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct se_storage<T, 2, 2>
|
||||
template<typename T>
|
||||
struct se_storage<T, 2>
|
||||
{
|
||||
using type = u16;
|
||||
|
||||
@@ -384,15 +357,10 @@ struct se_storage<T, 2, 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, 4>
|
||||
template<typename T>
|
||||
struct se_storage<T, 4>
|
||||
{
|
||||
using type = u32;
|
||||
|
||||
@@ -415,15 +383,10 @@ struct se_storage<T, 4, 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, 8>
|
||||
template<typename T>
|
||||
struct se_storage<T, 8>
|
||||
{
|
||||
using type = u64;
|
||||
|
||||
@@ -446,15 +409,10 @@ struct se_storage<T, 8, 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, 16>
|
||||
template<typename T>
|
||||
struct se_storage<T, 16>
|
||||
{
|
||||
using type = v128;
|
||||
|
||||
@@ -473,20 +431,43 @@ struct se_storage<T, 16, 16>
|
||||
const v128 result = swap(src);
|
||||
return reinterpret_cast<const T&>(result);
|
||||
}
|
||||
};
|
||||
|
||||
static inline T copy(const T& src)
|
||||
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)
|
||||
{
|
||||
return src;
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline stype_to convert(const stype_from& data, ...)
|
||||
{
|
||||
return storage_to::to(storage_from::from(data));
|
||||
}
|
||||
};
|
||||
|
||||
static struct se_raw_tag_t {} constexpr se_raw{};
|
||||
|
||||
template<typename T, bool Se = true>
|
||||
class se_t;
|
||||
|
||||
// Switched endianness
|
||||
template <typename T, std::size_t Align>
|
||||
class se_t<T, true, Align>
|
||||
template<typename T>
|
||||
class se_t<T, true>
|
||||
{
|
||||
using type = typename std::remove_cv<T>::type;
|
||||
using stype = typename se_storage<type, Align>::type;
|
||||
using storage = se_storage<type, Align>;
|
||||
using stype = se_storage_t<type>;
|
||||
using storage = se_storage<type>;
|
||||
|
||||
stype m_data;
|
||||
|
||||
@@ -495,6 +476,24 @@ class se_t<T, true, Align>
|
||||
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;
|
||||
|
||||
@@ -504,15 +503,27 @@ 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);
|
||||
}
|
||||
|
||||
se_t& operator=(const se_t&) = default;
|
||||
// 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=(type value)
|
||||
se_t& operator =(type value)
|
||||
{
|
||||
return m_data = storage::to(value), *this;
|
||||
}
|
||||
@@ -523,127 +534,181 @@ 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, std::size_t Align>
|
||||
class se_t<T, false, Align>
|
||||
template<typename T>
|
||||
class se_t<T, false>
|
||||
{
|
||||
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");
|
||||
|
||||
stype m_data;
|
||||
type m_data;
|
||||
|
||||
public:
|
||||
se_t() = default;
|
||||
|
||||
se_t(type value)
|
||||
: m_data(reinterpret_cast<const stype&>(value))
|
||||
constexpr se_t(type value)
|
||||
: m_data(value)
|
||||
{
|
||||
}
|
||||
|
||||
type value() const
|
||||
// Construct directly from raw data (don't use)
|
||||
constexpr se_t(const type& raw_value, const se_raw_tag_t&)
|
||||
: m_data(raw_value)
|
||||
{
|
||||
return storage::copy(reinterpret_cast<const type&>(m_data));
|
||||
}
|
||||
|
||||
se_t& operator=(const se_t& value) = default;
|
||||
|
||||
se_t& operator=(type value)
|
||||
constexpr type value() const
|
||||
{
|
||||
return m_data = reinterpret_cast<const stype&>(value), *this;
|
||||
return m_data;
|
||||
}
|
||||
|
||||
// Access underlying raw data (don't use)
|
||||
constexpr const type& raw_data() const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
se_t& operator =(const se_t& value) = default;
|
||||
|
||||
se_t& operator =(type value)
|
||||
{
|
||||
return m_data = value, *this;
|
||||
}
|
||||
|
||||
using simple_type = simple_t<T>;
|
||||
|
||||
operator type() const
|
||||
constexpr operator type() const
|
||||
{
|
||||
return storage::copy(reinterpret_cast<const type&>(m_data));
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// se_t<> with native endianness
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using nse_t = se_t<T, false, Align>;
|
||||
// se_t with native endianness (alias)
|
||||
template<typename T> using nse_t = se_t<T, false>;
|
||||
|
||||
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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator +=(se_t<T, Se>& 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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator -=(se_t<T, Se>& 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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator *=(se_t<T, Se>& 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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator /=(se_t<T, Se>& 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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator %=(se_t<T, Se>& 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, std::size_t Align, typename T1>
|
||||
inline se_t<T, Se, Align>& operator<<=(se_t<T, Se, Align>& left, const T1& right)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator <<=(se_t<T, Se>& 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)
|
||||
template<typename T, bool Se, typename T1>
|
||||
inline se_t<T, Se>& operator >>=(se_t<T, Se>& left, const T1& right)
|
||||
{
|
||||
auto value = left.value();
|
||||
return left = (value >>= right);
|
||||
}
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
inline se_t<T, Se, Align> operator++(se_t<T, Se, Align>& left, int)
|
||||
template<typename T, bool Se>
|
||||
inline se_t<T, Se> operator ++(se_t<T, Se>& left, int)
|
||||
{
|
||||
auto value = left.value();
|
||||
auto result = value++;
|
||||
@@ -651,8 +716,8 @@ inline se_t<T, Se, Align> operator++(se_t<T, Se, Align>& left, int)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
inline se_t<T, Se, Align> operator--(se_t<T, Se, Align>& left, int)
|
||||
template<typename T, bool Se>
|
||||
inline se_t<T, Se> operator --(se_t<T, Se>& left, int)
|
||||
{
|
||||
auto value = left.value();
|
||||
auto result = value--;
|
||||
@@ -660,111 +725,173 @@ inline se_t<T, Se, Align> operator--(se_t<T, Se, Align>& left, int)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
inline se_t<T, Se, Align>& operator++(se_t<T, Se, Align>& right)
|
||||
template<typename T, bool Se>
|
||||
inline se_t<T, Se>& operator ++(se_t<T, Se>& right)
|
||||
{
|
||||
auto value = right.value();
|
||||
return right = ++value;
|
||||
}
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
inline se_t<T, Se, Align>& operator--(se_t<T, Se, Align>& right)
|
||||
template<typename T, bool Se>
|
||||
inline se_t<T, Se>& operator --(se_t<T, Se>& 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, 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>;
|
||||
template<typename T> using be_t = se_t<T, true>;
|
||||
template<typename T> using le_t = se_t<T, false>;
|
||||
#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 to_se_<T>::type;
|
||||
using type = typename std::conditional<std::is_arithmetic<T>::value || std::is_enum<T>::value, se_t<T, Se>, T>::type;
|
||||
};
|
||||
|
||||
template <bool Se>
|
||||
struct to_se<v128, Se>
|
||||
{
|
||||
using type = se_t<v128, Se>;
|
||||
};
|
||||
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<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>>
|
||||
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
|
||||
@@ -773,27 +900,25 @@ 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
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
struct fmt_unveil<se_t<T, Se, Align>, void>
|
||||
// Formatting for BE/LE data
|
||||
template<typename T, bool Se>
|
||||
struct unveil<se_t<T, Se>, void>
|
||||
{
|
||||
using type = typename fmt_unveil<T>::type;
|
||||
|
||||
static inline auto get(const se_t<T, Se, Align>& arg)
|
||||
static inline auto get(const se_t<T, Se>& arg)
|
||||
{
|
||||
return fmt_unveil<T>::get(arg);
|
||||
return unveil<T>::get(arg);
|
||||
}
|
||||
};
|
||||
|
||||
#undef IS_BINARY_COMPARABLE
|
||||
#undef IS_INTEGER
|
||||
|
||||
+1
-34
@@ -9,7 +9,7 @@ struct bf_base
|
||||
using vtype = simple_t<type>;
|
||||
|
||||
// Datatype bitsize
|
||||
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
|
||||
static constexpr uint bitmax = sizeof(T) * CHAR_BIT; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
|
||||
|
||||
// Field bitsize
|
||||
static constexpr uint bitsize = N;
|
||||
@@ -242,36 +242,3 @@ 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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
#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;
|
||||
};
|
||||
+4
-70
@@ -12,7 +12,7 @@ namespace cfg
|
||||
{
|
||||
if (_type != type::node)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Invalid root node" HERE);
|
||||
throw std::logic_error("Invalid root node");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace cfg
|
||||
{
|
||||
if (!owner.m_nodes.emplace(name, this).second)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Node already exists: %s" HERE, name);
|
||||
throw std::logic_error("Node already exists");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace cfg
|
||||
return *static_cast<const node&>(*this).m_nodes.at(name);
|
||||
}
|
||||
|
||||
fmt::throw_exception<std::logic_error>("Invalid node type" HERE);
|
||||
throw std::logic_error("Invalid node type");
|
||||
}
|
||||
|
||||
entry_base& entry_base::operator[](const char* name) const
|
||||
@@ -42,17 +42,7 @@ namespace cfg
|
||||
return *static_cast<const node&>(*this).m_nodes.at(name);
|
||||
}
|
||||
|
||||
fmt::throw_exception<std::logic_error>("Invalid node type" HERE);
|
||||
}
|
||||
|
||||
bool entry_base::from_string(const std::string&)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("from_string() purecall" HERE);
|
||||
}
|
||||
|
||||
bool entry_base::from_list(std::vector<std::string>&&)
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("from_list() purecall" HERE);
|
||||
throw std::logic_error("Invalid node type");
|
||||
}
|
||||
|
||||
// Emit YAML
|
||||
@@ -95,62 +85,6 @@ 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())
|
||||
|
||||
+34
-22
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/Atomic.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <exception>
|
||||
@@ -19,12 +18,6 @@ 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
|
||||
{
|
||||
@@ -69,7 +62,10 @@ namespace cfg
|
||||
}
|
||||
|
||||
// Try to convert from string (optional)
|
||||
virtual bool from_string(const std::string&);
|
||||
virtual bool from_string(const std::string&)
|
||||
{
|
||||
throw std::logic_error("from_string() not specified");
|
||||
}
|
||||
|
||||
// Get string list (optional)
|
||||
virtual std::vector<std::string> to_list() const
|
||||
@@ -78,7 +74,10 @@ namespace cfg
|
||||
}
|
||||
|
||||
// Set multiple values. Implementation-specific, optional.
|
||||
virtual bool from_list(std::vector<std::string>&&);
|
||||
virtual bool from_list(std::vector<std::string>&&)
|
||||
{
|
||||
throw std::logic_error("from_list() not specified");
|
||||
}
|
||||
};
|
||||
|
||||
// Config tree node which contains another nodes
|
||||
@@ -180,7 +179,7 @@ namespace cfg
|
||||
for (const auto& v : init)
|
||||
{
|
||||
// Ensure elements are unique
|
||||
verify(HERE), map.emplace(v.first, v.second).second;
|
||||
VERIFY(map.emplace(v.first, v.second).second);
|
||||
}
|
||||
|
||||
return map;
|
||||
@@ -217,7 +216,7 @@ namespace cfg
|
||||
}
|
||||
|
||||
map_entry(node& owner, const std::string& name, std::size_t def_index, init_type init)
|
||||
: map_entry(owner, name, (init.begin() + (def_index < init.size() ? def_index : 0))->first, init)
|
||||
: map_entry(owner, name, def_index < init.size() ? (init.begin() + def_index)->first : throw std::logic_error("Invalid default value index"), init)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -297,20 +296,26 @@ namespace cfg
|
||||
|
||||
std::string to_string() const override
|
||||
{
|
||||
std::string result;
|
||||
fmt_class_string<T>::format(result, fmt_unveil<T>::get(m_value));
|
||||
return result; // TODO: ???
|
||||
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: ???
|
||||
}
|
||||
|
||||
bool from_string(const std::string& value) override
|
||||
{
|
||||
u64 result;
|
||||
|
||||
if (try_to_enum_value(&result, &fmt_class_string<T>::format, value))
|
||||
for (std::size_t i = 0; i < sizeof(bijective<T, const char*>::map) / sizeof(bijective_pair<T, const char*>); i++)
|
||||
{
|
||||
// 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;
|
||||
if (bijective<T, const char*>::map[i].v2 == value)
|
||||
{
|
||||
m_value = bijective<T, const char*>::map[i].v1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -318,7 +323,14 @@ namespace cfg
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
return try_to_enum_list(&fmt_class_string<T>::format);
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -352,7 +364,7 @@ namespace cfg
|
||||
{
|
||||
if (value < Min || value > Max)
|
||||
{
|
||||
fmt::throw_exception("Value out of the valid range: %lld" HERE, s64{ value });
|
||||
throw fmt::exception("Value out of the valid range: %lld" HERE, s64{ value });
|
||||
}
|
||||
|
||||
m_value = value;
|
||||
|
||||
+155
-185
@@ -1,8 +1,7 @@
|
||||
#include "File.h"
|
||||
#include "StrFmt.h"
|
||||
#include "Macro.h"
|
||||
#include "SharedMutex.h"
|
||||
#include "BEType.h"
|
||||
#include "Crypto/sha1.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
@@ -15,35 +14,36 @@
|
||||
|
||||
static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
||||
{
|
||||
// String size + null terminator
|
||||
const std::size_t buf_size = source.size() + 1;
|
||||
const auto buf_size = source.size() + 1; // size + null terminator
|
||||
|
||||
// Safe size
|
||||
const int size = narrow<int>(buf_size, "to_wchar" HERE);
|
||||
const int size = source.size() < INT_MAX ? static_cast<int>(buf_size) : throw fmt::exception("to_wchar(): invalid source length (0x%llx)", source.size());
|
||||
|
||||
// Buffer for max possible output length
|
||||
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]);
|
||||
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]); // allocate buffer assuming that length is the max possible size
|
||||
|
||||
verify("to_wchar" HERE), MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size);
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
|
||||
{
|
||||
throw fmt::exception("to_wchar(): MultiByteToWideChar() failed: error %u.", GetLastError());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void to_utf8(std::string& out, const wchar_t* source)
|
||||
static void to_utf8(std::string& result, const wchar_t* source)
|
||||
{
|
||||
// String size
|
||||
const std::size_t length = std::wcslen(source);
|
||||
const auto length = std::wcslen(source);
|
||||
|
||||
// Safe buffer size for max possible output length (including null terminator)
|
||||
const int buf_size = narrow<int>(length * 3 + 1, "to_utf8" HERE);
|
||||
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);
|
||||
|
||||
// Resize buffer
|
||||
out.resize(buf_size - 1);
|
||||
result.resize(buf_size); // set max possible length for utf-8 + null terminator
|
||||
|
||||
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);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
static time_t to_time(const ULARGE_INTEGER& ft)
|
||||
@@ -78,9 +78,7 @@ 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;
|
||||
case ERROR_DIRECTORY: return fs::error::inval;
|
||||
case ERROR_INVALID_NAME: return fs::error::inval;
|
||||
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
|
||||
default: throw fmt::exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +107,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: fmt::throw_exception("Unknown system error: %d.", e);
|
||||
default: throw fmt::exception("Unknown system error: %d.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +170,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)
|
||||
{
|
||||
verify(HERE), name.size() > 2, name[0] == '/', name[1] == '/', name.find('/', 2) == -1;
|
||||
EXPECTS(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
|
||||
|
||||
return get_device_manager().set_device(name, device);
|
||||
}
|
||||
@@ -201,6 +199,33 @@ 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))
|
||||
@@ -436,7 +461,7 @@ bool fs::rename(const std::string& from, const std::string& to)
|
||||
|
||||
if (device != get_virtual_device(to))
|
||||
{
|
||||
fmt::throw_exception("fs::rename() between different devices not implemented.\nFrom: %s\nTo: %s", from, to);
|
||||
throw fmt::exception("fs::rename() between different devices not implemented.\nFrom: %s\nTo: %s", from, to);
|
||||
}
|
||||
|
||||
if (device)
|
||||
@@ -469,7 +494,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
|
||||
|
||||
if (device != get_virtual_device(to) || device) // TODO
|
||||
{
|
||||
fmt::throw_exception("fs::copy_file() for virtual devices not implemented.\nFrom: %s\nTo: %s", from, to);
|
||||
throw fmt::exception("fs::copy_file() for virtual devices not implemented.\nFrom: %s\nTo: %s", from, to);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -593,15 +618,15 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
|
||||
void fs::file::xnull() const
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("fs::file is null");
|
||||
throw std::logic_error("fs::file is null");
|
||||
}
|
||||
|
||||
void fs::file::xfail() const
|
||||
{
|
||||
fmt::throw_exception("Unexpected fs::error %s", g_tls_error);
|
||||
throw fmt::exception("Unexpected fs::error %u", g_tls_error);
|
||||
}
|
||||
|
||||
bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
|
||||
{
|
||||
if (auto device = get_virtual_device(path))
|
||||
{
|
||||
@@ -616,25 +641,25 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD access = 0;
|
||||
if (test(mode & fs::read)) access |= GENERIC_READ;
|
||||
if (test(mode & fs::write)) access |= test(mode & fs::append) ? FILE_APPEND_DATA : GENERIC_WRITE;
|
||||
if (mode & fs::read) access |= GENERIC_READ;
|
||||
if (mode & fs::write) access |= mode & fs::append ? FILE_APPEND_DATA : GENERIC_WRITE;
|
||||
|
||||
DWORD disp = 0;
|
||||
if (test(mode & fs::create))
|
||||
if (mode & fs::create)
|
||||
{
|
||||
disp =
|
||||
test(mode & fs::excl) ? CREATE_NEW :
|
||||
test(mode & fs::trunc) ? CREATE_ALWAYS : OPEN_ALWAYS;
|
||||
mode & fs::excl ? CREATE_NEW :
|
||||
mode & fs::trunc ? CREATE_ALWAYS : OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (test(mode & fs::excl))
|
||||
if (mode & fs::excl)
|
||||
{
|
||||
g_tls_error = error::inval;
|
||||
return false;
|
||||
}
|
||||
|
||||
disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING;
|
||||
disp = 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);
|
||||
@@ -663,7 +688,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
stat_t stat() override
|
||||
{
|
||||
FILE_BASIC_INFO basic_info;
|
||||
verify("file::stat" HERE), GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
|
||||
if (!GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
stat_t info;
|
||||
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
@@ -694,17 +722,27 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
return false;
|
||||
}
|
||||
|
||||
verify("file::trunc" HERE), SetEndOfFile(m_handle), SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN);
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
// TODO (call ReadFile multiple times if count is too big)
|
||||
const int size = narrow<int>(count, "file::read" HERE);
|
||||
const int size = ::narrow<int>(count, "Too big count" HERE);
|
||||
EXPECTS(size >= 0);
|
||||
|
||||
DWORD nread;
|
||||
verify("file::read" HERE), ReadFile(m_handle, buffer, size, &nread, NULL);
|
||||
if (!ReadFile(m_handle, buffer, size, &nread, NULL))
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
@@ -712,10 +750,14 @@ bool fs::file::open(const std::string& path, bs_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, "file::write" HERE);
|
||||
const int size = ::narrow<int>(count, "Too big count" HERE);
|
||||
EXPECTS(size >= 0);
|
||||
|
||||
DWORD nwritten;
|
||||
verify("file::write" HERE), WriteFile(m_handle, buffer, size, &nwritten, NULL);
|
||||
if (!WriteFile(m_handle, buffer, size, &nwritten, NULL))
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
@@ -729,9 +771,12 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
whence == seek_set ? FILE_BEGIN :
|
||||
whence == seek_cur ? FILE_CURRENT :
|
||||
whence == seek_end ? FILE_END :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
|
||||
|
||||
verify("file::seek" HERE), SetFilePointerEx(m_handle, pos, &pos, mode);
|
||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return pos.QuadPart;
|
||||
}
|
||||
@@ -739,7 +784,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 size() override
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
verify("file::size" HERE), GetFileSizeEx(m_handle, &size);
|
||||
if (!GetFileSizeEx(m_handle, &size))
|
||||
{
|
||||
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
|
||||
}
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
@@ -749,14 +797,14 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
#else
|
||||
int flags = 0;
|
||||
|
||||
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::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::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;
|
||||
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;
|
||||
|
||||
const int fd = ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
|
||||
@@ -784,7 +832,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
stat_t stat() override
|
||||
{
|
||||
struct ::stat file_info;
|
||||
verify("file::stat" HERE), ::fstat(m_fd, &file_info) == 0;
|
||||
if (::fstat(m_fd, &file_info) != 0)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
stat_t info;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -811,7 +862,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::read(m_fd, buffer, count);
|
||||
verify("file::read" HERE), result != -1;
|
||||
if (result == -1)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -819,7 +873,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::write(m_fd, buffer, count);
|
||||
verify("file::write" HERE), result != -1;
|
||||
if (result == -1)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -830,10 +887,13 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
whence == seek_set ? SEEK_SET :
|
||||
whence == seek_cur ? SEEK_CUR :
|
||||
whence == seek_end ? SEEK_END :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
|
||||
|
||||
const auto result = ::lseek(m_fd, offset, mode);
|
||||
verify("file::seek" HERE), result != -1;
|
||||
if (result == -1)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -841,7 +901,10 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 size() override
|
||||
{
|
||||
struct ::stat file_info;
|
||||
verify("file::size" HERE), ::fstat(m_fd, &file_info) == 0;
|
||||
if (::fstat(m_fd, &file_info) != 0)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
return file_info.st_size;
|
||||
}
|
||||
@@ -871,27 +934,26 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
|
||||
fs::stat_t stat() override
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Not supported" HERE);
|
||||
throw std::logic_error("Not supported" HERE);
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
|
||||
throw 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);
|
||||
if (end < start) fmt::throw_exception<std::logic_error>("Stream overflow" HERE);
|
||||
const u64 read_size = end - start;
|
||||
const u64 read_size = end >= start ? end - start : throw std::logic_error("Stream overflow" HERE);
|
||||
std::memcpy(buffer, m_ptr + start, read_size);
|
||||
return read_size;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("Not allowed" HERE);
|
||||
throw std::logic_error("Not allowed" HERE);
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, fs::seek_mode whence) override
|
||||
@@ -900,7 +962,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) :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
@@ -914,7 +976,7 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
|
||||
void fs::dir::xnull() const
|
||||
{
|
||||
fmt::throw_exception<std::logic_error>("fs::dir is null");
|
||||
throw std::logic_error("fs::dir is null");
|
||||
}
|
||||
|
||||
bool fs::dir::open(const std::string& path)
|
||||
@@ -932,7 +994,7 @@ bool fs::dir::open(const std::string& path)
|
||||
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATAW found;
|
||||
const auto handle = FindFirstFileExW(to_wchar(path + "/*").get(), FindExInfoBasic, &found, FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
||||
const auto handle = FindFirstFileW(to_wchar(path + "/*").get(), &found);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -942,6 +1004,8 @@ 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;
|
||||
|
||||
@@ -961,24 +1025,33 @@ bool fs::dir::open(const std::string& path)
|
||||
}
|
||||
|
||||
public:
|
||||
windows_dir(HANDLE handle, WIN32_FIND_DATAW& found)
|
||||
windows_dir(HANDLE handle, const WIN32_FIND_DATAW& found)
|
||||
: m_handle(handle)
|
||||
{
|
||||
add_entry(found);
|
||||
}
|
||||
|
||||
while (FindNextFileW(handle, &found))
|
||||
{
|
||||
add_entry(found);
|
||||
}
|
||||
|
||||
verify("dir::read" HERE), ERROR_NO_MORE_FILES == GetLastError();
|
||||
FindClose(handle);
|
||||
~windows_dir()
|
||||
{
|
||||
FindClose(m_handle);
|
||||
}
|
||||
|
||||
bool read(dir_entry& out) override
|
||||
{
|
||||
if (m_pos >= m_entries.size())
|
||||
if (m_pos == m_entries.size())
|
||||
{
|
||||
return false;
|
||||
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);
|
||||
}
|
||||
|
||||
out = m_entries[m_pos++];
|
||||
@@ -1025,7 +1098,10 @@ bool fs::dir::open(const std::string& path)
|
||||
}
|
||||
|
||||
struct ::stat file_info;
|
||||
verify("dir::read" HERE), ::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) == 0;
|
||||
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
|
||||
{
|
||||
throw fmt::exception("System error: %d." HERE, errno);
|
||||
}
|
||||
|
||||
info.name = found->d_name;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -1131,78 +1207,6 @@ 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))
|
||||
@@ -1253,37 +1257,3 @@ 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;
|
||||
});
|
||||
}
|
||||
|
||||
+15
-22
@@ -1,16 +1,17 @@
|
||||
#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 class open_mode : u32
|
||||
enum struct open_mode : u32
|
||||
{
|
||||
read,
|
||||
write,
|
||||
@@ -18,18 +19,16 @@ namespace fs
|
||||
create,
|
||||
trunc,
|
||||
excl,
|
||||
|
||||
__bitset_enum_max
|
||||
};
|
||||
|
||||
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> 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 rewrite = open_mode::write + open_mode::create + open_mode::trunc;
|
||||
constexpr bitset_t<open_mode> rewrite = write + create + trunc;
|
||||
|
||||
// File seek mode
|
||||
enum class seek_mode : u32
|
||||
@@ -94,7 +93,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, bs_t<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<file_base> open(const std::string& path, bitset_t<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
|
||||
};
|
||||
|
||||
@@ -152,13 +151,13 @@ namespace fs
|
||||
file() = default;
|
||||
|
||||
// Open file with specified mode
|
||||
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read)
|
||||
explicit file(const std::string& path, bitset_t<open_mode> mode = ::fs::read)
|
||||
{
|
||||
open(path, mode);
|
||||
}
|
||||
|
||||
// Open file with specified mode
|
||||
bool open(const std::string& path, bs_t<open_mode> mode = ::fs::read);
|
||||
bool open(const std::string& path, bitset_t<open_mode> mode = ::fs::read);
|
||||
|
||||
// Open memory for read
|
||||
explicit file(const void* ptr, std::size_t size);
|
||||
@@ -440,12 +439,6 @@ 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);
|
||||
|
||||
|
||||
+24
-41
@@ -7,6 +7,7 @@
|
||||
#include <array>
|
||||
|
||||
#include "types.h"
|
||||
#include "Macro.h"
|
||||
#include "StrFmt.h"
|
||||
#include "File.h"
|
||||
#include "Log.h"
|
||||
@@ -45,7 +46,7 @@ static const u64 s_memory_size = 0x20000000;
|
||||
static void* const s_memory = []() -> void*
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (u64 addr = 0x10000000; addr <= 0x60000000; addr += 0x1000000)
|
||||
for (u64 addr = 0x1000000; addr <= 0x60000000; addr += 0x1000000)
|
||||
{
|
||||
if (VirtualAlloc((void*)addr, s_memory_size, MEM_RESERVE, PAGE_NOACCESS))
|
||||
{
|
||||
@@ -59,10 +60,6 @@ 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;
|
||||
@@ -83,7 +80,7 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||
|
||||
[[noreturn]] static void null()
|
||||
{
|
||||
fmt::throw_exception("Null function" HERE);
|
||||
throw std::runtime_error("Null function" HERE);
|
||||
}
|
||||
|
||||
virtual u64 getSymbolAddress(const std::string& name) override
|
||||
@@ -124,14 +121,11 @@ 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 %p", m_next);
|
||||
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at 0x%p", m_next);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
return (u8*)std::exchange(m_next, (void*)next);
|
||||
}
|
||||
|
||||
@@ -146,36 +140,23 @@ 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 %p", m_next);
|
||||
LOG_FATAL(GENERAL, "LLVM: Failed to allocate memory at 0x%p", m_next);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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");
|
||||
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");
|
||||
return (u8*)std::exchange(m_next, (void*)next);
|
||||
}
|
||||
|
||||
virtual bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
// 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
|
||||
// TODO: make sections read-only when necessary
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -199,17 +180,17 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
|
||||
#ifdef _WIN32
|
||||
if (!RtlDeleteFunctionTable(s_unwind.data()))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
LOG_FATAL(GENERAL, "RtlDeleteFunctionTable(addr=0x%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
}
|
||||
|
||||
if (!VirtualFree(s_memory, 0, MEM_DECOMMIT))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "VirtualFree(%p) failed! Error %u", s_memory, GetLastError());
|
||||
LOG_FATAL(GENERAL, "VirtualFree(0x%p) failed! Error %u", s_memory, GetLastError());
|
||||
}
|
||||
#else
|
||||
if (::mprotect(s_memory, s_memory_size, PROT_NONE))
|
||||
{
|
||||
LOG_FATAL(GENERAL, "mprotect(%p) failed! Error %d", s_memory, errno);
|
||||
LOG_FATAL(GENERAL, "mprotect(0x%p) failed! Error %d", s_memory, errno);
|
||||
}
|
||||
|
||||
// TODO: unregister EH frames if necessary
|
||||
@@ -235,7 +216,7 @@ static EventListener s_listener;
|
||||
|
||||
jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unordered_map<std::string, std::uintptr_t>&& table)
|
||||
{
|
||||
verify(HERE), s_memory;
|
||||
EXPECTS(s_memory);
|
||||
|
||||
std::string result;
|
||||
|
||||
@@ -250,13 +231,14 @@ 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)
|
||||
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Small : llvm::CodeModel::Large) // TODO
|
||||
.setRelocationModel(llvm::Reloc::PIC_)
|
||||
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Medium : llvm::CodeModel::Large) // TODO
|
||||
.setMCPU(llvm::sys::getHostCPUName())
|
||||
.create());
|
||||
|
||||
if (!m_engine)
|
||||
{
|
||||
fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result);
|
||||
throw fmt::exception("LLVM: Failed to create ExecutionEngine: %s", result);
|
||||
}
|
||||
|
||||
m_engine->setProcessAllSections(true); // ???
|
||||
@@ -286,17 +268,19 @@ 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 (const u64 addr : func_set)
|
||||
for (auto it = func_set.begin(), end = --func_set.end(); it != end; it++)
|
||||
{
|
||||
// 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;
|
||||
const u64 addr = *it;
|
||||
const u64 next = *func_set.upper_bound(addr);
|
||||
|
||||
// Generate RUNTIME_FUNCTION record
|
||||
RUNTIME_FUNCTION uw;
|
||||
@@ -314,7 +298,6 @@ 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;
|
||||
}
|
||||
@@ -324,15 +307,15 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
|
||||
|
||||
if (s_unwind_info + s_unwind_size != bits)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "LLVM: .xdata analysis failed! (%p != %p)", 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);
|
||||
}
|
||||
else if (!RtlAddFunctionTable(s_unwind.data(), (DWORD)s_unwind.size(), base))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "RtlAddFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
LOG_FATAL(GENERAL, "RtlAddFunctionTable(addr=0x%p) failed! Error %u", s_unwind_info, GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (%p, size=0x%llx)", s_unwind_info, s_unwind_size);
|
||||
LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (addr=0x%p, size=0x%llx)", s_unwind_info, s_unwind_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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.
|
||||
+56
-78
@@ -2,35 +2,27 @@
|
||||
#include "File.h"
|
||||
#include "StrFmt.h"
|
||||
|
||||
#include "rpcs3_version.h"
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
|
||||
// Thread-specific log prefix provider
|
||||
thread_local std::string(*g_tls_log_prefix)() = nullptr;
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
constexpr DECLARE(bijective<logs::level, const char*>::map);
|
||||
#endif
|
||||
|
||||
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
|
||||
@@ -42,7 +34,10 @@ namespace logs
|
||||
virtual ~file_writer() = default;
|
||||
|
||||
// Append raw data
|
||||
void log(const char* text, std::size_t size);
|
||||
void log(const std::string& text);
|
||||
|
||||
// Get current file size (may be used by secondary readers)
|
||||
std::size_t size() const;
|
||||
};
|
||||
|
||||
struct file_listener : public file_writer, public listener
|
||||
@@ -51,19 +46,17 @@ 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 message& msg, const std::string& prefix, const std::string& text) override;
|
||||
virtual void log(const channel& ch, level sev, 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);
|
||||
@@ -76,32 +69,12 @@ namespace logs
|
||||
channel ARMv7("ARMv7");
|
||||
}
|
||||
|
||||
void logs::listener::add(logs::listener* _new)
|
||||
void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt...)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
get_logger().log(ch, sev, fmt::unsafe_vformat(fmt, args));
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
[[noreturn]] extern void catch_all_exceptions();
|
||||
@@ -112,7 +85,7 @@ logs::file_writer::file_writer(const std::string& name)
|
||||
{
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
|
||||
{
|
||||
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
|
||||
throw fmt::exception("Can't create log file %s (error %d)", name, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -121,49 +94,54 @@ logs::file_writer::file_writer(const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
void logs::file_writer::log(const char* text, std::size_t size)
|
||||
void logs::file_writer::log(const std::string& text)
|
||||
{
|
||||
m_file.write(text, size);
|
||||
m_file.write(text);
|
||||
}
|
||||
|
||||
void logs::file_listener::log(const logs::message& msg, const std::string& prefix, const std::string& _text)
|
||||
std::size_t logs::file_writer::size() const
|
||||
{
|
||||
std::string text; text.reserve(prefix.size() + _text.size() + 200);
|
||||
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);
|
||||
|
||||
// Used character: U+00B7 (Middle Dot)
|
||||
switch (msg.sev)
|
||||
switch (sev)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: print time?
|
||||
|
||||
if (prefix.size() > 0)
|
||||
if (auto prefix = g_tls_log_prefix)
|
||||
{
|
||||
text += "{";
|
||||
text += prefix;
|
||||
text += "} ";
|
||||
msg += '{';
|
||||
msg += prefix();
|
||||
msg += "} ";
|
||||
}
|
||||
|
||||
if (msg.ch->name)
|
||||
if (ch.name)
|
||||
{
|
||||
text += msg.ch->name;
|
||||
text += msg.sev == level::todo ? " TODO: " : ": ";
|
||||
msg += ch.name;
|
||||
msg += sev == level::todo ? " TODO: " : ": ";
|
||||
}
|
||||
else if (msg.sev == level::todo)
|
||||
else if (sev == level::todo)
|
||||
{
|
||||
text += "TODO: ";
|
||||
msg += "TODO: ";
|
||||
}
|
||||
|
||||
text += _text;
|
||||
text += '\n';
|
||||
msg += text;
|
||||
msg += '\n';
|
||||
|
||||
file_writer::log(text.data(), text.size());
|
||||
file_writer::log(msg);
|
||||
}
|
||||
|
||||
+35
-45
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
#include "StrFmt.h"
|
||||
|
||||
namespace logs
|
||||
{
|
||||
@@ -18,37 +17,6 @@ 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)
|
||||
@@ -66,17 +34,19 @@ namespace logs
|
||||
|
||||
// Formatting function
|
||||
template<typename... Args>
|
||||
SAFE_BUFFERS FORCE_INLINE void format(level sev, const char* fmt, const Args&... args) const
|
||||
void format(level sev, const char* fmt, const Args&... args) const
|
||||
{
|
||||
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)...});
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
if (sev <= enabled)
|
||||
#else
|
||||
if (__builtin_expect(sev <= enabled, 0))
|
||||
#endif
|
||||
broadcast(*this, sev, fmt, ::unveil<Args>::get(args)...);
|
||||
}
|
||||
|
||||
#define GEN_LOG_METHOD(_sev)\
|
||||
template<typename... Args>\
|
||||
SAFE_BUFFERS void _sev(const char* fmt, const Args&... args) const\
|
||||
void _sev(const char* fmt, const Args&... args) const\
|
||||
{\
|
||||
return format<Args...>(level::_sev, fmt, args...);\
|
||||
}
|
||||
@@ -90,6 +60,10 @@ 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 */
|
||||
@@ -104,12 +78,28 @@ 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__)
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
Show();
|
||||
}
|
||||
|
||||
void Update(const u8 thread_id, const u64 value, const wxString& msg)
|
||||
force_inline void Update(const u8 thread_id, const u64 value, const wxString& msg)
|
||||
{
|
||||
if(thread_id > m_cores) return;
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#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
|
||||
@@ -0,0 +1,51 @@
|
||||
#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__ */
|
||||
@@ -0,0 +1,122 @@
|
||||
#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
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "Atomic.h"
|
||||
#include "Platform.h"
|
||||
|
||||
// Binary semaphore
|
||||
class benaphore
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#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.
|
||||
|
||||
@@ -9,8 +9,10 @@ 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>
|
||||
template<typename T, void(T::*Sleep)() = &T::sleep, void(T::*Awake)() = &T::awake>
|
||||
class sleep_entry final
|
||||
{
|
||||
sleep_queue<T>& m_queue;
|
||||
@@ -22,6 +24,7 @@ public:
|
||||
: m_queue(queue)
|
||||
, m_thread(entry)
|
||||
{
|
||||
if (Sleep) (m_thread.*Sleep)();
|
||||
}
|
||||
|
||||
// Constructor; calls enter()
|
||||
@@ -35,6 +38,7 @@ public:
|
||||
~sleep_entry()
|
||||
{
|
||||
leave();
|
||||
if (Awake) (m_thread.*Awake)();
|
||||
}
|
||||
|
||||
// Add thread to the sleep queue
|
||||
|
||||
+56
-267
@@ -1,284 +1,73 @@
|
||||
#include "StrFmt.h"
|
||||
#include "BEType.h"
|
||||
#include "StrUtil.h"
|
||||
#include "cfmt.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
std::string v128::to_hex() const
|
||||
{
|
||||
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();;)
|
||||
{
|
||||
va_list args;
|
||||
va_copy(args, _args);
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||
#endif
|
||||
|
||||
void fmt_class_string<const void*>::format(std::string& out, u64 arg)
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
|
||||
}
|
||||
else
|
||||
{
|
||||
out += "(NULL)";
|
||||
}
|
||||
}
|
||||
|
||||
void fmt_class_string<const char*>::format(std::string& out, u64 arg)
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
out += reinterpret_cast<const char*>(static_cast<std::uintptr_t>(arg));
|
||||
}
|
||||
else
|
||||
{
|
||||
out += "(NULL)";
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<std::string>::format(std::string& out, u64 arg)
|
||||
{
|
||||
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);
|
||||
}
|
||||
const std::size_t len = std::vsnprintf(buf_addr, buf_size, fmt, args);
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
va_end(args);
|
||||
|
||||
if (sup)
|
||||
assert(len <= INT_MAX);
|
||||
|
||||
if (len < buf_size)
|
||||
{
|
||||
out += " (";
|
||||
sup->fmt_string(out, arg); // Print value
|
||||
out += ")";
|
||||
return{ buf_addr, len };
|
||||
}
|
||||
|
||||
if (msg)
|
||||
{
|
||||
out += ": ";
|
||||
out += msg;
|
||||
}
|
||||
|
||||
throw std::runtime_error{out};
|
||||
buf.reset(buf_addr = new char[buf_size = len + 1]);
|
||||
}
|
||||
|
||||
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
|
||||
std::string fmt::unsafe_format(const char* fmt...) noexcept
|
||||
{
|
||||
const fmt_type_info* sup;
|
||||
const u64* args;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
auto result = unsafe_vformat(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
bool test(std::size_t index) const
|
||||
{
|
||||
if (!sup[index].fmt_string)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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
|
||||
fmt::exception_base::exception_base(const char* fmt...)
|
||||
: std::runtime_error((va_start(m_args, fmt), unsafe_vformat(fmt, m_args)))
|
||||
{
|
||||
cfmt_append(out, fmt, cfmt_src{sup, args});
|
||||
va_end(m_args);
|
||||
}
|
||||
|
||||
std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to)
|
||||
@@ -293,7 +82,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))
|
||||
@@ -313,7 +102,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)
|
||||
{
|
||||
@@ -322,7 +111,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;
|
||||
}
|
||||
}
|
||||
@@ -341,7 +130,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);
|
||||
}
|
||||
@@ -354,7 +143,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;
|
||||
|
||||
|
||||
+31
-239
@@ -1,260 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
template <typename... Args>
|
||||
static std::string format(const char*, const Args&...);
|
||||
}
|
||||
std::string unsafe_format(const char* fmt...) noexcept;
|
||||
std::string unsafe_vformat(const char*, va_list) noexcept;
|
||||
|
||||
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)
|
||||
// Formatting function
|
||||
template<typename... Args>
|
||||
inline std::string format(const char* fmt, const Args&... args)
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(&arg);
|
||||
return unsafe_format(fmt, ::unveil<Args>::get(args)...);
|
||||
}
|
||||
|
||||
// Temporary value container (can possibly be created by other fmt_unveil<> specializations)
|
||||
struct u64_wrapper
|
||||
// Helper class
|
||||
class exception_base : public std::runtime_error
|
||||
{
|
||||
T arg;
|
||||
// Helper (there is no other room)
|
||||
va_list m_args;
|
||||
|
||||
// Allow implicit conversion
|
||||
operator u64() const
|
||||
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)...)
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(&arg);
|
||||
}
|
||||
};
|
||||
|
||||
// This overload resolution takes the precedence
|
||||
static inline u64_wrapper get(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>())))
|
||||
{
|
||||
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>()...};
|
||||
|
||||
const auto result = static_cast<To>(value);
|
||||
if (static_cast<From>(result) != value) throw fmt::exception(format_str, value, 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
@@ -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);
|
||||
}
|
||||
|
||||
+50
-337
@@ -6,14 +6,12 @@
|
||||
#include "Thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <Psapi.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#define _XOPEN_SOURCE
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
@@ -21,7 +19,11 @@
|
||||
static void report_fatal_error(const std::string& msg)
|
||||
{
|
||||
std::string _msg = msg + "\n"
|
||||
"HOW TO REPORT ERRORS: Check the FAQ, README, other sources.\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"
|
||||
"Please, don't send incorrect reports. Thanks for understanding.\n";
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -588,57 +590,6 @@ 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
|
||||
@@ -860,7 +811,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)", (u32)reg, d_size, i_size);
|
||||
LOG_ERROR(MEMORY, "get_x64_reg_value(): invalid arguments (reg=%d, d_size=%lld, i_size=%lld)", reg, d_size, i_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -879,7 +830,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)", (u32)reg, d_size, value);
|
||||
LOG_ERROR(MEMORY, "put_x64_reg_value(): invalid destination (reg=%d, d_size=%lld, value=0x%llx)", reg, d_size, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1026,7 +977,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
||||
{
|
||||
if (op == X64OP_NONE)
|
||||
{
|
||||
LOG_ERROR(MEMORY, "decode_x64_reg_op(%p): unsupported opcode: %s", code, *(be_t<v128, 1>*)code);
|
||||
LOG_ERROR(MEMORY, "decode_x64_reg_op(%016llxh): unsupported opcode found (%016llX%016llX)", code, *(be_t<u64>*)(code), *(be_t<u64>*)(code + 8));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1059,7 +1010,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)", (u32)op, (u32)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)", op, reg, d_size, a_size, i_size);
|
||||
report_opcode();
|
||||
return false;
|
||||
}
|
||||
@@ -1131,7 +1082,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)", (u32)op, (u32)reg, d_size, i_size);
|
||||
LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", op, reg, d_size, i_size);
|
||||
report_opcode();
|
||||
return false;
|
||||
}
|
||||
@@ -1148,7 +1099,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)", (u32)op, (u32)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)", op, reg, d_size, a_size, i_size);
|
||||
report_opcode();
|
||||
return false;
|
||||
}
|
||||
@@ -1162,7 +1113,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", (u32)reg);
|
||||
LOG_ERROR(MEMORY, "X64OP_STORE: d_size=16, reg=%d", reg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1574,7 +1525,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)", (u32)op, (u32)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)", op, reg, d_size, a_size, i_size);
|
||||
report_opcode();
|
||||
return false;
|
||||
}
|
||||
@@ -1588,34 +1539,8 @@ 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();
|
||||
}
|
||||
@@ -1628,13 +1553,10 @@ 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)
|
||||
s_tls_ret_addr = RIP(context);
|
||||
s_tls_ret_pos = is_leaf_function(s_tls_ret_addr) ? 0 : RSP(context) -= sizeof(u64);
|
||||
*--(u64*&)(RSP(context)) = RIP(context);
|
||||
RIP(context) = (u64)std::addressof(throw_access_violation);
|
||||
}
|
||||
|
||||
static void _handle_interrupt(x64_context* ctx);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static LONG exception_handler(PEXCEPTION_POINTERS pExp)
|
||||
@@ -1672,7 +1594,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
msg += fmt::format("Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
|
||||
msg += fmt::format("Access violation %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1684,58 +1606,8 @@ 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);
|
||||
|
||||
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));
|
||||
msg += fmt::format("Image base: %p.\n", GetModuleHandle(NULL));
|
||||
|
||||
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
|
||||
{
|
||||
@@ -1774,11 +1646,6 @@ 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
|
||||
@@ -1802,7 +1669,7 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
else
|
||||
{
|
||||
// TODO (debugger interaction)
|
||||
report_fatal_error(fmt::format("Segfault %s location %p at %p.", cause, info->si_addr, RIP(context)));
|
||||
report_fatal_error(fmt::format("Access violation %s location %p at %p.", cause, info->si_addr, RIP(context)));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
@@ -1816,15 +1683,7 @@ const bool s_exception_handler_set = []() -> bool
|
||||
|
||||
if (::sigaction(SIGSEGV, &sa, NULL) == -1)
|
||||
{
|
||||
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::printf("sigaction() failed (0x%x).", errno);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
@@ -1856,27 +1715,22 @@ struct thread_ctrl::internal
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::condition_variable cond;
|
||||
std::condition_variable jcv; // Allows simultaneous joining
|
||||
std::condition_variable icv;
|
||||
std::condition_variable join; // Allows simultaneous joining
|
||||
|
||||
task_stack atexit;
|
||||
|
||||
std::exception_ptr exception; // Stored exception
|
||||
std::exception_ptr exception; // Caught 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;
|
||||
@@ -1898,6 +1752,7 @@ 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();
|
||||
}
|
||||
|
||||
@@ -1907,11 +1762,15 @@ 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)
|
||||
@@ -1935,12 +1794,11 @@ 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 = []
|
||||
{
|
||||
@@ -1982,10 +1840,6 @@ void thread_ctrl::initialize()
|
||||
|
||||
void thread_ctrl::finalize() noexcept
|
||||
{
|
||||
// Disable and discard possible interrupts
|
||||
interrupt_disable();
|
||||
test_interrupt();
|
||||
|
||||
// TODO
|
||||
vm::reservation_free();
|
||||
|
||||
@@ -2003,6 +1857,7 @@ void thread_ctrl::finalize() noexcept
|
||||
|
||||
void thread_ctrl::push_atexit(task_stack task)
|
||||
{
|
||||
initialize_once();
|
||||
m_data->atexit.push(std::move(task));
|
||||
}
|
||||
|
||||
@@ -2015,8 +1870,6 @@ thread_ctrl::thread_ctrl(std::string&& name)
|
||||
#undef new
|
||||
new (&m_thread) std::thread;
|
||||
#pragma pop_macro("new")
|
||||
|
||||
initialize_once();
|
||||
}
|
||||
|
||||
thread_ctrl::~thread_ctrl()
|
||||
@@ -2062,20 +1915,24 @@ 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->jcv.notify_all();
|
||||
m_data->join.notify_all();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hard way
|
||||
initialize_once();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_data->mutex);
|
||||
m_data->jcv.wait(lock, [&] { return m_joining >= 0x80000000; });
|
||||
m_data->join.wait(lock, WRAP_EXPR(m_joining >= 0x80000000));
|
||||
}
|
||||
|
||||
if (UNLIKELY(m_data && m_data->exception && !std::uncaught_exception()))
|
||||
if (UNLIKELY(m_data && m_data->exception))
|
||||
{
|
||||
std::rethrow_exception(m_data->exception);
|
||||
}
|
||||
@@ -2083,6 +1940,7 @@ void thread_ctrl::join()
|
||||
|
||||
void thread_ctrl::lock()
|
||||
{
|
||||
initialize_once();
|
||||
m_data->mutex.lock();
|
||||
}
|
||||
|
||||
@@ -2098,6 +1956,8 @@ 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();
|
||||
@@ -2114,153 +1974,6 @@ 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));
|
||||
@@ -2280,18 +1993,18 @@ std::string named_thread::get_name() const
|
||||
return fmt::format("('%s') Unnamed Thread", typeid(*this).name());
|
||||
}
|
||||
|
||||
void named_thread::start_thread(const std::shared_ptr<void>& _this)
|
||||
void named_thread::start()
|
||||
{
|
||||
// Ensure it's not called from the constructor and the correct object is passed
|
||||
verify("named_thread::start_thread" HERE), _this.get() == this;
|
||||
// Get shared_ptr instance (will throw if called from the constructor or the object has been created incorrectly)
|
||||
auto&& ptr = shared_from_this();
|
||||
|
||||
// Run thread
|
||||
thread_ctrl::spawn(m_thread, get_name(), [this, _this]()
|
||||
m_thread = thread_ctrl::spawn(get_name(), [thread = std::move(ptr)]()
|
||||
{
|
||||
try
|
||||
{
|
||||
LOG_TRACE(GENERAL, "Thread started");
|
||||
on_task();
|
||||
thread->on_task();
|
||||
LOG_TRACE(GENERAL, "Thread ended");
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
@@ -2304,6 +2017,6 @@ void named_thread::start_thread(const std::shared_ptr<void>& _this)
|
||||
LOG_NOTICE(GENERAL, "Thread aborted");
|
||||
}
|
||||
|
||||
on_exit();
|
||||
thread->on_exit();
|
||||
});
|
||||
}
|
||||
|
||||
+17
-147
@@ -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,9 +94,6 @@ 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{};
|
||||
|
||||
@@ -190,42 +187,6 @@ 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);
|
||||
@@ -233,12 +194,9 @@ public:
|
||||
// Wait until pred(). Abortable, may throw. Thread must be locked.
|
||||
// Timeout in microseconds (zero means infinite).
|
||||
template<typename F>
|
||||
static inline auto wait_for(u64 useconds, F&& pred)
|
||||
static inline auto wait(u64 useconds, F&& pred)
|
||||
{
|
||||
if (useconds)
|
||||
{
|
||||
g_tls_this_thread->wait_start(useconds);
|
||||
}
|
||||
g_tls_this_thread->wait_start(useconds);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -255,26 +213,6 @@ 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)
|
||||
@@ -292,7 +230,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Wait once. Abortable, may throw. Thread must be locked.
|
||||
// Wait once. Thread must be locked.
|
||||
static inline void wait()
|
||||
{
|
||||
g_tls_this_thread->test();
|
||||
@@ -300,7 +238,7 @@ public:
|
||||
g_tls_this_thread->test();
|
||||
}
|
||||
|
||||
// Wait eternally. Abortable, may throw. Thread must be locked.
|
||||
// Wait unconditionally until aborted. Thread must be locked.
|
||||
[[noreturn]] static inline void eternalize()
|
||||
{
|
||||
while (true)
|
||||
@@ -325,24 +263,17 @@ public:
|
||||
|
||||
// Named thread factory
|
||||
template<typename N, typename F>
|
||||
static inline void spawn(N&& name, F&& func)
|
||||
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func)
|
||||
{
|
||||
auto&& out = std::make_shared<thread_ctrl>(std::forward<N>(name));
|
||||
auto ctrl = std::make_shared<thread_ctrl>(std::forward<N>(name));
|
||||
|
||||
thread_ctrl::start(out, std::forward<F>(func));
|
||||
}
|
||||
thread_ctrl::start(ctrl, std::forward<F>(func));
|
||||
|
||||
// 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));
|
||||
return ctrl;
|
||||
}
|
||||
};
|
||||
|
||||
class named_thread
|
||||
class named_thread : public std::enable_shared_from_this<named_thread>
|
||||
{
|
||||
// Pointer to managed resource (shared with actual thread)
|
||||
std::shared_ptr<thread_ctrl> m_thread;
|
||||
@@ -359,8 +290,8 @@ public:
|
||||
virtual std::string get_name() const;
|
||||
|
||||
protected:
|
||||
// Start thread (cannot be called from the constructor: should throw in such case)
|
||||
void start_thread(const std::shared_ptr<void>& _this);
|
||||
// Start thread (cannot be called from the constructor: should throw bad_weak_ptr in such case)
|
||||
void start();
|
||||
|
||||
// Thread task (called in the thread)
|
||||
virtual void on_task() = 0;
|
||||
@@ -370,9 +301,9 @@ protected:
|
||||
|
||||
public:
|
||||
// ID initialization
|
||||
virtual void on_init(const std::shared_ptr<void>& _this)
|
||||
virtual void on_init()
|
||||
{
|
||||
return start_thread(_this);
|
||||
start();
|
||||
}
|
||||
|
||||
// ID finalization
|
||||
@@ -386,31 +317,6 @@ 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
|
||||
@@ -446,36 +352,6 @@ 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
|
||||
{
|
||||
@@ -484,8 +360,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
|
||||
@@ -496,10 +372,4 @@ public:
|
||||
{
|
||||
m_thread->join();
|
||||
}
|
||||
|
||||
// Access thread_ctrl
|
||||
thread_ctrl* operator->() const
|
||||
{
|
||||
return m_thread.get();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,27 +16,30 @@ namespace memory_helper
|
||||
void* reserve_memory(size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return verify("reserve_memory" HERE, VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS));
|
||||
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
ENSURES(ret != NULL);
|
||||
#else
|
||||
return verify("reserve_memory" HERE, ::mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0));
|
||||
void* ret = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
ENSURES(ret != 0);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void commit_page_memory(void* pointer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), VirtualAlloc(pointer, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
VERIFY(VirtualAlloc(pointer, size, MEM_COMMIT, PAGE_READWRITE) != NULL);
|
||||
#else
|
||||
verify(HERE), ::mprotect((void*)((u64)pointer & -4096), size, PROT_READ | PROT_WRITE) != -1;
|
||||
VERIFY(mprotect((void*)((u64)pointer & -4096), size, PROT_READ | PROT_WRITE) != -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_reserved_memory(void* pointer, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), VirtualFree(pointer, 0, MEM_DECOMMIT);
|
||||
VERIFY(VirtualFree(pointer, 0, MEM_DECOMMIT) != 0);
|
||||
#else
|
||||
verify(HERE), ::mprotect(pointer, size, PROT_NONE) != -1;
|
||||
VERIFY(mprotect(pointer, size, PROT_NONE) != -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,732 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,614 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
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
|
||||
+1
-43
@@ -2,6 +2,7 @@
|
||||
|
||||
#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.
|
||||
@@ -102,46 +103,3 @@ 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
@@ -1,124 +0,0 @@
|
||||
#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
|
||||
@@ -3,6 +3,7 @@
|
||||
/* For internal use. Don't include. */
|
||||
|
||||
#include "types.h"
|
||||
#include "Macro.h"
|
||||
#include "Atomic.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
+165
-556
File diff suppressed because it is too large
Load Diff
@@ -1,973 +0,0 @@
|
||||
#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
|
||||
+17
-3
@@ -14,12 +14,26 @@ namespace utils
|
||||
case version_type::release: return "Release";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
throw;
|
||||
}
|
||||
|
||||
uint version::to_hex() const
|
||||
version::version(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo)
|
||||
: m_hi(hi)
|
||||
, m_mid(mid)
|
||||
, m_lo(lo)
|
||||
{
|
||||
return (m_hi << 24) | (m_mid << 16) | (m_lo << 8) | ((uint(m_type) & 0xf) << 4) | (m_type_index & 0xf);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string version::to_string() const
|
||||
|
||||
+21
-22
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
enum class version_type : uint
|
||||
enum class version_type : std::uint8_t
|
||||
{
|
||||
pre_alpha,
|
||||
alpha,
|
||||
@@ -18,35 +17,29 @@ namespace utils
|
||||
|
||||
class version
|
||||
{
|
||||
uint m_hi;
|
||||
uint m_mid;
|
||||
uint m_lo;
|
||||
std::uint8_t m_hi;
|
||||
std::uint8_t m_mid;
|
||||
std::uint8_t m_lo;
|
||||
version_type m_type = version_type::release;
|
||||
uint m_type_index = 1;
|
||||
const char* m_postfix;
|
||||
std::uint8_t m_type_index = 1;
|
||||
std::string m_postfix;
|
||||
|
||||
public:
|
||||
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(std::uint8_t hi, std::uint8_t mid, std::uint8_t lo = 0);
|
||||
|
||||
uint hi() const
|
||||
version& type(version_type type, std::uint8_t type_index = 1);
|
||||
|
||||
std::uint8_t hi() const
|
||||
{
|
||||
return m_hi;
|
||||
}
|
||||
|
||||
uint mid() const
|
||||
std::uint8_t mid() const
|
||||
{
|
||||
return m_mid;
|
||||
}
|
||||
|
||||
uint lo() const
|
||||
std::uint8_t lo() const
|
||||
{
|
||||
return m_lo;
|
||||
}
|
||||
@@ -61,12 +54,18 @@ namespace utils
|
||||
return m_postfix;
|
||||
}
|
||||
|
||||
uint type_index() const
|
||||
version& postfix(const std::string& value)
|
||||
{
|
||||
m_postfix = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::uint8_t type_index() const
|
||||
{
|
||||
return m_type_index;
|
||||
}
|
||||
|
||||
uint to_hex() const;
|
||||
std::uint16_t to_hex() const;
|
||||
std::string to_string() const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
if(WIN32 AND NOT VULKAN_PREBUILT)
|
||||
if(APPLE)
|
||||
else()
|
||||
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 )
|
||||
|
||||
Submodule Vulkan/Vulkan-LoaderAndValidationLayers updated: 1f321cf93d...1affe90f0e
@@ -39,20 +39,23 @@
|
||||
</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 -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
|
||||
<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
|
||||
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 -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<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=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 -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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
+1
-1
Submodule Vulkan/glslang updated: f042e407a9...3c5b1e6b31
+7
-7
@@ -9,21 +9,21 @@ clone_depth: 3
|
||||
test: off
|
||||
|
||||
before_build:
|
||||
- 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
|
||||
# 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
|
||||
- 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/ -DVULKAN_PREBUILT=ON)
|
||||
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/)
|
||||
|
||||
build_script:
|
||||
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
install:
|
||||
- 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
|
||||
- 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'
|
||||
- set WXWIN=C:\rpcs3\wxWidgets
|
||||
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
|
||||
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;C:\wxWidgets;%PATH%
|
||||
|
||||
@@ -1,485 +0,0 @@
|
||||
#!/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: 69e5622092...051e787f26
@@ -1,10 +0,0 @@
|
||||
#!/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
|
||||
+20
-6
@@ -12,8 +12,21 @@ 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)
|
||||
|
||||
# Check for a sufficient compiler and set build options
|
||||
include(ConfigureCompiler)
|
||||
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()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DUNICODE)
|
||||
@@ -135,7 +148,6 @@ ${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
|
||||
@@ -159,7 +171,6 @@ endif()
|
||||
|
||||
link_directories(
|
||||
"${RPCS3_SRC_DIR}/../3rdparty/minidx12/"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan"
|
||||
)
|
||||
|
||||
if(NOT USE_SYSTEM_FFMPEG)
|
||||
@@ -183,7 +194,7 @@ RPCS3_SRC
|
||||
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit/*.cpp"
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
if(APPLE)
|
||||
set (EXCLUDE_DIR "/RSX/VK/")
|
||||
foreach (TMP_PATH ${RPCS3_SRC})
|
||||
string (FIND ${TMP_PATH} ${EXCLUDE_DIR} EXCLUDE_DIR_FOUND)
|
||||
@@ -201,7 +212,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 HLSL)
|
||||
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV)
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} opengl32.lib glu32.lib libpthread)
|
||||
else()
|
||||
@@ -222,6 +233,9 @@ 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
@@ -7,86 +7,86 @@
|
||||
// TODO: Still reliant on wxWidgets for zlib functions. Alternative solutions?
|
||||
#include <zlib.h>
|
||||
|
||||
inline u8 Read8(const fs::file& f)
|
||||
force_inline u8 Read8(const fs::file& f)
|
||||
{
|
||||
u8 ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u16 Read16(const fs::file& f)
|
||||
force_inline u16 Read16(const fs::file& f)
|
||||
{
|
||||
be_t<u16> ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u32 Read32(const fs::file& f)
|
||||
force_inline u32 Read32(const fs::file& f)
|
||||
{
|
||||
be_t<u32> ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u64 Read64(const fs::file& f)
|
||||
force_inline u64 Read64(const fs::file& f)
|
||||
{
|
||||
be_t<u64> ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u16 Read16LE(const fs::file& f)
|
||||
force_inline u16 Read16LE(const fs::file& f)
|
||||
{
|
||||
u16 ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u32 Read32LE(const fs::file& f)
|
||||
force_inline u32 Read32LE(const fs::file& f)
|
||||
{
|
||||
u32 ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u64 Read64LE(const fs::file& f)
|
||||
force_inline u64 Read64LE(const fs::file& f)
|
||||
{
|
||||
u64 ret;
|
||||
f.read(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void Write8(const fs::file& f, const u8 data)
|
||||
force_inline void Write8(const fs::file& f, const u8 data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write16LE(const fs::file& f, const u16 data)
|
||||
force_inline void Write16LE(const fs::file& f, const u16 data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write32LE(const fs::file& f, const u32 data)
|
||||
force_inline void Write32LE(const fs::file& f, const u32 data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write64LE(const fs::file& f, const u64 data)
|
||||
force_inline void Write64LE(const fs::file& f, const u64 data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write16(const fs::file& f, const be_t<u16> data)
|
||||
force_inline void Write16(const fs::file& f, const be_t<u16> data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write32(const fs::file& f, const be_t<u32> data)
|
||||
force_inline void Write32(const fs::file& f, const be_t<u32> data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
inline void Write64(const fs::file& f, const be_t<u64> data)
|
||||
force_inline void Write64(const fs::file& f, const be_t<u64> data)
|
||||
{
|
||||
f.write(&data, sizeof(data));
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ void AudioDumper::WriteData(const void* buffer, u32 size)
|
||||
{
|
||||
if (GetCh())
|
||||
{
|
||||
verify(HERE), size, m_output.write(buffer, size) == size;
|
||||
VERIFY(m_output.write(buffer, size) == size);
|
||||
m_header.Size += size;
|
||||
m_header.RIFF.Size += size;
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
#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
|
||||
@@ -1,164 +0,0 @@
|
||||
#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
|
||||
@@ -1,98 +1,148 @@
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Utilities/Log.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Utilities/Config.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "XAudio2Thread.h"
|
||||
#include <Windows.h>
|
||||
|
||||
extern cfg::bool_entry g_cfg_audio_convert_to_u16;
|
||||
|
||||
XAudio2Thread::XAudio2Thread()
|
||||
: m_xaudio2_instance(nullptr)
|
||||
, m_master_voice(nullptr)
|
||||
, m_source_voice(nullptr)
|
||||
{
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
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");
|
||||
LOG_ERROR(GENERAL, "XAudio2Thread : CoInitializeEx() failed(0x%08x)", (u32)hr);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto lib2_7 = LoadLibraryExW(L"XAudio2_7.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))
|
||||
hr = XAudio2Create(&m_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
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");
|
||||
LOG_ERROR(GENERAL, "XAudio2Thread : XAudio2Create() failed(0x%08x)", (u32)hr);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
fmt::throw_exception("No supported XAudio2 library found");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
XAudio2Thread::~XAudio2Thread()
|
||||
{
|
||||
m_funcs.destroy();
|
||||
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();
|
||||
}
|
||||
|
||||
void XAudio2Thread::Play()
|
||||
{
|
||||
m_funcs.play();
|
||||
HRESULT hr = m_source_voice->Start();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "XAudio2Thread : Start() failed(0x%08x)", (u32)hr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void XAudio2Thread::Close()
|
||||
{
|
||||
m_funcs.stop();
|
||||
m_funcs.flush();
|
||||
Stop();
|
||||
HRESULT hr = m_source_voice->FlushSourceBuffers();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "XAudio2Thread : FlushSourceBuffers() failed(0x%08x)", (u32)hr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void XAudio2Thread::Stop()
|
||||
{
|
||||
m_funcs.stop();
|
||||
HRESULT hr = m_source_voice->Stop();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "XAudio2Thread : Stop() failed(0x%08x)", (u32)hr);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
void XAudio2Thread::Open(const void* src, int size)
|
||||
{
|
||||
m_funcs.open();
|
||||
m_funcs.add(src, size);
|
||||
m_funcs.play();
|
||||
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();
|
||||
}
|
||||
|
||||
void XAudio2Thread::AddData(const void* src, int size)
|
||||
{
|
||||
m_funcs.add(src, 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();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,35 +4,13 @@
|
||||
|
||||
#include "Emu/Audio/AudioThread.h"
|
||||
|
||||
#include "3rdparty/XAudio2_7/XAudio2.h"
|
||||
|
||||
class XAudio2Thread : public AudioThread
|
||||
{
|
||||
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);
|
||||
IXAudio2* m_xaudio2_instance;
|
||||
IXAudio2MasteringVoice* m_master_voice;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
|
||||
public:
|
||||
XAudio2Thread();
|
||||
|
||||
+29
-65
@@ -3,55 +3,30 @@
|
||||
#include "CPUThread.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
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);
|
||||
}
|
||||
#include <condition_variable>
|
||||
|
||||
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_flag::exit;
|
||||
state -= cpu_state::exit;
|
||||
|
||||
g_tls_current_cpu_thread = this;
|
||||
|
||||
Emu.SendDbgCommand(DID_CREATE_THREAD, this);
|
||||
|
||||
std::unique_lock<named_thread> lock(*this);
|
||||
std::unique_lock<std::mutex> lock(get_current_thread_mutex());
|
||||
|
||||
// Check thread status
|
||||
while (!test(state & cpu_flag::exit))
|
||||
while (!(state & cpu_state::exit))
|
||||
{
|
||||
CHECK_EMU_STATUS;
|
||||
|
||||
// check stop status
|
||||
if (!test(state & cpu_flag::stop))
|
||||
if (!(state & cpu_state::stop))
|
||||
{
|
||||
if (lock) lock.unlock();
|
||||
|
||||
@@ -59,7 +34,7 @@ void cpu_thread::on_task()
|
||||
{
|
||||
cpu_task();
|
||||
}
|
||||
catch (cpu_flag _s)
|
||||
catch (cpu_state _s)
|
||||
{
|
||||
state += _s;
|
||||
}
|
||||
@@ -69,7 +44,7 @@ void cpu_thread::on_task()
|
||||
throw;
|
||||
}
|
||||
|
||||
state -= cpu_flag::ret;
|
||||
state -= cpu_state::ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -79,38 +54,39 @@ void cpu_thread::on_task()
|
||||
continue;
|
||||
}
|
||||
|
||||
thread_ctrl::wait();
|
||||
get_current_thread_cv().wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_thread::on_stop()
|
||||
{
|
||||
state += cpu_flag::exit;
|
||||
lock_notify();
|
||||
state += cpu_state::exit;
|
||||
(*this)->lock_notify();
|
||||
}
|
||||
|
||||
cpu_thread::~cpu_thread()
|
||||
{
|
||||
}
|
||||
|
||||
cpu_thread::cpu_thread()
|
||||
cpu_thread::cpu_thread(cpu_type type)
|
||||
: type(type)
|
||||
{
|
||||
}
|
||||
|
||||
bool cpu_thread::check_state()
|
||||
bool cpu_thread::check_status()
|
||||
{
|
||||
std::unique_lock<named_thread> lock(*this, std::defer_lock);
|
||||
std::unique_lock<std::mutex> lock(get_current_thread_mutex(), std::defer_lock);
|
||||
|
||||
while (true)
|
||||
{
|
||||
CHECK_EMU_STATUS; // check at least once
|
||||
|
||||
if (test(state & cpu_flag::exit))
|
||||
if (state & cpu_state::exit)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!test(state & cpu_state_pause))
|
||||
if (!state.test(cpu_state_pause) && !state.test(cpu_state::interrupt))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -121,38 +97,26 @@ bool cpu_thread::check_state()
|
||||
continue;
|
||||
}
|
||||
|
||||
thread_ctrl::wait();
|
||||
if (!state.test(cpu_state_pause) && state & cpu_state::interrupt && handle_interrupt())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
get_current_thread_cv().wait(lock);
|
||||
}
|
||||
|
||||
const auto state_ = state.load();
|
||||
|
||||
if (test(state_, cpu_flag::ret + cpu_flag::stop))
|
||||
if (state_ & make_bitset(cpu_state::ret, cpu_state::stop))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (test(state_, cpu_flag::dbg_step))
|
||||
if (state_ & cpu_state::dbg_step)
|
||||
{
|
||||
state += cpu_flag::dbg_pause;
|
||||
state -= cpu_flag::dbg_step;
|
||||
state += cpu_state::dbg_pause;
|
||||
state -= cpu_state::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());
|
||||
}
|
||||
|
||||
+59
-18
@@ -1,60 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utilities/Thread.h"
|
||||
#include "../Utilities/bit_set.h"
|
||||
#include "../Utilities/BitSet.h"
|
||||
|
||||
// Thread state flags
|
||||
enum class cpu_flag : u32
|
||||
// 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
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
|
||||
class cpu_thread : public named_thread
|
||||
{
|
||||
void on_task() override final;
|
||||
void on_task() override;
|
||||
|
||||
public:
|
||||
virtual void on_stop() override;
|
||||
virtual ~cpu_thread() override;
|
||||
|
||||
const id_value<> id{};
|
||||
const cpu_type type;
|
||||
|
||||
cpu_thread();
|
||||
cpu_thread(cpu_type type);
|
||||
|
||||
// Public recursive sleep state counter
|
||||
atomic_t<u8> sleep_counter{};
|
||||
|
||||
// Public thread state
|
||||
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
|
||||
atomic_t<bitset_t<cpu_state>> state{ cpu_state::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_state();
|
||||
bool check_status();
|
||||
|
||||
// Run thread
|
||||
void run();
|
||||
// Increse sleep counter
|
||||
void sleep()
|
||||
{
|
||||
if (!sleep_counter++) return; //handle_interrupt();
|
||||
}
|
||||
|
||||
// Set cpu_flag::signal
|
||||
void set_signal();
|
||||
// Decrese sleep counter
|
||||
void awake()
|
||||
{
|
||||
if (!--sleep_counter) owner = nullptr;
|
||||
}
|
||||
|
||||
// Print CPU state
|
||||
virtual std::string dump() const;
|
||||
|
||||
// Thread entry point function
|
||||
virtual std::string dump() const = 0;
|
||||
virtual void cpu_init() {}
|
||||
virtual void cpu_task() = 0;
|
||||
virtual bool handle_interrupt() { return false; }
|
||||
};
|
||||
|
||||
inline cpu_thread* get_current_cpu_thread() noexcept
|
||||
@@ -63,3 +80,27 @@ 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();
|
||||
}
|
||||
};
|
||||
|
||||
+205
-66
@@ -1,76 +1,215 @@
|
||||
#pragma once
|
||||
|
||||
struct CellOk
|
||||
#define ERROR_CODE(code) static_cast<s32>(code)
|
||||
|
||||
enum CellOk : s32
|
||||
{
|
||||
enum : s32
|
||||
CELL_OK = 0,
|
||||
};
|
||||
|
||||
enum CellError : s32
|
||||
{
|
||||
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),
|
||||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
__not_an_error,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CELL_OK = 0
|
||||
};
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// Temporary workaround
|
||||
constexpr auto CELL_OK = CellOk::CELL_OK;
|
||||
// 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__)
|
||||
|
||||
enum CellError : u32
|
||||
template<typename T, typename>
|
||||
struct ppu_gpr_cast_impl;
|
||||
|
||||
template<>
|
||||
struct ppu_gpr_cast_impl<ppu_error_code, void>
|
||||
{
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
+351
-389
@@ -3,6 +3,8 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
extern std::mutex g_mutex_avcodec_open2;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "libavcodec/avcodec.h"
|
||||
@@ -13,391 +15,97 @@ 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);
|
||||
|
||||
class AudioDecoder : public ppu_thread
|
||||
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)
|
||||
{
|
||||
public:
|
||||
squeue_t<AdecTask> job;
|
||||
volatile bool is_closed;
|
||||
volatile bool is_finished;
|
||||
bool just_started;
|
||||
bool just_finished;
|
||||
av_register_all();
|
||||
avcodec_register_all();
|
||||
|
||||
AVCodec* codec;
|
||||
AVInputFormat* input_format;
|
||||
AVCodecContext* ctx;
|
||||
AVFormatContext* fmt;
|
||||
u8* io_buf;
|
||||
|
||||
struct AudioReader
|
||||
switch (type)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
case CELL_ADEC_TYPE_ATRACX:
|
||||
case CELL_ADEC_TYPE_ATRACX_2CH:
|
||||
case CELL_ADEC_TYPE_ATRACX_6CH:
|
||||
case CELL_ADEC_TYPE_ATRACX_8CH:
|
||||
{
|
||||
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);
|
||||
}
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
|
||||
input_format = av_find_input_format("oma");
|
||||
break;
|
||||
}
|
||||
|
||||
~AudioDecoder()
|
||||
case CELL_ADEC_TYPE_MP3:
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
|
||||
input_format = av_find_input_format("mp3");
|
||||
break;
|
||||
}
|
||||
|
||||
virtual void cpu_task() override
|
||||
default:
|
||||
{
|
||||
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;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
AudioDecoder::~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);
|
||||
}
|
||||
}
|
||||
|
||||
int adecRead(void* opaque, u8* buf, int buf_size)
|
||||
{
|
||||
@@ -454,16 +162,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, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
|
||||
adec.cbFunc(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
|
||||
|
||||
adec.job.pop(adec.task);
|
||||
|
||||
@@ -473,10 +181,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)", (u32)task.type);
|
||||
cellAdec.error("adecRawRead(): unknown task (%d)", task.type);
|
||||
Emu.Pause();
|
||||
return -1;
|
||||
}
|
||||
@@ -504,6 +212,267 @@ 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)
|
||||
@@ -558,11 +527,7 @@ s32 cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
|
||||
|
||||
*handle = adec->id;
|
||||
|
||||
adec->run();
|
||||
adecOpen(*handle = idm::make<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -576,11 +541,7 @@ s32 cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res,
|
||||
return CELL_ADEC_ERROR_ARG;
|
||||
}
|
||||
|
||||
auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
|
||||
|
||||
*handle = adec->id;
|
||||
|
||||
adec->run();
|
||||
adecOpen(*handle = idm::make<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -613,7 +574,8 @@ s32 cellAdecClose(u32 handle)
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
}
|
||||
|
||||
idm::remove<ppu_thread>(handle);
|
||||
idm::remove<PPUThread>(adec->adecCb->id);
|
||||
idm::remove<AudioDecoder>(handle);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -817,7 +779,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Unsupported frame format (channels=%d, format=%d)" HERE, frame->channels, frame->format);
|
||||
throw EXCEPTION("Unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1043,7 +1043,7 @@ struct AdecTask
|
||||
|
||||
struct AdecFrame
|
||||
{
|
||||
struct AVFrame* data;
|
||||
AVFrame* data;
|
||||
u64 pts;
|
||||
u64 userdata;
|
||||
u32 auAddr;
|
||||
@@ -1096,3 +1096,58 @@ 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
Reference in New Issue
Block a user