Compare commits

...

21 Commits

Author SHA1 Message Date
Alistair Leslie-Hughes
265554a9da Release v10.16 2025-10-04 19:48:02 +10:00
Elizabeth Figura
38d4b8ca78 Rebase against 01269452e0fbb1f081d506bd64996590a553e2b9. 2025-10-03 16:39:15 -05:00
Elizabeth Figura
9c06e8eab3 Rebase against 192d335facd5ec6ff2b9acec615efff16385a416. 2025-10-01 16:58:46 -05:00
Elizabeth Figura
78a888cd3d user32-FlashWindowEx: Remove patch.
This was fixed upstream by d4b2865eb7f2612e52b3fee6ae121e59c2d28296.

Although some parts of the patch still apply and are orthogonal to the change, tests show they're not correct either.
2025-10-01 15:44:21 -05:00
Elizabeth Figura
1f7871a75c user32-ListBox_Size: Remove patch set.
Upstreamed by 57791a5b1a5429a31711f4cd746846d8fee4b798; omitted from the last rebase.
2025-09-30 20:10:45 -05:00
Alistair Leslie-Hughes
815194acd6 Updated vkd3d-latest patchset 2025-10-01 07:52:38 +10:00
Alistair Leslie-Hughes
7e9e516c71 Rebase against bcd3e1a4de9d6efb177b932a937412bfb962d149. 2025-10-01 07:52:38 +10:00
Alistair Leslie-Hughes
ea30d81923 Updated vkd3d-latest patchset 2025-09-30 09:16:55 +10:00
Alistair Leslie-Hughes
a8cce16566 Rebase against 7fb9d22a7932aaf32383ecebb59487d57a503754. 2025-09-30 07:46:22 +10:00
Elizabeth Figura
20ba4773d6 Rebase against 8da914b27c9939ecf511001bcac1a6c74e7edde0. 2025-09-21 16:54:15 -05:00
Alistair Leslie-Hughes
64988e15df Rebase against fc70990d579a74974c6e4f1550f892188114f5cf. 2025-09-20 09:13:49 +10:00
Alistair Leslie-Hughes
1a739efaa4 Updated vkd3d-latest patchset 2025-09-20 09:13:49 +10:00
Alistair Leslie-Hughes
27156e4a6e Updated d3dx11_43-D3DX11CreateTextureFromMemory patchset
Thanks Connor McAdams.
2025-09-20 07:17:19 +10:00
Alistair Leslie-Hughes
112b476921 Added d3dx9-setrawvalue patchset 2025-09-20 07:14:13 +10:00
Alistair Leslie-Hughes
2465e06751 Updated vkd3d-latest patchset 2025-09-19 09:30:04 +10:00
Elizabeth Figura
0e9c421030 Rebase against 0abb419016e3a38e36ba0bdfe9c0497a29a86fcf. 2025-09-18 17:22:54 -05:00
Elizabeth Figura
04570cc4c7 Rebase against 915a1e6fc76943913a77b71446c72dc13eadc1a0. 2025-09-17 16:46:56 -05:00
Elizabeth Figura
c062a34be3 Rebase against 58407c404938f5e83a4ab2a6fa7b7a75ad2b5e85. 2025-09-16 17:03:19 -05:00
Elizabeth Figura
42ab95dc1f ntdll-NtSetLdtEntries: Restore the parts that were not yet upstreamed. 2025-09-16 13:45:16 -05:00
Alistair Leslie-Hughes
e1dea6b9ac vkd3d-latest patchset
Squash
2025-09-16 08:43:37 +10:00
Alistair Leslie-Hughes
74477d5d72 Rebase against 7d26649f6375cd8bf765405237c85933c58e8de8. 2025-09-16 08:37:45 +10:00
115 changed files with 18070 additions and 18534 deletions

View File

