You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-12-15 08:03:15 -08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
265554a9da | ||
|
|
38d4b8ca78 | ||
|
|
9c06e8eab3 | ||
|
|
78a888cd3d | ||
|
|
1f7871a75c | ||
|
|
815194acd6 | ||
|
|
7e9e516c71 | ||
|
|
ea30d81923 | ||
|
|
a8cce16566 | ||
|
|
20ba4773d6 | ||
|
|
64988e15df | ||
|
|
1a739efaa4 | ||
|
|
27156e4a6e | ||
|
|
112b476921 | ||
|
|
2465e06751 | ||
|
|
0e9c421030 | ||
|
|
04570cc4c7 | ||
|
|
c062a34be3 | ||
|
|
42ab95dc1f | ||
|
|
e1dea6b9ac | ||
|
|
74477d5d72 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1,2 @@
|
||||
Fixes: [45533] - Implement D3DX11CreateTextureFromMemory
|
||||
Disabled: True
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ¶m->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
|
||||
|
||||
1
patches/d3dx9-setrawvalue/definition
Normal file
1
patches/d3dx9-setrawvalue/definition
Normal file
@@ -0,0 +1 @@
|
||||
Fixes: [48598] d3dx9: Improve Rendering in MudRunner.
|
||||
@@ -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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Fixes: [32572] Support for ID3DXSkinInfoImpl_UpdateSkinnedMesh
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
Fixes: [37019] Don't set HWTRANSFORMANDLIGHT flag on d3d7 RGB device
|
||||
Fixes: [27002] Properly initialize caps->dwZBufferBitDepths in ddraw7_GetCaps
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user