@@ -1,406 +0,0 @@
From 18e01f69f4a3ad85253bb73dcd3ff197074c8810 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 3 Aug 2021 11:13:18 +1000
Subject: [PATCH] d3dx11_42: Implement D3DX11CreateTextureFromMemory
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
---
dlls/d3dx11_43/texture.c | 365 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 359 insertions(+), 6 deletions(-)
diff --git a/dlls/d3dx11_43/texture.c b/dlls/d3dx11_43/texture.c
index cbf3b630f58..0bc5ef9ab03 100644
--- a/dlls/d3dx11_43/texture.c
+++ b/dlls/d3dx11_43/texture.c
@@ -15,12 +15,15 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
#include "d3dx11.h"
#include "d3dcompiler.h"
#include "dxhelpers.h"
+#include "wincodec.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
@@ -277,16 +280,366 @@ HRESULT WINAPI D3DX11CreateTextureFromFileW(ID3D11Device *device, const WCHAR *f
return E_NOTIMPL;
}
-HRESULT WINAPI D3DX11CreateTextureFromMemory(ID3D11Device *device, const void *data,
- SIZE_T data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump,
- ID3D11Resource **texture, HRESULT *hresult)
+static const DXGI_FORMAT block_compressed_formats[] =
+{
+ DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB
+};
+
+static BOOL is_block_compressed(DXGI_FORMAT format)
{
- FIXME("device %p, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p stub.\n",
- device, data, data_size, load_info, pump, texture, hresult);
+ unsigned int i;
- return E_NOTIMPL;
+ for (i = 0; i < ARRAY_SIZE(block_compressed_formats); ++i)
+ if (format == block_compressed_formats[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+static unsigned int get_bpp_from_format(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return 128;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 96;
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_Y210:
+ case DXGI_FORMAT_Y216:
+ return 64;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_YUY2:
+ return 32;
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ return 24;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_A8P8:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return 16;
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_NV11:
+ return 12;
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 8;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return 4;
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static const struct
+{
+ const GUID *wic_guid;
+ DXGI_FORMAT dxgi_format;
+}
+wic_pixel_formats[] =
+{
+ { &GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM },
+ { &GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
+ { &GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
+ { &GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
+ { &GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
+ { &GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
+ { &GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
+ { &GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
+ { &GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM },
+ { &GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM },
+ { &GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
+ { &GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB },
+ { &GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
+ { &GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM },
+ { &GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
+ { &GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
+ { &GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
+ { &GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }
+};
+
+static const GUID *dxgi_format_to_wic_guid(DXGI_FORMAT format)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); ++i)
+ {
+ if (wic_pixel_formats[i].dxgi_format == format)
+ return wic_pixel_formats[i].wic_guid;
+ }
+
+ return NULL;
}
+HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT sdk_version, IWICImagingFactory **imaging_factory);
+
+HRESULT WINAPI D3DX11CreateTextureFromMemory(ID3D11Device *device, const void *src_data,
+ SIZE_T src_data_size, D3DX11_IMAGE_LOAD_INFO *load_info, ID3DX11ThreadPump *pump,
+ ID3D11Resource **texture, HRESULT *hresult)
+ {
+ unsigned int frame_count, width, height, stride, frame_size;
+ IWICFormatConverter *converter = NULL;
+ IWICDdsFrameDecode *dds_frame = NULL;
+ D3D11_TEXTURE2D_DESC texture_2d_desc;
+ D3D11_SUBRESOURCE_DATA resource_data;
+ IWICBitmapFrameDecode *frame = NULL;
+ IWICImagingFactory *factory = NULL;
+ IWICBitmapDecoder *decoder = NULL;
+ ID3D11Texture2D *texture_2d;
+ D3DX11_IMAGE_INFO img_info;
+ IWICStream *stream = NULL;
+ const GUID *dst_format;
+ BYTE *buffer = NULL;
+ BOOL can_convert;
+ GUID src_format;
+ HRESULT hr;
+
+ TRACE("device %p, data %p, data_size %Iu, load_info %p, pump %p, texture %p, hresult %p.\n",
+ device, src_data, src_data_size, load_info, pump, texture, hresult);
+
+ if (!src_data || !src_data_size || !texture)
+ return E_FAIL;
+ if (pump)
+ FIXME("Thread pump is not supported yet.\n");
+
+ if (load_info)
+ {
+ img_info.Width = load_info->Width;
+ img_info.Height = load_info->Height;
+ img_info.Depth = load_info->Depth;
+ img_info.ArraySize = 1;
+ img_info.MipLevels = load_info->MipLevels;
+ img_info.MiscFlags = load_info->MiscFlags;
+ img_info.Format = load_info->Format;
+ }
+ else
+ {
+ if (FAILED(D3DX11GetImageInfoFromMemory(src_data, src_data_size, NULL, &img_info, NULL)))
+ return E_FAIL;
+ if (img_info.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
+ {
+ FIXME("Cube map is not supported.\n");
+ return E_FAIL;
+ }
+ }
+
+ if (FAILED(hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory)))
+ goto end;
+ if (FAILED(hr = IWICImagingFactory_CreateStream(factory, &stream)))
+ goto end;
+ if (FAILED(hr = IWICStream_InitializeFromMemory(stream, (BYTE *)src_data, src_data_size)))
+ goto end;
+ if (FAILED(hr = IWICImagingFactory_CreateDecoderFromStream(factory, (IStream *)stream, NULL, 0, &decoder)))
+ goto end;
+ if (FAILED(hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)) || !frame_count)
+ goto end;
+ if (FAILED(hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame)))
+ goto end;
+ if (FAILED(hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &src_format)))
+ goto end;
+
+ width = img_info.Width;
+ height = img_info.Height;
+ if (is_block_compressed(img_info.Format))
+ {
+ width = (width + 3) & ~3;
+ height = (height + 3) & ~3;
+ }
+ stride = (width * get_bpp_from_format(img_info.Format) + 7) / 8;
+ frame_size = stride * height;
+
+ if (!(buffer = heap_alloc(frame_size)))
+ {
+ hr = E_FAIL;
+ goto end;
+ }
+
+ if (is_block_compressed(img_info.Format))
+ {
+ if (FAILED(hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICDdsFrameDecode, (void **)&dds_frame)))
+ goto end;
+ if (FAILED(hr = IWICDdsFrameDecode_CopyBlocks(dds_frame, NULL, stride * 4, frame_size, buffer)))
+ goto end;
+ }
+ else
+ {
+ if (!(dst_format = dxgi_format_to_wic_guid(img_info.Format)))
+ {
+ hr = E_FAIL;
+ FIXME("Unsupported DXGI format %#x.\n", img_info.Format);
+ goto end;
+ }
+
+ if (IsEqualGUID(&src_format, dst_format))
+ {
+ if (FAILED(hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, stride, frame_size, buffer)))
+ goto end;
+ }
+ else
+ {
+ if (FAILED(hr = IWICImagingFactory_CreateFormatConverter(factory, &converter)))
+ goto end;
+ if (FAILED(hr = IWICFormatConverter_CanConvert(converter, &src_format, dst_format, &can_convert)))
+ goto end;
+ if (!can_convert)
+ {
+ WARN("Format converting %s to %s is not supported by WIC.\n",
+ debugstr_guid(&src_format), debugstr_guid(dst_format));
+ goto end;
+ }
+ if (FAILED(hr = IWICFormatConverter_Initialize(converter, (IWICBitmapSource *)frame, dst_format,
+ WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom)))
+ goto end;
+ if (FAILED(hr = IWICFormatConverter_CopyPixels(converter, NULL, stride, frame_size, buffer)))
+ goto end;
+ }
+ }
+
+ memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
+ texture_2d_desc.Width = width;
+ texture_2d_desc.Height = height;
+ texture_2d_desc.MipLevels = 1;
+ texture_2d_desc.ArraySize = img_info.ArraySize;
+ texture_2d_desc.Format = img_info.Format;
+ texture_2d_desc.SampleDesc.Count = 1;
+ texture_2d_desc.Usage = D3D11_USAGE_DEFAULT;
+ texture_2d_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ texture_2d_desc.MiscFlags = img_info.MiscFlags;
+
+ resource_data.pSysMem = buffer;
+ resource_data.SysMemPitch = stride;
+ resource_data.SysMemSlicePitch = frame_size;
+
+ if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_2d_desc, &resource_data, &texture_2d)))
+ goto end;
+
+ *texture = (ID3D11Resource *)texture_2d;
+ hr = S_OK;
+
+end:
+ if (converter)
+ IWICFormatConverter_Release(converter);
+ if (dds_frame)
+ IWICDdsFrameDecode_Release(dds_frame);
+ if (buffer)
+ heap_free(buffer);
+ if (frame)
+ IWICBitmapFrameDecode_Release(frame);
+ if (decoder)
+ IWICBitmapDecoder_Release(decoder);
+ if (stream)
+ IWICStream_Release(stream);
+ if (factory)
+ IWICImagingFactory_Release(factory);
+
+ return hr;
+ }
+
HRESULT WINAPI D3DX11SaveTextureToFileW(ID3D11DeviceContext *context, ID3D11Resource *texture,
D3DX11_IMAGE_FILE_FORMAT format, const WCHAR *filename)
{
--
2.51.0

View File

@@ -1,25 +0,0 @@
From 3c5ed75d72440b3c1ff668c3aece8216b561bece Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sat, 13 Sep 2025 08:17:15 +1000
Subject: [PATCH] d3dx9: Add support for GUID_WICPixelFormat16bppGray
Stop error with HighFleet on startup.
---
dlls/d3dx9_36/d3dx_helpers.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c
index 60394ca1d9b..26b00191b68 100644
--- a/dlls/d3dx9_36/d3dx_helpers.c
+++ b/dlls/d3dx9_36/d3dx_helpers.c
@@ -140,6 +140,7 @@ static const struct
{ &GUID_WICPixelFormat2bppIndexed, D3DX_PIXEL_FORMAT_P2_UINT },
{ &GUID_WICPixelFormat4bppIndexed, D3DX_PIXEL_FORMAT_P4_UINT },
{ &GUID_WICPixelFormat8bppGray, D3DX_PIXEL_FORMAT_L8_UNORM },
+ { &GUID_WICPixelFormat16bppGray, D3DX_PIXEL_FORMAT_R16_UNORM },
{ &GUID_WICPixelFormat16bppBGR555, D3DX_PIXEL_FORMAT_B5G5R5X1_UNORM },
{ &GUID_WICPixelFormat16bppBGR565, D3DX_PIXEL_FORMAT_B5G6R5_UNORM },
{ &GUID_WICPixelFormat24bppBGR, D3DX_PIXEL_FORMAT_B8G8R8_UNORM },
--
2.51.0

View File

@@ -1,49 +0,0 @@
From 9d0bf8024bf5d97540fd1fa7456766fea808bc20 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sat, 13 Sep 2025 08:17:15 +1000
Subject: [PATCH] d3dx9_36: Use correct pixel type for DXT* format
Required for Puyo-Puyo tetris.
---
dlls/d3dx9_36/d3dx_helpers.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx_helpers.c b/dlls/d3dx9_36/d3dx_helpers.c
index 26b00191b68..694b1b53548 100644
--- a/dlls/d3dx9_36/d3dx_helpers.c
+++ b/dlls/d3dx9_36/d3dx_helpers.c
@@ -290,8 +290,8 @@ static enum d3dx_pixel_format_id d3dx_pixel_format_id_from_dds_pixel_format(cons
{
uint32_t i;
- TRACE("pixel_format: size %lu, flags %#lx, fourcc %#lx, bpp %lu.\n", pixel_format->size,
- pixel_format->flags, pixel_format->fourcc, pixel_format->bpp);
+ TRACE("pixel_format: size %lu, flags %#lx, fourcc %s, bpp %lu.\n", pixel_format->size,
+ pixel_format->flags, debugstr_fourcc(pixel_format->fourcc), pixel_format->bpp);
TRACE("rmask %#lx, gmask %#lx, bmask %#lx, amask %#lx.\n", pixel_format->rmask, pixel_format->gmask,
pixel_format->bmask, pixel_format->amask);
@@ -1152,6 +1152,20 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
if ((image->format = d3dx_pixel_format_id_from_dds_pixel_format(&header->pixel_format)) == D3DX_PIXEL_FORMAT_COUNT)
return D3DXERR_INVALIDDATA;
+ switch (image->format)
+ {
+ case D3DX_PIXEL_FORMAT_DXT1_UNORM:
+ case D3DX_PIXEL_FORMAT_DXT2_UNORM:
+ case D3DX_PIXEL_FORMAT_DXT3_UNORM:
+ case D3DX_PIXEL_FORMAT_DXT4_UNORM:
+ case D3DX_PIXEL_FORMAT_DXT5_UNORM:
+ image->format = D3DX_PIXEL_FORMAT_R8G8B8A8_UNORM;
+ break;
+ default:
+ /* Leave format as is */
+ break;
+ }
+
image->image_file_format = D3DX_IMAGE_FILE_FORMAT_DDS;
image->layer_count = 1;
if (header->flags & DDS_DEPTH)
--
2.51.0

View File

@@ -0,0 +1,234 @@
From da45b8dd00ab02ba03d8608afdf32085f5d28603 Mon Sep 17 00:00:00 2001
From: Connor McAdams <cmcadams@codeweavers.com>
Date: Wed, 17 Sep 2025 15:26:50 -0400
Subject: [PATCH] d3dx10: Create 3D textures for images representing 3D
textures.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
---
dlls/d3dx10_43/async.c | 11 +++++-
dlls/d3dx10_43/tests/d3dx10.c | 35 ++++++++++++------
dlls/d3dx10_43/texture.c | 69 +++++++++++++++++++++++++++--------
3 files changed, 86 insertions(+), 29 deletions(-)
diff --git a/dlls/d3dx10_43/async.c b/dlls/d3dx10_43/async.c
index 62627886804..e2cd14a7736 100644
--- a/dlls/d3dx10_43/async.c
+++ b/dlls/d3dx10_43/async.c
@@ -322,6 +322,8 @@ struct texture_processor
{
ID3DX10DataProcessor ID3DX10DataProcessor_iface;
ID3D10Device *device;
+ D3DX10_IMAGE_INFO img_info;
+ D3DX10_IMAGE_INFO *img_info_out;
D3DX10_IMAGE_LOAD_INFO load_info;
D3D10_SUBRESOURCE_DATA *resource_data;
};
@@ -334,6 +336,7 @@ static inline struct texture_processor *texture_processor_from_ID3DX10DataProces
static HRESULT WINAPI texture_processor_Process(ID3DX10DataProcessor *iface, void *data, SIZE_T size)
{
struct texture_processor *processor = texture_processor_from_ID3DX10DataProcessor(iface);
+ HRESULT hr;
TRACE("iface %p, data %p, size %Iu.\n", iface, data, size);
@@ -343,7 +346,10 @@ static HRESULT WINAPI texture_processor_Process(ID3DX10DataProcessor *iface, voi
free(processor->resource_data);
processor->resource_data = NULL;
}
- return load_texture_data(data, size, &processor->load_info, &processor->resource_data);
+ hr = load_texture_data(data, size, &processor->load_info, &processor->resource_data);
+ if (SUCCEEDED(hr) && processor->img_info_out)
+ *processor->img_info_out = processor->img_info;
+ return hr;
}
static HRESULT WINAPI texture_processor_CreateDeviceObject(ID3DX10DataProcessor *iface, void **object)
@@ -594,7 +600,10 @@ HRESULT WINAPI D3DX10CreateAsyncTextureProcessor(ID3D10Device *device,
object->ID3DX10DataProcessor_iface.lpVtbl = &texture_processor_vtbl;
object->device = device;
ID3D10Device_AddRef(device);
+ if (load_info)
+ object->img_info_out = load_info->pSrcInfo;
init_load_info(load_info, &object->load_info);
+ object->load_info.pSrcInfo = &object->img_info;
*processor = &object->ID3DX10DataProcessor_iface;
return S_OK;
diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c
index f660b9a2953..818889138a5 100644
--- a/dlls/d3dx10_43/tests/d3dx10.c
+++ b/dlls/d3dx10_43/tests/d3dx10.c
@@ -20,6 +20,7 @@
#include "initguid.h"
#include "d3d10_1.h"
#include "d3dx10.h"
+#include "wine/wined3d.h"
#include "wine/test.h"
#include <stdint.h>
@@ -69,6 +70,8 @@
#define DDS_PF_BUMPLUMINANCE 0x00040000
#define DDS_PF_BUMPDUDV 0x00080000
+static bool wined3d_opengl;
+
struct dds_pixel_format
{
DWORD size;
@@ -1751,13 +1754,8 @@ static void check_test_image_load_info_resource_(uint32_t line, ID3D10Resource *
HRESULT hr;
ID3D10Resource_GetType(resource, &resource_dimension);
- todo_wine_if(image_load_info->expected_type == D3D10_RESOURCE_DIMENSION_TEXTURE3D)
- ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n",
- resource_dimension, image_load_info->expected_type);
-
- if (resource_dimension != image_load_info->expected_type)
- return;
-
+ ok(resource_dimension == image_load_info->expected_type, "Got unexpected ResourceDimension %u, expected %u.\n",
+ resource_dimension, image_load_info->expected_type);
switch (resource_dimension)
{
case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
@@ -1826,10 +1824,9 @@ static void check_resource_info(ID3D10Resource *resource, const struct test_imag
}
ID3D10Resource_GetType(resource, &resource_dimension);
- todo_wine_if (image->expected_info.ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D)
- ok(resource_dimension == image->expected_info.ResourceDimension,
- "Got unexpected ResourceDimension %u, expected %u.\n",
- resource_dimension, image->expected_info.ResourceDimension);
+ ok(resource_dimension == image->expected_info.ResourceDimension,
+ "Got unexpected ResourceDimension %u, expected %u.\n",
+ resource_dimension, image->expected_info.ResourceDimension);
switch (resource_dimension)
{
@@ -2022,7 +2019,10 @@ static void check_resource_data(ID3D10Resource *resource, const struct test_imag
if (SUCCEEDED(ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture3D, (void **)&texture3d)))
{
- check_texture3d_data(texture3d, image, line);
+ if (wined3d_opengl && is_block_compressed(image->expected_info.Format))
+ skip("Skipping compressed format 3D texture readback test.\n");
+ else
+ check_texture3d_data(texture3d, image, line);
ID3D10Texture3D_Release(texture3d);
}
else if (SUCCEEDED(ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&texture2d)))
@@ -5992,6 +5992,17 @@ static void test_preprocess_shader(void)
START_TEST(d3dx10)
{
+ HMODULE wined3d;
+
+ if ((wined3d = GetModuleHandleA("wined3d.dll")))
+ {
+ enum wined3d_renderer (CDECL *p_wined3d_get_renderer)(void);
+
+ if ((p_wined3d_get_renderer = (void *)GetProcAddress(wined3d, "wined3d_get_renderer"))
+ && p_wined3d_get_renderer() == WINED3D_RENDERER_OPENGL)
+ wined3d_opengl = true;
+ }
+
test_D3DX10UnsetAllDeviceObjects();
test_D3DX10CreateAsyncMemoryLoader();
test_D3DX10CreateAsyncFileLoader();
diff --git a/dlls/d3dx10_43/texture.c b/dlls/d3dx10_43/texture.c
index 4d279bccbd5..a21ce7ff139 100644
--- a/dlls/d3dx10_43/texture.c
+++ b/dlls/d3dx10_43/texture.c
@@ -439,9 +439,12 @@ static HRESULT create_texture(ID3D10Device *device, const void *data, SIZE_T siz
{
D3D10_SUBRESOURCE_DATA *resource_data;
D3DX10_IMAGE_LOAD_INFO load_info_copy;
+ D3DX10_IMAGE_INFO img_info;
HRESULT hr;
init_load_info(load_info, &load_info_copy);
+ if (!load_info_copy.pSrcInfo)
+ load_info_copy.pSrcInfo = &img_info;
if (FAILED((hr = load_texture_data(data, size, &load_info_copy, &resource_data))))
return hr;
@@ -774,25 +777,59 @@ end:
HRESULT create_d3d_texture(ID3D10Device *device, D3DX10_IMAGE_LOAD_INFO *load_info,
D3D10_SUBRESOURCE_DATA *resource_data, ID3D10Resource **texture)
{
- D3D10_TEXTURE2D_DESC texture_2d_desc;
- ID3D10Texture2D *texture_2d;
HRESULT hr;
- memset(&texture_2d_desc, 0, sizeof(texture_2d_desc));
- texture_2d_desc.Width = load_info->Width;
- texture_2d_desc.Height = load_info->Height;
- texture_2d_desc.MipLevels = load_info->MipLevels;
- texture_2d_desc.ArraySize = load_info->MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE ? 6 : 1;
- texture_2d_desc.Format = load_info->Format;
- texture_2d_desc.SampleDesc.Count = 1;
- texture_2d_desc.Usage = load_info->Usage;
- texture_2d_desc.BindFlags = load_info->BindFlags;
- texture_2d_desc.MiscFlags = load_info->MiscFlags;
-
- if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d)))
- return hr;
+ *texture = NULL;
+ switch (load_info->pSrcInfo->ResourceDimension)
+ {
+ case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ D3D10_TEXTURE2D_DESC texture_2d_desc = { 0 };
+ ID3D10Texture2D *texture_2d;
+
+ texture_2d_desc.Width = load_info->Width;
+ texture_2d_desc.Height = load_info->Height;
+ texture_2d_desc.MipLevels = load_info->MipLevels;
+ texture_2d_desc.ArraySize = load_info->pSrcInfo->ArraySize;
+ texture_2d_desc.Format = load_info->Format;
+ texture_2d_desc.SampleDesc.Count = 1;
+ texture_2d_desc.Usage = load_info->Usage;
+ texture_2d_desc.BindFlags = load_info->BindFlags;
+ texture_2d_desc.CPUAccessFlags = load_info->CpuAccessFlags;
+ texture_2d_desc.MiscFlags = load_info->MiscFlags;
+
+ if (FAILED(hr = ID3D10Device_CreateTexture2D(device, &texture_2d_desc, resource_data, &texture_2d)))
+ return hr;
+ *texture = (ID3D10Resource *)texture_2d;
+ break;
+ }
+
+ case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ D3D10_TEXTURE3D_DESC texture_3d_desc = { 0 };
+ ID3D10Texture3D *texture_3d;
+
+ texture_3d_desc.Width = load_info->Width;
+ texture_3d_desc.Height = load_info->Height;
+ texture_3d_desc.Depth = load_info->Depth;
+ texture_3d_desc.MipLevels = load_info->MipLevels;
+ texture_3d_desc.Format = load_info->Format;
+ texture_3d_desc.Usage = load_info->Usage;
+ texture_3d_desc.BindFlags = load_info->BindFlags;
+ texture_3d_desc.CPUAccessFlags = load_info->CpuAccessFlags;
+ texture_3d_desc.MiscFlags = load_info->MiscFlags;
+
+ if (FAILED(hr = ID3D10Device_CreateTexture3D(device, &texture_3d_desc, resource_data, &texture_3d)))
+ return hr;
+ *texture = (ID3D10Resource *)texture_3d;
+ break;
+ }
+
+ default:
+ FIXME("Unhandled resource dimension %d.\n", load_info->pSrcInfo->ResourceDimension);
+ return E_NOTIMPL;
+ }
- *texture = (ID3D10Resource *)texture_2d;
return S_OK;
}
--
2.51.0

View File

@@ -1 +1,2 @@
Fixes: [45533] - Implement D3DX11CreateTextureFromMemory
Disabled: True

View File

@@ -0,0 +1,97 @@
From 4295a5251ba743d6a7cef9847ba58f6b4b3319c9 Mon Sep 17 00:00:00 2001
From: Connor McAdams <cmcadams@codeweavers.com>
Date: Thu, 11 Sep 2025 14:42:19 -0400
Subject: [PATCH 1/2] d3dx9: Add support for setting vec{2,3} effect parameters
in ID3DXEffect::SetRawValue().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
---
dlls/d3dx9_36/effect.c | 44 ++++++++++++++++++++++++++++--------
dlls/d3dx9_36/tests/effect.c | 3 ---
2 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 72e216d3fff..500832340d3 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -4456,20 +4456,46 @@ static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE par
{
uint8_t *dst_data;
- if (param->columns != 4)
+ if (param->columns == 4)
{
- FIXME("Vec%u parameters are currently unsupported.\n", param->columns);
- return E_NOTIMPL;
- }
+ if ((byte_offset + bytes) > param->bytes)
+ {
+ FIXME("Writing adjacent parameters is currently unsupported.\n");
+ return E_NOTIMPL;
+ }
- if ((byte_offset + bytes) > param->bytes)
+ dst_data = param_get_data_and_dirtify(effect, param, !byte_offset ? bytes : param->bytes, TRUE);
+ memcpy(dst_data + byte_offset, data, bytes);
+ }
+ else
{
- FIXME("Writing adjacent parameters is currently unsupported.\n");
- return E_NOTIMPL;
+ unsigned int src_elems = (bytes + 0xf) / sizeof(D3DXVECTOR4);
+ unsigned int dst_stride = sizeof(float) * param->columns;
+ unsigned int dst_elems = max(1, param->element_count);
+ const D3DXVECTOR4 *src_data = data;
+ unsigned int i, bytes_left;
+
+ if (byte_offset)
+ {
+ FIXME("Setting Vec%u parameters with an offset is currently unsupported.\n", param->columns);
+ return E_NOTIMPL;
+ }
+
+ if (src_elems > dst_elems)
+ {
+ FIXME("Writing adjacent parameters is currently unsupported.\n");
+ return E_NOTIMPL;
+ }
+
+ bytes_left = bytes;
+ dst_data = param_get_data_and_dirtify(effect, param, dst_elems * dst_stride, TRUE);
+ for (i = 0; i < src_elems; ++i)
+ {
+ memcpy(dst_data + (i * dst_stride), &src_data[i], min(bytes_left, dst_stride));
+ bytes_left -= sizeof(*src_data);
+ }
}
- dst_data = param_get_data_and_dirtify(effect, param, !byte_offset ? bytes : param->bytes, TRUE);
- memcpy(dst_data + byte_offset, data, bytes);
break;
}
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 2b9f607b045..1be4a28777b 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -9068,17 +9068,14 @@ static void test_effect_set_raw_value(IDirect3DDevice9 *device)
{ "2", 0, 8,
{ .f = { 0.0f, 1.0f } },
{ .f = { 0.0f, 1.0f } },
- .todo_hr = TRUE
},
{ "2_2", 0, 16,
{ .f = { 0.0f, 1.0f, 0.0f, 2.0f } },
{ .f = { 0.0f, 1.0f, 0.0f, 0.0f } },
- .todo_hr = TRUE
},
{ "2_2", 0, 24,
{ .f = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 0.0f } },
{ .f = { 0.0f, 1.0f, 4.0f, 0.0f } },
- .todo_hr = TRUE
},
{ "4", 0, 16,
{ .f = { 1.0f, 2.0f, 0.0f, 3.0f } },
--
2.51.0

View File

@@ -0,0 +1,73 @@
From b3fa43c5d012f89417a31b15bc3f88fe10fbf429 Mon Sep 17 00:00:00 2001
From: Connor McAdams <cmcadams@codeweavers.com>
Date: Fri, 19 Sep 2025 13:58:15 -0400
Subject: [PATCH 2/2] d3dx9: Add partial support for setting D3DXPC_STRUCT
parameters in ID3DXEffect::SetRawValue().
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
---
dlls/d3dx9_36/effect.c | 48 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 500832340d3..119f280e1a8 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -4530,6 +4530,54 @@ static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE par
break;
}
+ case D3DXPC_STRUCT:
+ {
+ const uint8_t *cur_param_data = data;
+ UINT bytes_left = bytes;
+ unsigned int i;
+ HRESULT hr;
+
+ if (byte_offset)
+ {
+ FIXME("Setting structure members at an offset is currently unsupported.\n");
+ return E_NOTIMPL;
+ }
+
+ for (i = 0; i < param->member_count; ++i)
+ {
+ UINT member_size = param->members[i].class == D3DXPC_MATRIX_ROWS ? 64 : 16;
+ unsigned int member_elems = max(1, param->members[i].element_count);
+ struct d3dx_parameter *member = &param->members[i];
+
+ if (member->class != D3DXPC_MATRIX_ROWS && member->class != D3DXPC_VECTOR)
+ {
+ FIXME("Unhandled structure member parameter class %s.\n", debug_d3dxparameter_class(member->class));
+ return E_NOTIMPL;
+ }
+
+ member_size *= member_elems;
+ hr = iface->lpVtbl->SetRawValue(iface, (D3DXHANDLE)member, (const void *)cur_param_data, 0,
+ min(member_size, bytes_left));
+ if (FAILED(hr))
+ {
+ WARN("Failed with hr %#lx.\n", hr);
+ return hr;
+ }
+
+ if (bytes_left <= member_size)
+ {
+ bytes_left = 0;
+ break;
+ }
+ cur_param_data += member_size;
+ bytes_left -= member_size;
+ }
+
+ if (bytes_left)
+ FIXME("%u bytes were leftover, might have attempted to write an adjacent parameter.\n", bytes_left);
+ break;
+ }
+
default:
FIXME("Unhandled parameter class %s.\n", debug_d3dxparameter_class(param->class));
return E_NOTIMPL;
--
2.51.0

View File

@@ -0,0 +1 @@
Fixes: [48598] d3dx9: Improve Rendering in MudRunner.

View File

@@ -1,220 +0,0 @@
From 7ba5e4a89be15deeb704078ad8321c7cc5aa02eb Mon Sep 17 00:00:00 2001
From: Christian Costa <titan.costa@gmail.com>
Date: Mon, 22 Jul 2013 21:51:20 +0200
Subject: [PATCH] d3dx9_36: Implement ID3DXSkinInfoImpl_UpdateSkinnedMesh.
This patch fixes last problem of bug 32572.
---
dlls/d3dx9_36/skin.c | 86 ++++++++++++++++++++++++++++++++++++--
dlls/d3dx9_36/tests/mesh.c | 83 ++++++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/skin.c b/dlls/d3dx9_36/skin.c
index b81fb6863d3..75ee6d44a95 100644
--- a/dlls/d3dx9_36/skin.c
+++ b/dlls/d3dx9_36/skin.c
@@ -2,6 +2,7 @@
* Skin Info operations specific to D3DX9.
*
* Copyright (C) 2011 Dylan Smith
+ * Copyright (C) 2013 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -399,10 +400,89 @@ static HRESULT WINAPI d3dx9_skin_info_GetDeclaration(ID3DXSkinInfo *iface,
static HRESULT WINAPI d3dx9_skin_info_UpdateSkinnedMesh(ID3DXSkinInfo *iface, const D3DXMATRIX *bone_transforms,
const D3DXMATRIX *bone_inv_transpose_transforms, const void *src_vertices, void *dst_vertices)
{
- FIXME("iface %p, bone_transforms %p, bone_inv_transpose_transforms %p, src_vertices %p, dst_vertices %p stub!\n",
- iface, bone_transforms, bone_inv_transpose_transforms, src_vertices, dst_vertices);
+ struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface);
+ DWORD size = D3DXGetFVFVertexSize(skin->fvf);
+ DWORD i, j;
- return E_NOTIMPL;
+ TRACE("iface %p, bone_transforms %p, bone_inv_transpose_transforms %p, src_vertices %p, dst_vertices %p\n",
+ skin, bone_transforms, bone_inv_transpose_transforms, src_vertices, dst_vertices);
+
+ if (bone_inv_transpose_transforms)
+ FIXME("Skinning vertices with two position elements not supported\n");
+
+ if ((skin->fvf & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
+ FIXME("Vertex type %#lx not supported\n", skin->fvf & D3DFVF_POSITION_MASK);
+ return E_FAIL;
+ }
+
+ /* Reset all positions */
+ for (i = 0; i < skin->num_vertices; i++) {
+ D3DXVECTOR3 *position = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * i);
+ position->x = 0.0f;
+ position->y = 0.0f;
+ position->z = 0.0f;
+ }
+
+ /* Update positions that are influenced by bones */
+ for (i = 0; i < skin->num_bones; i++) {
+ D3DXMATRIX bone_inverse, matrix;
+
+ D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform);
+ D3DXMatrixMultiply(&matrix, &bone_transforms[i], &bone_inverse);
+ D3DXMatrixMultiply(&matrix, &matrix, &skin->bones[i].transform);
+
+ for (j = 0; j < skin->bones[i].num_influences; j++) {
+ D3DXVECTOR3 position;
+ D3DXVECTOR3 *position_src = (D3DXVECTOR3*)((BYTE*)src_vertices + size * skin->bones[i].vertices[j]);
+ D3DXVECTOR3 *position_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * skin->bones[i].vertices[j]);
+ FLOAT weight = skin->bones[i].weights[j];
+
+ D3DXVec3TransformCoord(&position, position_src, &matrix);
+ position_dest->x += weight * position.x;
+ position_dest->y += weight * position.y;
+ position_dest->z += weight * position.z;
+ }
+ }
+
+ if (skin->fvf & D3DFVF_NORMAL) {
+ /* Reset all normals */
+ for (i = 0; i < skin->num_vertices; i++) {
+ D3DXVECTOR3 *normal = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * i + sizeof(D3DXVECTOR3));
+ normal->x = 0.0f;
+ normal->y = 0.0f;
+ normal->z = 0.0f;
+ }
+
+ /* Update normals that are influenced by bones */
+ for (i = 0; i < skin->num_bones; i++) {
+ D3DXMATRIX bone_inverse, matrix;
+
+ D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform);
+ D3DXMatrixMultiply(&matrix, &skin->bones[i].transform, &bone_transforms[i]);
+
+ for (j = 0; j < skin->bones[i].num_influences; j++) {
+ D3DXVECTOR3 normal;
+ D3DXVECTOR3 *normal_src = (D3DXVECTOR3*)((BYTE*)src_vertices + size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3));
+ D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3));
+ FLOAT weight = skin->bones[i].weights[j];
+
+ D3DXVec3TransformNormal(&normal, normal_src, &bone_inverse);
+ D3DXVec3TransformNormal(&normal, &normal, &matrix);
+ normal_dest->x += weight * normal.x;
+ normal_dest->y += weight * normal.y;
+ normal_dest->z += weight * normal.z;
+ }
+ }
+
+ /* Normalize all normals that are influenced by bones*/
+ for (i = 0; i < skin->num_vertices; i++) {
+ D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + (i * size) + sizeof(D3DXVECTOR3));
+ if ((normal_dest->x != 0.0f) && (normal_dest->y != 0.0f) && (normal_dest->z != 0.0f))
+ D3DXVec3Normalize(normal_dest, normal_dest);
+ }
+ }
+
+ return D3D_OK;
}
static HRESULT WINAPI d3dx9_skin_info_ConvertToBlendedMesh(ID3DXSkinInfo *iface, ID3DXMesh *mesh_in,
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 1daec158a5f..64b02276843 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -5241,6 +5241,88 @@ static void test_create_skin_info(void)
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#lx\n", hr);
}
+static void test_update_skinned_mesh(void)
+{
+ static DWORD bone0_vertices[2] = { 1, 3 };
+ static FLOAT bone0_weights[2] = { 1.0f, 0.5f };
+ static DWORD bone1_vertices[2] = { 2, 3 };
+ static FLOAT bone1_weights[2] = { 1.0f, 0.5f };
+ static D3DMATRIX bones_matrix[2] =
+ { { { {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 2.0f, 2.0f, 4.0f, 1.0f
+ } } },
+ { { {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ -4.0f, -4.0f, 4.0f, 1.0f
+ } } } };
+ static D3DVECTOR vertices_src[] = {{ 1.0f, 1.0f, 1.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 1.0f, -1.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { -1.0f, -1.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f },
+ { -1.0f, -1.0f, -1.0f },
+ { -1.0f, 0.0f, 0.0f },
+ };
+ static D3DVECTOR vertices_ref[] = {{ 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f },
+ { 3.0f, 3.0f, 3.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { -5.0f, -5.0f, 5.0f },
+ { 0.0f, 0.0f, 1.0f },
+ { -2.0f, -2.0f, 3.0f },
+ { -1.0f, 0.0f, 0.0f },
+ };
+ D3DVECTOR vertices_dest[8];
+ HRESULT hr;
+ ID3DXSkinInfo *skin_info;
+ D3DXMATRIX matrix;
+ int i;
+
+ D3DXMatrixIdentity(&matrix);
+ for (i = 0; i < 8; i++)
+ {
+ vertices_dest[i].x = 10000.0f;
+ vertices_dest[i].y = 10000.0f;
+ vertices_dest[i].z = 10000.0f;
+ }
+
+ hr = D3DXCreateSkinInfoFVF(4, D3DFVF_XYZ | D3DFVF_NORMAL, 2, &skin_info);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+
+ skin_info->lpVtbl->SetBoneInfluence(skin_info, 0, 2, bone0_vertices, bone0_weights);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+ skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 0, &matrix);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+ skin_info->lpVtbl->SetBoneInfluence(skin_info, 1, 2, bone1_vertices, bone1_weights);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+ skin_info->lpVtbl->SetBoneOffsetMatrix(skin_info, 1, &matrix);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+ skin_info->lpVtbl->UpdateSkinnedMesh(skin_info, bones_matrix, NULL, vertices_src, vertices_dest);
+ ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr);
+ for (i = 0; i < 4; i++)
+ {
+ ok(compare(vertices_dest[i*2].x, vertices_ref[i*2].x), "Vertex[%d].position.x: got %g, expected %g\n",
+ i, vertices_dest[i*2].x, vertices_ref[i*2].x);
+ ok(compare(vertices_dest[i*2].y, vertices_ref[i*2].y), "Vertex[%d].position.y: got %g, expected %g\n",
+ i, vertices_dest[i*2].y, vertices_ref[i*2].y);
+ ok(compare(vertices_dest[i*2].z, vertices_ref[i*2].z), "Vertex[%d].position.z: got %g, expected %g\n",
+ i, vertices_dest[i*2].z, vertices_ref[i*2].z);
+ ok(compare(vertices_dest[i*2+1].x, vertices_ref[i*2+1].x), "Vertex[%d].normal.x: got %g, expected %g\n",
+ i, vertices_dest[i*2+1].x, vertices_ref[i*2+1].x);
+ ok(compare(vertices_dest[i*2+1].y, vertices_ref[i*2+1].y), "Vertex[%d].normal.y: got %g, expected %g\n",
+ i, vertices_dest[i*2+1].y, vertices_ref[i*2+1].y);
+ ok(compare(vertices_dest[i*2+1].z, vertices_ref[i*2+1].z), "Vertex[%d].normal.z: got %g, expected %g\n",
+ i, vertices_dest[i*2+1].z, vertices_ref[i*2+1].z);
+ }
+ skin_info->lpVtbl->Release(skin_info);
+}
+
static void test_convert_adjacency_to_point_reps(void)
{
HRESULT hr;
@@ -11484,6 +11566,7 @@ START_TEST(mesh)
D3DXGenerateAdjacencyTest();
test_update_semantics();
test_create_skin_info();
+ test_update_skinned_mesh();
test_convert_adjacency_to_point_reps();
test_convert_point_reps_to_adjacency();
test_weld_vertices();
--
2.38.1

View File

@@ -1 +0,0 @@
Fixes: [32572] Support for ID3DXSkinInfoImpl_UpdateSkinnedMesh

View File

@@ -1,54 +0,0 @@
From 826f68ed53563b81d225b49131bbd3595c6d885b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 6 Sep 2015 20:21:42 +0200
Subject: [PATCH] ddraw: Set dwZBufferBitDepth in ddraw7_GetCaps.
---
dlls/ddraw/ddraw.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 8d608656143..cc8adccf049 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -1434,6 +1434,28 @@ HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
return DD_OK;
}
+HRESULT CALLBACK enum_zbuffer(DDPIXELFORMAT *format, void *ctx)
+{
+ DDCAPS *caps = ctx;
+
+ switch (format->dwZBufferBitDepth)
+ {
+ case 8:
+ caps->dwZBufferBitDepths |= DDBD_8;
+ break;
+ case 16:
+ caps->dwZBufferBitDepths |= DDBD_16;
+ break;
+ case 24:
+ caps->dwZBufferBitDepths |= DDBD_24;
+ break;
+ case 32:
+ caps->dwZBufferBitDepths |= DDBD_32;
+ break;
+ }
+ return D3DENUMRET_OK;
+}
+
/*****************************************************************************
* IDirectDraw7::GetCaps
*
@@ -1514,6 +1536,8 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
+ IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
+
caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
if(DriverCaps)
--
2.20.1

View File

@@ -1,2 +0,0 @@
Fixes: [37019] Don't set HWTRANSFORMANDLIGHT flag on d3d7 RGB device
Fixes: [27002] Properly initialize caps->dwZBufferBitDepths in ddraw7_GetCaps

View File

@@ -7,4 +7,3 @@
# Carmageddon 2 demo
# The Sims Online
Fixes: [19153] Resident Evil 1 fails to start (needs IDirect3D3::EnumDevices() to return a device named "RGB Emulation")
Depends: ddraw-Device_Caps

View File

@@ -1,85 +0,0 @@
From 6c64a33f908b9fade24fe11d89533a70fdce352f Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Wed, 13 Jun 2018 10:44:49 -0500
Subject: [PATCH] configure: Check for sys/eventfd.h, ppoll(), and shm_open().
We use ppoll() instead of poll() for the better time granularity.
Although perhaps we shouldn't since the server doesn't do this.
---
configure.ac | 8 ++++++++
include/config.h.in | 11 ++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index eb7f8223b51..388ac14dc8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -411,6 +411,7 @@ AC_CHECK_HEADERS(\
sys/cdio.h \
sys/epoll.h \
sys/event.h \
+ sys/eventfd.h \
sys/extattr.h \
sys/filio.h \
sys/ipc.h \
@@ -2079,6 +2080,7 @@ AC_CHECK_FUNCS(\
port_create \
posix_fadvise \
posix_fallocate \
+ ppoll \
prctl \
sched_getcpu \
sched_yield \
@@ -2100,6 +2102,12 @@ AC_SEARCH_LIBS(clock_gettime, rt,
test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")])
LIBS=$ac_save_LIBS
+ac_save_LIBS=$LIBS
+AC_SEARCH_LIBS(shm_open, rt,
+ [AC_DEFINE(HAVE_SHM_OPEN, 1, [Define to 1 if you have the `shm_open' function.])
+ test "$ac_res" = "none required" || AC_SUBST(RT_LIBS,"$ac_res")])
+LIBS=$ac_save_LIBS
+
AC_CACHE_CHECK([for sched_setaffinity],wine_cv_have_sched_setaffinity,
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[#include <sched.h>]], [[sched_setaffinity(0, 0, 0);]])],[wine_cv_have_sched_setaffinity=yes],[wine_cv_have_sched_setaffinity=no]))
diff --git a/include/config.h.in b/include/config.h.in
index 6033d8674f3..563b63a92df 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -321,6 +321,9 @@
/* Define to 1 if you have the 'posix_fallocate' function. */
#undef HAVE_POSIX_FALLOCATE
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
/* Define to 1 if you have the 'prctl' function. */
#undef HAVE_PRCTL
@@ -381,7 +384,10 @@
/* Define to 1 if 'interface_id' is a member of 'sg_io_hdr_t'. */
#undef HAVE_SG_IO_HDR_T_INTERFACE_ID
-/* Define to 1 if 'si_fd' is a member of 'siginfo_t'. */
+/* Define to 1 if you have the `shm_open' function. */
+#undef HAVE_SHM_OPEN
+
+/* Define to 1 if `si_fd' is a member of `siginfo_t'. */
#undef HAVE_SIGINFO_T_SI_FD
/* Define to 1 if you have the 'sigprocmask' function. */
@@ -510,6 +516,9 @@
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
+/* Define to 1 if you have the <sys/eventfd.h> header file. */
+#undef HAVE_SYS_EVENTFD_H
+
/* Define to 1 if you have the <sys/event.h> header file. */
#undef HAVE_SYS_EVENT_H
--
2.45.2

View File

@@ -1,446 +0,0 @@
From da832ae3626406e9aee5f9f78bce01f2a0d49691 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 20:09:59 -0500
Subject: [PATCH] server: Create server objects for eventfd-based
synchronization objects.
---
server/Makefile.in | 1 +
server/esync.c | 318 ++++++++++++++++++++++++++++++++++++++++++++
server/esync.h | 24 ++++
server/main.c | 4 +
server/protocol.def | 24 ++++
5 files changed, 371 insertions(+)
create mode 100644 server/esync.c
create mode 100644 server/esync.h
diff --git a/server/Makefile.in b/server/Makefile.in
index 7e571ac2ba6..9632c4e694f 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -11,6 +11,7 @@ SOURCES = \
debugger.c \
device.c \
directory.c \
+ esync.c \
event.c \
fd.c \
file.c \
diff --git a/server/esync.c b/server/esync.c
new file mode 100644
index 00000000000..35b4833fd4c
--- /dev/null
+++ b/server/esync.c
@@ -0,0 +1,318 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_SYS_EVENTFD_H
+# include <sys/eventfd.h>
+#endif
+#include <sys/mman.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <unistd.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+
+#include "handle.h"
+#include "request.h"
+#include "file.h"
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
+
+ return do_esync_cached;
+#else
+ return 0;
+#endif
+}
+
+static char shm_name[29];
+static int shm_fd;
+static off_t shm_size;
+static void **shm_addrs;
+static int shm_addrs_size; /* length of the allocated shm_addrs array */
+static long pagesize;
+
+static void shm_cleanup(void)
+{
+ close( shm_fd );
+ if (shm_unlink( shm_name ) == -1)
+ perror( "shm_unlink" );
+}
+
+void esync_init(void)
+{
+ struct stat st;
+
+ if (fstat( config_dir_fd, &st ) == -1)
+ fatal_error( "cannot stat config dir\n" );
+
+ if (st.st_ino != (unsigned long)st.st_ino)
+ sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino );
+ else
+ sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino );
+
+ shm_unlink( shm_name );
+
+ shm_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 );
+ if (shm_fd == -1)
+ perror( "shm_open" );
+
+ pagesize = sysconf( _SC_PAGESIZE );
+
+ shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
+ shm_addrs_size = 128;
+
+ shm_size = pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ perror( "ftruncate" );
+
+ fprintf( stderr, "esync: up and running.\n" );
+
+ atexit( shm_cleanup );
+}
+
+struct esync
+{
+ struct object obj; /* object header */
+ int fd; /* eventfd file descriptor */
+ enum esync_type type;
+ unsigned int shm_idx; /* index into the shared memory section */
+};
+
+static void esync_dump( struct object *obj, int verbose );
+static void esync_destroy( struct object *obj );
+
+static const struct object_ops esync_ops =
+{
+ sizeof(struct esync), /* size */
+ &no_type, /* type */
+ esync_dump, /* dump */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ default_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ default_get_full_name, /* get_full_name */
+ no_lookup_name, /* lookup_name */
+ directory_link_name, /* link_name */
+ default_unlink_name, /* unlink_name */
+ no_open_file, /* open_file */
+ no_kernel_obj_list, /* get_kernel_obj_list */
+ no_close_handle, /* close_handle */
+ esync_destroy /* destroy */
+};
+
+static void esync_dump( struct object *obj, int verbose )
+{
+ struct esync *esync = (struct esync *)obj;
+ assert( obj->ops == &esync_ops );
+ fprintf( stderr, "esync fd=%d\n", esync->fd );
+}
+
+static void esync_destroy( struct object *obj )
+{
+ struct esync *esync = (struct esync *)obj;
+ close( esync->fd );
+}
+
+static int type_matches( enum esync_type type1, enum esync_type type2 )
+{
+ return (type1 == type2) ||
+ ((type1 == ESYNC_AUTO_EVENT || type1 == ESYNC_MANUAL_EVENT) &&
+ (type2 == ESYNC_AUTO_EVENT || type2 == ESYNC_MANUAL_EVENT));
+}
+
+static void *get_shm( unsigned int idx )
+{
+ int entry = (idx * 8) / pagesize;
+ int offset = (idx * 8) % pagesize;
+
+ if (entry >= shm_addrs_size)
+ {
+ int new_size = max(shm_addrs_size * 2, entry + 1);
+
+ if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) )))
+ fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 );
+
+ memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) );
+
+ shm_addrs_size = new_size;
+ }
+
+ if (!shm_addrs[entry])
+ {
+ void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
+ if (addr == (void *)-1)
+ {
+ fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize );
+ perror( "mmap" );
+ }
+
+ if (debug_level)
+ fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr );
+
+ if (__sync_val_compare_and_swap( &shm_addrs[entry], 0, addr ))
+ munmap( addr, pagesize ); /* someone beat us to it */
+ }
+
+ return (void *)((unsigned long)shm_addrs[entry] + offset);
+}
+
+struct semaphore
+{
+ int max;
+ int count;
+};
+C_ASSERT(sizeof(struct semaphore) == 8);
+
+struct esync *create_esync( struct object *root, const struct unicode_str *name,
+ unsigned int attr, int initval, int max, enum esync_type type,
+ const struct security_descriptor *sd )
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ struct esync *esync;
+
+ if ((esync = create_named_object( root, &esync_ops, name, attr, sd )))
+ {
+ if (get_error() != STATUS_OBJECT_NAME_EXISTS)
+ {
+ int flags = EFD_CLOEXEC | EFD_NONBLOCK;
+
+ if (type == ESYNC_SEMAPHORE)
+ flags |= EFD_SEMAPHORE;
+
+ /* initialize it if it didn't already exist */
+ esync->fd = eventfd( initval, flags );
+ if (esync->fd == -1)
+ {
+ perror( "eventfd" );
+ file_set_error();
+ release_object( esync );
+ return NULL;
+ }
+ esync->type = type;
+
+ /* Use the fd as index, since that'll be unique across all
+ * processes, but should hopefully end up also allowing reuse. */
+ esync->shm_idx = esync->fd + 1; /* we keep index 0 reserved */
+ while (esync->shm_idx * 8 >= shm_size)
+ {
+ /* Better expand the shm section. */
+ shm_size += pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ {
+ fprintf( stderr, "esync: couldn't expand %s to size %ld: ",
+ shm_name, (long)shm_size );
+ perror( "ftruncate" );
+ }
+ }
+
+ /* Initialize the shared memory portion. We want to do this on the
+ * server side to avoid a potential though unlikely race whereby
+ * the same object is opened and used between the time it's created
+ * and the time its shared memory portion is initialized. */
+ switch (type)
+ {
+ case ESYNC_SEMAPHORE:
+ {
+ struct semaphore *semaphore = get_shm( esync->shm_idx );
+ semaphore->max = max;
+ semaphore->count = initval;
+ break;
+ }
+ default:
+ assert( 0 );
+ }
+ }
+ else
+ {
+ /* validate the type */
+ if (!type_matches( type, esync->type ))
+ {
+ release_object( &esync->obj );
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ return NULL;
+ }
+ }
+ }
+ return esync;
+#else
+ /* FIXME: Provide a fallback implementation using pipe(). */
+ set_error( STATUS_NOT_IMPLEMENTED );
+ return NULL;
+#endif
+}
+
+DECL_HANDLER(create_esync)
+{
+ struct esync *esync;
+ struct unicode_str name;
+ struct object *root;
+ const struct security_descriptor *sd;
+ const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
+
+ if (!do_esync())
+ {
+ set_error( STATUS_NOT_IMPLEMENTED );
+ return;
+ }
+
+ if (!req->type)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (!objattr) return;
+
+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->max, req->type, sd )))
+ {
+ if (get_error() == STATUS_OBJECT_NAME_EXISTS)
+ reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes );
+ else
+ reply->handle = alloc_handle_no_access_check( current->process, esync,
+ req->access, objattr->attributes );
+
+ reply->type = esync->type;
+ reply->shm_idx = esync->shm_idx;
+ send_client_fd( current->process, esync->fd, reply->handle );
+ release_object( esync );
+ }
+
+ if (root) release_object( root );
+}
diff --git a/server/esync.h b/server/esync.h
new file mode 100644
index 00000000000..00f9e638d83
--- /dev/null
+++ b/server/esync.h
@@ -0,0 +1,24 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <unistd.h>
+
+extern int do_esync(void);
+void esync_init(void);
diff --git a/server/main.c b/server/main.c
index e014ec535ff..052667b4c6b 100644
--- a/server/main.c
+++ b/server/main.c
@@ -34,6 +34,7 @@
#include "thread.h"
#include "request.h"
#include "unicode.h"
+#include "esync.h"
/* command-line options */
int debug_level = 0;
@@ -229,6 +230,9 @@ int main( int argc, char *argv[] )
sock_init();
open_master_socket();
+ if (do_esync())
+ esync_init();
+
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
set_current_time();
init_signals();
diff --git a/server/protocol.def b/server/protocol.def
index fa4ca4aaa9e..a9ee996a8ab 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4080,6 +4080,29 @@ struct handle_info
obj_handle_t handle; /* next thread handle */
@END
+enum esync_type
+{
+ ESYNC_SEMAPHORE = 1,
+ ESYNC_AUTO_EVENT,
+ ESYNC_MANUAL_EVENT,
+ ESYNC_MUTEX,
+ ESYNC_AUTO_SERVER,
+ ESYNC_MANUAL_SERVER,
+ ESYNC_QUEUE,
+};
+
+/* Create a new eventfd-based synchronization object */
+@REQ(create_esync)
+ unsigned int access; /* wanted access rights */
+ int initval; /* initial value */
+ int type; /* type of esync object */
+ int max; /* maximum count on a semaphore */
+ VARARG(objattr,object_attributes); /* object attributes */
+@REPLY
+ obj_handle_t handle; /* handle to the object */
+ int type; /* actual type (may be different for events) */
+ unsigned int shm_idx;
+@END
/* Setup keyboard auto-repeat */
@REQ(set_keyboard_repeat)
@@ -4089,3 +4112,4 @@ struct handle_info
@REPLY
int enable; /* previous state of auto-repeat enable */
@END
+
--
2.47.2

View File

@@ -1,425 +0,0 @@
From 955a93ac10d1328e293fbf033e28107f98c43c7f Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:09:22 -0500
Subject: [PATCH] ntdll: Create eventfd-based objects for semaphores.
---
dlls/ntdll/Makefile.in | 1 +
dlls/ntdll/unix/esync.c | 270 +++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 35 +++++
dlls/ntdll/unix/loader.c | 2 +
dlls/ntdll/unix/server.c | 4 +-
dlls/ntdll/unix/sync.c | 4 +
server/esync.c | 1 +
7 files changed, 315 insertions(+), 2 deletions(-)
create mode 100644 dlls/ntdll/unix/esync.c
create mode 100644 dlls/ntdll/unix/esync.h
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 74e6da5bb56..a2b498759a9 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -48,6 +48,7 @@ SOURCES = \
unix/cdrom.c \
unix/debug.c \
unix/env.c \
+ unix/esync.c \
unix/file.c \
unix/loader.c \
unix/loadorder.c \
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
new file mode 100644
index 00000000000..7be4e03fa34
--- /dev/null
+++ b/dlls/ntdll/unix/esync.c
@@ -0,0 +1,270 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "wine/server.h"
+#include "wine/debug.h"
+
+#include "unix_private.h"
+#include "esync.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(esync);
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
+
+ return do_esync_cached;
+#else
+ static int once;
+ if (!once++)
+ FIXME("eventfd not supported on this platform.\n");
+ return 0;
+#endif
+}
+
+struct esync
+{
+ enum esync_type type;
+ int fd;
+ void *shm;
+};
+
+struct semaphore
+{
+ int max;
+ int count;
+};
+C_ASSERT(sizeof(struct semaphore) == 8);
+
+static char shm_name[29];
+static int shm_fd;
+static void **shm_addrs;
+static int shm_addrs_size; /* length of the allocated shm_addrs array */
+static long pagesize;
+
+static pthread_mutex_t shm_addrs_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void *get_shm( unsigned int idx )
+{
+ int entry = (idx * 8) / pagesize;
+ int offset = (idx * 8) % pagesize;
+ void *ret;
+
+ pthread_mutex_lock( &shm_addrs_mutex );
+
+ if (entry >= shm_addrs_size)
+ {
+ int new_size = max(shm_addrs_size * 2, entry + 1);
+
+ if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) )))
+ ERR("Failed to grow shm_addrs array to size %d.\n", shm_addrs_size);
+ memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) );
+ shm_addrs_size = new_size;
+ }
+
+ if (!shm_addrs[entry])
+ {
+ void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
+ if (addr == (void *)-1)
+ ERR("Failed to map page %d (offset %#lx).\n", entry, entry * pagesize);
+
+ TRACE("Mapping page %d at %p.\n", entry, addr);
+
+ if (InterlockedCompareExchangePointer( &shm_addrs[entry], addr, 0 ))
+ munmap( addr, pagesize ); /* someone beat us to it */
+ }
+
+ ret = (void *)((unsigned long)shm_addrs[entry] + offset);
+
+ pthread_mutex_unlock( &shm_addrs_mutex );
+
+ return ret;
+}
+
+/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
+ * This is copied and adapted from the fd cache code. */
+
+#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync))
+#define ESYNC_LIST_ENTRIES 256
+
+static struct esync *esync_list[ESYNC_LIST_ENTRIES];
+static struct esync esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];
+
+static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
+{
+ UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1;
+ *entry = idx / ESYNC_LIST_BLOCK_SIZE;
+ return idx % ESYNC_LIST_BLOCK_SIZE;
+}
+
+static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, void *shm )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES)
+ {
+ FIXME( "too many allocated handles, not caching %p\n", handle );
+ return FALSE;
+ }
+
+ if (!esync_list[entry]) /* do we need to allocate a new block of entries? */
+ {
+ if (!entry) esync_list[0] = esync_list_initial_block;
+ else
+ {
+ void *ptr = anon_mmap_alloc( ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync),
+ PROT_READ | PROT_WRITE );
+ if (ptr == MAP_FAILED) return FALSE;
+ esync_list[entry] = ptr;
+ }
+ }
+
+ if (!InterlockedCompareExchange( (int *)&esync_list[entry][idx].type, type, 0 ))
+ {
+ esync_list[entry][idx].fd = fd;
+ esync_list[entry][idx].shm = shm;
+ }
+ return &esync_list[entry][idx];
+}
+
+static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, int initval, int max )
+{
+ NTSTATUS ret;
+ data_size_t len;
+ struct object_attributes *objattr;
+ obj_handle_t fd_handle;
+ unsigned int shm_idx;
+ sigset_t sigset;
+ int fd;
+
+ if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
+
+ /* We have to synchronize on the fd cache CS so that our calls to
+ * receive_fd don't race with theirs. */
+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset );
+ SERVER_START_REQ( create_esync )
+ {
+ req->access = access;
+ req->initval = initval;
+ req->type = type;
+ req->max = max;
+ wine_server_add_data( req, objattr, len );
+ ret = wine_server_call( req );
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+ {
+ *handle = wine_server_ptr_handle( reply->handle );
+ type = reply->type;
+ shm_idx = reply->shm_idx;
+ fd = receive_fd( &fd_handle );
+ assert( wine_server_ptr_handle(fd_handle) == *handle );
+ }
+ }
+ SERVER_END_REQ;
+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset );
+
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+ {
+ add_to_list( *handle, type, fd, shm_idx ? get_shm( shm_idx ) : 0 );
+ TRACE("-> handle %p, fd %d.\n", *handle, fd);
+ }
+
+ free( objattr );
+ return ret;
+}
+
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
+{
+ TRACE("name %s, initial %d, max %d.\n",
+ attr ? debugstr_us(attr->ObjectName) : "<no name>", initial, max);
+
+ return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max );
+}
+
+void esync_init(void)
+{
+ struct stat st;
+
+ if (!do_esync())
+ {
+ /* make sure the server isn't running with WINEESYNC */
+ HANDLE handle;
+ NTSTATUS ret;
+
+ ret = create_esync( 0, &handle, 0, NULL, 0, 0 );
+ if (ret != STATUS_NOT_IMPLEMENTED)
+ {
+ ERR("Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.\n");
+ exit(1);
+ }
+
+ return;
+ }
+
+ if (stat( config_dir, &st ) == -1)
+ ERR("Cannot stat %s\n", config_dir);
+
+ if (st.st_ino != (unsigned long)st.st_ino)
+ sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino );
+ else
+ sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino );
+
+ if ((shm_fd = shm_open( shm_name, O_RDWR, 0644 )) == -1)
+ {
+ /* probably the server isn't running with WINEESYNC, tell the user and bail */
+ if (errno == ENOENT)
+ ERR("Failed to open esync shared memory file; make sure no stale wineserver instances are running without WINEESYNC.\n");
+ else
+ ERR("Failed to initialize shared memory: %s\n", strerror( errno ));
+ exit(1);
+ }
+
+ pagesize = sysconf( _SC_PAGESIZE );
+
+ shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
+ shm_addrs_size = 128;
+}
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
new file mode 100644
index 00000000000..5fec18860f8
--- /dev/null
+++ b/dlls/ntdll/unix/esync.h
@@ -0,0 +1,35 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int do_esync(void);
+extern void esync_init(void);
+
+extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
+
+
+/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
+ * don't race with theirs. It looks weird, I know.
+ *
+ * If we weren't trying to avoid touching the code I'd rename the mutex to
+ * "server_fd_mutex" or something similar. */
+extern pthread_mutex_t fd_cache_mutex;
+
+extern int receive_fd( obj_handle_t *handle );
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index aa120ae38ec..fdda50575d1 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -87,6 +87,7 @@
#include "winioctl.h"
#include "winternl.h"
#include "unix_private.h"
+#include "esync.h"
#include "wine/list.h"
#include "ntsyscalls.h"
#include "wine/debug.h"
@@ -1790,6 +1791,7 @@ static void start_main_thread(void)
signal_alloc_thread( teb );
dbg_init();
startup_info_size = server_init_process();
+ esync_init();
virtual_map_user_shared_data();
init_cpu_info();
init_files();
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 7211457387c..cd8dbbdcc10 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -103,7 +103,7 @@ sigset_t server_block_set; /* signals to block during server calls */
static int fd_socket = -1; /* socket to exchange file descriptors with the server */
static int initial_cwd = -1;
static pid_t server_pid;
-static pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t fd_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
/* atomically exchange a 64-bit value */
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
@@ -918,7 +918,7 @@ void wine_server_send_fd( int fd )
*
* Receive a file descriptor passed from the server.
*/
-static int receive_fd( obj_handle_t *handle )
+int receive_fd( obj_handle_t *handle )
{
struct iovec vec;
struct msghdr msghdr;
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index bfbcaf4a851..f21ceb80298 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -63,6 +63,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
+#include "esync.h"
WINE_DEFAULT_DEBUG_CHANNEL(sync);
@@ -272,6 +273,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
+ if (do_esync())
+ return esync_create_semaphore( handle, access, attr, initial, max );
+
SERVER_START_REQ( create_semaphore )
{
req->access = access;
diff --git a/server/esync.c b/server/esync.c
index 35b4833fd4c..75ef586df30 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -41,6 +41,7 @@
#include "handle.h"
#include "request.h"
#include "file.h"
+#include "esync.h"
int do_esync(void)
{
--
2.42.0

View File

@@ -1,108 +0,0 @@
From d8135b1bdafffc23be62c216edda9ac280045753 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:16:34 -0500
Subject: [PATCH] ntdll: Implement NtReleaseSemaphore().
---
dlls/ntdll/unix/esync.c | 43 +++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 3 +++
3 files changed, 47 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 7be4e03fa34..e8da4bd311b 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifdef HAVE_SYS_STAT_H
@@ -170,6 +171,16 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v
return &esync_list[entry][idx];
}
+static struct esync *get_cached_object( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
+ if (!esync_list[entry][idx].type) return NULL;
+
+ return &esync_list[entry][idx];
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
@@ -225,6 +236,38 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max );
}
+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
+{
+ struct esync *obj;
+ struct semaphore *semaphore;
+ uint64_t count64 = count;
+ ULONG current;
+
+ TRACE("%p, %d, %p.\n", handle, count, prev);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ semaphore = obj->shm;
+
+ do
+ {
+ current = semaphore->count;
+
+ if (count + current > semaphore->max)
+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED;
+ } while (InterlockedCompareExchange( &semaphore->count, count + current, current ) != current);
+
+ if (prev) *prev = current;
+
+ /* We don't have to worry about a race between increasing the count and
+ * write(). The fact that we were able to increase the count means that we
+ * have permission to actually write that many releases to the semaphore. */
+
+ if (write( obj->fd, &count64, sizeof(count64) ) == -1)
+ return errno_to_status( errno );
+
+ return STATUS_SUCCESS;
+}
+
void esync_init(void)
{
struct stat st;
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 5fec18860f8..cbaaed3e308 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -23,6 +23,7 @@ extern void esync_init(void);
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev );
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index f21ceb80298..c85f985b4f3 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -358,6 +358,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
{
unsigned int ret;
+ if (do_esync())
+ return esync_release_semaphore( handle, count, previous );
+
SERVER_START_REQ( release_semaphore )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

View File

@@ -1,77 +0,0 @@
From e57a0ae8ff11195fa4a29aa1c1ccc250c0036073 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:20:44 -0500
Subject: [PATCH] ntdll: Implement NtClose().
---
dlls/ntdll/unix/esync.c | 18 ++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/server.c | 4 ++++
3 files changed, 23 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index e8da4bd311b..e031e9cb94f 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -181,6 +181,24 @@ static struct esync *get_cached_object( HANDLE handle )
return &esync_list[entry][idx];
}
+NTSTATUS esync_close( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ TRACE("%p.\n", handle);
+
+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
+ {
+ if (InterlockedExchange((int *)&esync_list[entry][idx].type, 0))
+ {
+ close( esync_list[entry][idx].fd );
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_HANDLE;
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index cbaaed3e308..c63491dcaad 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -20,6 +20,7 @@
extern int do_esync(void);
extern void esync_init(void);
+extern NTSTATUS esync_close( HANDLE handle );
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max);
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index cd8dbbdcc10..00d665d9e62 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -79,6 +79,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
+#include "esync.h"
#include "ddk/wdm.h"
WINE_DEFAULT_DEBUG_CHANNEL(server);
@@ -1839,6 +1840,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
* retrieve it again */
fd = remove_fd_from_cache( handle );
+ if (do_esync())
+ esync_close( handle );
+
SERVER_START_REQ( close_handle )
{
req->handle = wine_server_obj_handle( handle );
--
2.42.0

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