https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d255223474c491edc24ef…
commit d255223474c491edc24efad314e6f56328589604
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sun Jan 21 22:15:58 2018 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Sun Jan 21 22:15:58 2018 +0100
[DDRAW] Sync with Wine 3.0. CORE-14225
---
dll/directx/wine/ddraw/ddraw.c | 221 ++++++++-------------------------
dll/directx/wine/ddraw/ddraw_private.h | 10 +-
dll/directx/wine/ddraw/device.c | 50 +++++---
dll/directx/wine/ddraw/executebuffer.c | 5 +-
dll/directx/wine/ddraw/surface.c | 182 ++++++++++++---------------
dll/directx/wine/ddraw/vertexbuffer.c | 5 +-
dll/directx/wine/ddraw/viewport.c | 4 +-
media/doc/README.WINE | 2 +-
8 files changed, 175 insertions(+), 304 deletions(-)
diff --git a/dll/directx/wine/ddraw/ddraw.c b/dll/directx/wine/ddraw/ddraw.c
index 9712bb53ae..2ab9edd015 100644
--- a/dll/directx/wine/ddraw/ddraw.c
+++ b/dll/directx/wine/ddraw/ddraw.c
@@ -45,7 +45,6 @@ static struct enum_device_entry
char interface_name[100];
char device_name[100];
const GUID *device_guid;
- DWORD remove_caps;
} device_list7[] =
{
/* T&L HAL device */
@@ -53,7 +52,6 @@ static struct enum_device_entry
"WINE Direct3D7 Hardware Transform and Lighting acceleration using
WineD3D",
"Wine D3D7 T&L HAL",
&IID_IDirect3DTnLHalDevice,
- 0,
},
/* HAL device */
@@ -61,7 +59,6 @@ static struct enum_device_entry
"WINE Direct3D7 Hardware acceleration using WineD3D",
"Direct3D HAL",
&IID_IDirect3DHALDevice,
- 0,
},
/* RGB device */
@@ -69,7 +66,6 @@ static struct enum_device_entry
"WINE Direct3D7 RGB Software Emulation using WineD3D",
"Wine D3D7 RGB",
&IID_IDirect3DRGBDevice,
- D3DDEVCAPS_HWTRANSFORMANDLIGHT,
},
};
@@ -1419,23 +1415,10 @@ HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw,
D3DDEVICEDESC7 *caps)
caps->dwMinTextureHeight = 1;
/* Convert DWORDs safely to WORDs */
- if (wined3d_caps.MaxTextureBlendStages > 0xffff)
- caps->wMaxTextureBlendStages = 0xffff;
- else
- caps->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
- if (wined3d_caps.MaxSimultaneousTextures > 0xffff)
- caps->wMaxSimultaneousTextures = 0xffff;
- else
- caps->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
-
- if (wined3d_caps.MaxUserClipPlanes > 0xffff)
- caps->wMaxUserClipPlanes = 0xffff;
- else
- caps->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
- if (wined3d_caps.MaxVertexBlendMatrices > 0xffff)
- caps->wMaxVertexBlendMatrices = 0xffff;
- else
- caps->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
+ caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
+ caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures,
0xffff);
+ caps->wMaxUserClipPlanes = min(wined3d_caps.MaxUserClipPlanes,
D3DMAXUSERCLIPPLANES);
+ caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
caps->deviceGUID = IID_IDirect3DTnLHalDevice;
@@ -1447,28 +1430,6 @@ 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->u1.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
*
@@ -1549,10 +1510,6 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS
*DriverCaps, DD
caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
- caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
-
- IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface,
&IID_IDirect3DHALDevice, enum_zbuffer, &caps);
-
if(DriverCaps)
{
DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
@@ -1665,17 +1622,14 @@ static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface,
DDSURFACEDESC2
struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
struct wined3d_display_mode mode;
HRESULT hr;
- DWORD Size;
TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
- wined3d_mutex_lock();
/* This seems sane */
- if (!DDSD)
- {
- wined3d_mutex_unlock();
+ if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize !=
sizeof(DDSURFACEDESC2)))
return DDERR_INVALIDPARAMS;
- }
+
+ wined3d_mutex_lock();
if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d,
WINED3DADAPTER_DEFAULT, &mode, NULL)))
{
@@ -1684,10 +1638,8 @@ static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface,
DDSURFACEDESC2
return hr;
}
- Size = DDSD->dwSize;
- memset(DDSD, 0, Size);
-
- DDSD->dwSize = Size;
+ memset(DDSD, 0, DDSD->dwSize);
+ DDSD->dwSize = sizeof(*DDSD);
DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH |
DDSD_REFRESHRATE;
DDSD->dwWidth = mode.width;
DDSD->dwHeight = mode.height;
@@ -1720,21 +1672,25 @@ static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface,
DDSURFACEDESC2
static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC
*surface_desc)
{
struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
+ HRESULT hr;
TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
- /* FIXME: Test sizes, properly convert surface_desc */
- return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2
*)surface_desc);
+ hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2
*)surface_desc);
+ if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
+ return hr;
}
static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC
*surface_desc)
{
struct ddraw *ddraw = impl_from_IDirectDraw(iface);
+ HRESULT hr;
TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
- /* FIXME: Test sizes, properly convert surface_desc */
- return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2
*)surface_desc);
+ hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2
*)surface_desc);
+ if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
+ return hr;
}
/*****************************************************************************
@@ -2101,14 +2057,7 @@ static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID
riid)
*****************************************************************************/
static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
{
- struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
-
- TRACE("iface %p.\n", iface);
-
- ddraw->flags |= DDRAW_GDI_FLIP;
-
- if (ddraw->primary)
- ddraw_surface_update_frontbuffer(ddraw->primary, NULL, FALSE);
+ FIXME("iface %p stub!\n", iface);
return DD_OK;
}
@@ -3240,97 +3189,46 @@ static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface,
DWORD Flags,
{
struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
struct ddraw_surface *surf;
- DWORD match_flags = Flags & (DDENUMSURFACES_ALL | DDENUMSURFACES_NOMATCH |
DDENUMSURFACES_MATCH);
+ BOOL all, nomatch;
+ DDSURFACEDESC2 desc;
+ struct list *entry, *entry2;
TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
iface, Flags, DDSD, Context, Callback);
+ all = Flags & DDENUMSURFACES_ALL;
+ nomatch = Flags & DDENUMSURFACES_NOMATCH;
+
if (!Callback)
return DDERR_INVALIDPARAMS;
- if (Flags & DDENUMSURFACES_CANBECREATED)
- {
- IDirectDrawSurface7 *surface;
- DDSURFACEDESC2 testdesc;
- HRESULT hr;
-
- if (match_flags != DDENUMSURFACES_MATCH)
- return DDERR_INVALIDPARAMS;
-
- if (!DDSD)
- return DDERR_INVALIDPARAMS;
+ wined3d_mutex_lock();
- memcpy(&testdesc, DDSD, sizeof(testdesc));
- if (!(testdesc.dwFlags & DDSD_WIDTH))
- {
- testdesc.dwFlags |= DDSD_WIDTH;
- testdesc.dwWidth = 512;
- }
- if (!(testdesc.dwFlags & DDSD_HEIGHT))
- {
- testdesc.dwFlags |= DDSD_HEIGHT;
- testdesc.dwHeight = 512;
- }
+ /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
+ LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list)
+ {
+ surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
- hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
- if (SUCCEEDED(hr))
+ if (!surf->iface_count)
{
- surf = unsafe_impl_from_IDirectDrawSurface7(surface);
- Callback(NULL, &surf->surface_desc, Context);
- IDirectDrawSurface7_Release(surface);
+ WARN("Not enumerating surface %p because it doesn't have any
references.\n", surf);
+ continue;
}
- else
- ERR("Failed to create surface, hr %#x.\n", hr);
- }
- else if (Flags & DDENUMSURFACES_DOESEXIST)
- {
- BOOL all, nomatch;
- DDSURFACEDESC2 desc;
- struct list *entry, *entry2;
-
- /* a combination of match flags is not allowed */
- if (match_flags != 0 &&
- match_flags != DDENUMSURFACES_ALL &&
- match_flags != DDENUMSURFACES_MATCH &&
- match_flags != DDENUMSURFACES_NOMATCH)
- return DDERR_INVALIDPARAMS;
-
- all = (Flags & DDENUMSURFACES_ALL) != 0;
- nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
- if (!all && !DDSD)
- return DDERR_INVALIDPARAMS;
-
- wined3d_mutex_lock();
-
- /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
- LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list)
+ if (all || (nomatch != ddraw_match_surface_desc(DDSD,
&surf->surface_desc)))
{
- surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
-
- if (!surf->iface_count)
+ TRACE("Enumerating surface %p.\n", surf);
+ desc = surf->surface_desc;
+ IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
+ if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) !=
DDENUMRET_OK)
{
- WARN("Not enumerating surface %p because it doesn't have any
references.\n", surf);
- continue;
- }
-
- if (all || (nomatch != ddraw_match_surface_desc(DDSD,
&surf->surface_desc)))
- {
- TRACE("Enumerating surface %p.\n", surf);
- desc = surf->surface_desc;
- IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
- if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context)
!= DDENUMRET_OK)
- {
- wined3d_mutex_unlock();
- return DD_OK;
- }
+ wined3d_mutex_unlock();
+ return DD_OK;
}
}
-
- wined3d_mutex_unlock();
}
- else
- return DDERR_INVALIDPARAMS;
+
+ wined3d_mutex_unlock();
return DD_OK;
}
@@ -3728,7 +3626,6 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface,
LPD3DENUMDEVICESCALLBA
{
struct ddraw *ddraw = impl_from_IDirect3D7(iface);
D3DDEVICEDESC7 device_desc7;
- DWORD dev_caps;
HRESULT hr;
size_t i;
@@ -3745,15 +3642,11 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface,
LPD3DENUMDEVICESCALLBA
return hr;
}
- dev_caps = device_desc7.dwDevCaps;
-
for (i = 0; i < sizeof(device_list7)/sizeof(device_list7[0]); i++)
{
HRESULT ret;
device_desc7.deviceGUID = *device_list7[i].device_guid;
- device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
-
ret = callback(device_list7[i].interface_name, device_list7[i].device_name,
&device_desc7, context);
if (ret != DDENUMRET_OK)
{
@@ -4151,8 +4044,8 @@ static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface,
D3DFINDDEVICESEARCH *fd
if (!fds || !fdr) return DDERR_INVALIDPARAMS;
- if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize !=
sizeof(D3DFINDDEVICERESULT1) &&
- fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize !=
sizeof(D3DFINDDEVICERESULT)))
+ if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
+ || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
return DDERR_INVALIDPARAMS;
if ((fds->dwFlags & D3DFDS_COLORMODEL)
@@ -4181,24 +4074,8 @@ static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface,
D3DFINDDEVICESEARCH *fd
/* Now return our own GUID */
ddraw_d3dcaps1_from_7(&desc1, &desc7);
fdr->guid = IID_D3DDEVICE_WineD3D;
-
- if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1))
- {
- D3DFINDDEVICERESULT1 *fdr1 = (D3DFINDDEVICERESULT1 *)fdr;
- memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc));
- memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc));
- }
- else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2))
- {
- D3DFINDDEVICERESULT2 *fdr2 = (D3DFINDDEVICERESULT2 *)fdr;
- memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc));
- memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc));
- }
- else
- {
- fdr->ddHwDesc = desc1;
- fdr->ddSwDesc = desc1;
- }
+ fdr->ddHwDesc = desc1;
+ fdr->ddSwDesc = desc1;
TRACE("Returning Wine's wined3d device with (undumped)
capabilities.\n");
@@ -4255,7 +4132,7 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID
riid,
TRACE("iface %p, riid %s, surface %p, device %p.\n", iface,
debugstr_guid(riid), surface, device);
wined3d_mutex_lock();
- if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7,
&object, NULL)))
+ if (SUCCEEDED(hr = d3d_device_create(ddraw, target, (IUnknown *)surface, 7,
&object, NULL)))
{
*device = &object->IDirect3DDevice7_iface;
}
@@ -4284,7 +4161,7 @@ static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID
riid,
return CLASS_E_NOAGGREGATION;
wined3d_mutex_lock();
- if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface,
3, &device_impl, NULL)))
+ if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 3,
&device_impl, NULL)))
{
*device = &device_impl->IDirect3DDevice3_iface;
}
@@ -4310,7 +4187,7 @@ static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID
riid,
iface, debugstr_guid(riid), surface, device);
wined3d_mutex_lock();
- if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface,
2, &device_impl, NULL)))
+ if (SUCCEEDED(hr = d3d_device_create(ddraw, surface_impl, (IUnknown *)surface, 2,
&device_impl, NULL)))
{
*device = &device_impl->IDirect3DDevice2_iface;
}
@@ -4682,7 +4559,7 @@ static const struct IDirectDraw2Vtbl ddraw2_vtbl =
ddraw2_GetAvailableVidMem,
};
-static struct IDirectDrawVtbl ddraw1_vtbl =
+static const struct IDirectDrawVtbl ddraw1_vtbl =
{
/* IUnknown */
ddraw1_QueryInterface,
diff --git a/dll/directx/wine/ddraw/ddraw_private.h
b/dll/directx/wine/ddraw/ddraw_private.h
index a7d19d32f6..04ee59c05f 100644
--- a/dll/directx/wine/ddraw/ddraw_private.h
+++ b/dll/directx/wine/ddraw/ddraw_private.h
@@ -44,6 +44,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
extern const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops DECLSPEC_HIDDEN;
extern DWORD force_refresh_rate DECLSPEC_HIDDEN;
@@ -62,14 +64,13 @@ struct FvfToDecl
#define DDRAW_NO3D 0x00000008
#define DDRAW_SCL_DDRAW1 0x00000010
#define DDRAW_SCL_RECURSIVE 0x00000020
-#define DDRAW_GDI_FLIP 0x00000040
#define DDRAW_STRIDE_ALIGNMENT 8
#define DDRAW_WINED3D_FLAGS (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \
| WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES |
WINED3D_PIXEL_CENTER_INTEGER \
| WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \
- | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_LIMIT_VIEWPORT)
+ | WINED3D_LEGACY_CUBEMAP_FILTERING)
enum ddraw_device_state
{
@@ -308,7 +309,6 @@ struct d3d_device
IUnknown IUnknown_inner;
LONG ref;
UINT version;
- BOOL hw;
IUnknown *outer_unknown;
struct wined3d_device *wined3d_device;
@@ -349,9 +349,11 @@ struct d3d_device
/* Handle management */
struct ddraw_handle_table handle_table;
D3DMATRIXHANDLE world, proj, view;
+
+ struct wined3d_vec4 user_clip_planes[D3DMAXUSERCLIPPLANES];
};
-HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface
*target, IUnknown *rt_iface,
+HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown
*rt_iface,
UINT version, struct d3d_device **device, IUnknown *outer_unknown)
DECLSPEC_HIDDEN;
enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
DECLSPEC_HIDDEN;
diff --git a/dll/directx/wine/ddraw/device.c b/dll/directx/wine/ddraw/device.c
index 6b93266467..fe48ad3b36 100644
--- a/dll/directx/wine/ddraw/device.c
+++ b/dll/directx/wine/ddraw/device.c
@@ -1166,7 +1166,7 @@ static HRESULT WINAPI
d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
* IDirect3DDevice2::EnumTextureformats
*
* EnumTextureFormats for Version 1 and 2, see
- * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
+ * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
*
* This version has a different callback and does not enumerate FourCC
* formats
@@ -1852,7 +1852,7 @@ static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
return DDERR_INVALIDCAPS;
}
- if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps &
DDSCAPS_VIDEOMEMORY))
+ if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
WARN("Surface %p is not in video memory.\n", target_impl);
wined3d_mutex_unlock();
@@ -1928,7 +1928,7 @@ static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3
*iface,
return DDERR_INVALIDPIXELFORMAT;
}
- if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps &
DDSCAPS_VIDEOMEMORY))
+ if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
WARN("Surface %p is not in video memory.\n", target_impl);
IDirectDrawSurface4_AddRef(target);
@@ -1977,7 +1977,7 @@ static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2
*iface,
return DDERR_INVALIDPIXELFORMAT;
}
- if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps &
DDSCAPS_VIDEOMEMORY))
+ if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
WARN("Surface %p is not in video memory.\n", target_impl);
IDirectDrawSurface_AddRef(target);
@@ -6453,6 +6453,7 @@ static HRESULT WINAPI
d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *i
static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE
*plane)
{
struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
+ const struct wined3d_vec4 *wined3d_plane;
HRESULT hr;
TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
@@ -6460,8 +6461,19 @@ static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface,
DWORD idx, D3DV
if (!plane)
return DDERR_INVALIDPARAMS;
+ wined3d_plane = (struct wined3d_vec4 *)plane;
+
wined3d_mutex_lock();
- hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct
wined3d_vec4 *)plane);
+ hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, wined3d_plane);
+ if (idx < ARRAY_SIZE(device->user_clip_planes))
+ {
+ device->user_clip_planes[idx] = *wined3d_plane;
+ if (hr == WINED3DERR_INVALIDCALL)
+ {
+ WARN("Clip plane %u is not supported.\n", idx);
+ hr = D3D_OK;
+ }
+ }
wined3d_mutex_unlock();
return hr;
@@ -6501,6 +6513,7 @@ static HRESULT WINAPI
d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *ifa
static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE
*plane)
{
struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
+ struct wined3d_vec4 *wined3d_plane;
HRESULT hr;
TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
@@ -6508,8 +6521,16 @@ static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface,
DWORD idx, D3DV
if (!plane)
return DDERR_INVALIDPARAMS;
+ wined3d_plane = (struct wined3d_vec4 *)plane;
+
wined3d_mutex_lock();
- hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct
wined3d_vec4 *)plane);
+ hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, wined3d_plane);
+ if (hr == WINED3DERR_INVALIDCALL && idx <
ARRAY_SIZE(device->user_clip_planes))
+ {
+ WARN("Clip plane %u is not supported.\n", idx);
+ *wined3d_plane = device->user_clip_planes[idx];
+ hr = D3D_OK;
+ }
wined3d_mutex_unlock();
return hr;
@@ -6866,7 +6887,7 @@ enum wined3d_depth_buffer_type
d3d_device_update_depth_stencil(struct d3d_device
return WINED3D_ZB_TRUE;
}
-static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, BOOL hw,
+static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown
*outer_unknown)
{
static const D3DMATRIX ident =
@@ -6889,7 +6910,6 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct
ddraw *ddraw, B
device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
device->ref = 1;
device->version = version;
- device->hw = hw;
if (outer_unknown)
device->outer_unknown = outer_unknown;
@@ -6940,18 +6960,14 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct
ddraw *ddraw, B
return D3D_OK;
}
-HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface
*target, IUnknown *rt_iface,
+HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown
*rt_iface,
UINT version, struct d3d_device **device, IUnknown *outer_unknown)
{
struct d3d_device *object;
- BOOL hw = TRUE;
HRESULT hr;
- TRACE("ddraw %p, guid %s, target %p, version %u, device %p, outer_unknown
%p.\n",
- ddraw, debugstr_guid(guid), target, version, device, outer_unknown);
-
- if (IsEqualGUID(guid, &IID_IDirect3DRGBDevice))
- hw = FALSE;
+ TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
+ ddraw, target, version, device, outer_unknown);
if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
|| (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
@@ -6966,7 +6982,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid,
struct ddraw_su
return DDERR_NOPALETTEATTACHED;
}
- if (hw && !(target->surface_desc.ddsCaps.dwCaps &
DDSCAPS_VIDEOMEMORY))
+ if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
{
WARN("Surface %p is not in video memory.\n", target);
return D3DERR_SURFACENOTINVIDMEM;
@@ -6993,7 +7009,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid,
struct ddraw_su
return DDERR_OUTOFMEMORY;
}
- if (FAILED(hr = d3d_device_init(object, ddraw, hw, target, rt_iface, version,
outer_unknown)))
+ if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version,
outer_unknown)))
{
WARN("Failed to initialize device, hr %#x.\n", hr);
HeapFree(GetProcessHeap(), 0, object);
diff --git a/dll/directx/wine/ddraw/executebuffer.c
b/dll/directx/wine/ddraw/executebuffer.c
index 1bc5b5c5fb..7b68bd70b5 100644
--- a/dll/directx/wine/ddraw/executebuffer.c
+++ b/dll/directx/wine/ddraw/executebuffer.c
@@ -297,10 +297,7 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer
*buffer,
ci->wStart, ci->wDest, ci->dwCount,
ci->dwFlags);
if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
- {
- static int once;
- if (!once++) FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not
implemented.\n");
- }
+ FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not
implemented.\n");
if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
FIXME("D3DPROCESSVERTICES_NOCOLOR not
implemented.\n");
diff --git a/dll/directx/wine/ddraw/surface.c b/dll/directx/wine/ddraw/surface.c
index 74f2d15d27..abae18ba6c 100644
--- a/dll/directx/wine/ddraw/surface.c
+++ b/dll/directx/wine/ddraw/surface.c
@@ -37,7 +37,6 @@ static inline struct ddraw_surface
*impl_from_IDirectDrawGammaControl(IDirectDra
* to support windowless rendering first. */
HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect,
BOOL read)
{
- struct ddraw *ddraw = surface->ddraw;
HDC surface_dc, screen_dc;
int x, y, w, h;
HRESULT hr;
@@ -58,14 +57,14 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface
*surface, const RE
if (w <= 0 || h <= 0)
return DD_OK;
- if (ddraw->swapchain_window && !(ddraw->flags & DDRAW_GDI_FLIP))
+ if (surface->ddraw->swapchain_window)
{
/* Nothing to do, we control the frontbuffer, or at least the parts we
* care about. */
if (read)
return DD_OK;
- return wined3d_texture_blt(ddraw->wined3d_frontbuffer, 0, rect,
+ return wined3d_texture_blt(surface->ddraw->wined3d_frontbuffer, 0, rect,
surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL,
WINED3D_TEXF_POINT);
}
@@ -204,7 +203,7 @@ static HRESULT WINAPI
ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface,
{
HRESULT hr;
- if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown
*)&This->IDirectDrawSurface_iface,
+ if (FAILED(hr = d3d_device_create(This->ddraw, This, (IUnknown
*)&This->IDirectDrawSurface_iface,
1, &This->device1, (IUnknown
*)&This->IDirectDrawSurface_iface)))
{
This->device1 = NULL;
@@ -5181,46 +5180,6 @@ static struct ddraw_surface *get_sub_mimaplevel(struct
ddraw_surface *surface)
return impl_from_IDirectDrawSurface7(next_level);
}
-static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2)
-{
- if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) !=
- (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)))
- return FALSE;
-
- if (format1->dwFlags & (DDPF_RGB|DDPF_YUV))
- {
- if (!(format1->dwFlags & DDPF_ALPHA))
- {
- /* The RGB and YUV bits are stored in the same fields */
- if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount)
- return FALSE;
-
- if (format1->u2.dwRBitMask != format2->u2.dwRBitMask)
- return FALSE;
-
- if (format1->u3.dwGBitMask != format2->u3.dwGBitMask)
- return FALSE;
-
- if (format1->u4.dwBBitMask != format2->u4.dwBBitMask)
- return FALSE;
- }
-
- if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA))
- {
- if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask)
- return FALSE;
- }
- }
-
- if (format1->dwFlags & DDPF_FOURCC)
- {
- if (format1->dwFourCC != format2->dwFourCC)
- return FALSE;
- }
-
- return TRUE;
-}
-
/*****************************************************************************
* IDirect3DTexture2::Load
*
@@ -5242,7 +5201,7 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface,
IDirect3DTextu
{
struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
- RECT src_rect, dst_rect;
+ struct wined3d_resource *dst_resource, *src_resource;
HRESULT hr;
TRACE("iface %p, src_texture %p.\n", iface, src_texture);
@@ -5255,60 +5214,90 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface,
IDirect3DTextu
wined3d_mutex_lock();
+ dst_resource = wined3d_texture_get_resource(dst_surface->wined3d_texture);
+ src_resource = wined3d_texture_get_resource(src_surface->wined3d_texture);
+
+ if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
+ != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
+ || (src_surface->surface_desc.u2.dwMipMapCount !=
dst_surface->surface_desc.u2.dwMipMapCount))
+ {
+ ERR("Trying to load surfaces with different mip-map counts.\n");
+ }
+
for (;;)
{
- DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
+ struct ddraw_palette *dst_pal, *src_pal;
+ DDSURFACEDESC *src_desc, *dst_desc;
TRACE("Copying surface %p to surface %p.\n", src_surface,
dst_surface);
- if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
- &dst_surface->surface_desc.u4.ddpfPixelFormat))
- {
- struct ddraw_palette *dst_pal, *src_pal;
+ /* Suppress the ALLOCONLOAD flag */
+ dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
- /* Get the palettes */
- dst_pal = dst_surface->palette;
- src_pal = src_surface->palette;
+ /* Get the palettes */
+ dst_pal = dst_surface->palette;
+ src_pal = src_surface->palette;
- if (src_pal)
- {
- PALETTEENTRY palent[256];
+ if (src_pal)
+ {
+ PALETTEENTRY palent[256];
- if (!dst_pal)
- {
- wined3d_mutex_unlock();
- return DDERR_NOPALETTEATTACHED;
- }
- IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface,
0, 0, 256, palent);
- IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface,
0, 0, 256, palent);
+ if (!dst_pal)
+ {
+ wined3d_mutex_unlock();
+ return DDERR_NOPALETTEATTACHED;
}
+ IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0,
0, 256, palent);
+ IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0,
0, 256, palent);
+ }
+ /* Copy one surface on the other */
+ dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
+ src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
+
+ if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight !=
dst_desc->dwHeight))
+ {
+ /* Should also check for same pixel format, u1.lPitch, ... */
+ ERR("Error in surface sizes.\n");
+ wined3d_mutex_unlock();
+ return D3DERR_TEXTURE_LOAD_FAILED;
+ }
+ else
+ {
+ struct wined3d_map_desc src_map_desc, dst_map_desc;
+
+ /* Copy the src blit color key if the source has one, don't erase
+ * the destination's ckey if the source has none */
if (src_desc->dwFlags & DDSD_CKSRCBLT)
{
IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
}
- }
- else
- {
- if (src_desc->dwFlags & DDSD_CKSRCBLT)
- return E_FAIL;
- }
- /* Suppress the ALLOCONLOAD flag */
- dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
+ if (FAILED(hr = wined3d_resource_map(src_resource,
+ src_surface->sub_resource_idx, &src_map_desc, NULL, 0)))
+ {
+ ERR("Failed to lock source surface, hr %#x.\n", hr);
+ wined3d_mutex_unlock();
+ return D3DERR_TEXTURE_LOAD_FAILED;
+ }
- SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth,
src_surface->surface_desc.dwHeight);
- SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth,
dst_surface->surface_desc.dwHeight);
+ if (FAILED(hr = wined3d_resource_map(dst_resource,
+ dst_surface->sub_resource_idx, &dst_map_desc, NULL, 0)))
+ {
+ ERR("Failed to lock destination surface, hr %#x.\n", hr);
+ wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
+ wined3d_mutex_unlock();
+ return D3DERR_TEXTURE_LOAD_FAILED;
+ }
- hr = wined3d_texture_blt(dst_surface->wined3d_texture,
dst_surface->sub_resource_idx, &dst_rect,
- src_surface->wined3d_texture,
src_surface->sub_resource_idx, &src_rect,
- 0, NULL, WINED3D_TEXF_LINEAR);
- if (FAILED(hr))
- {
- ERR("Failed to blit surface, hr %#x.\n", hr);
- wined3d_mutex_unlock();
- return hr;
+ if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags &
DDPF_FOURCC)
+ memcpy(dst_map_desc.data, src_map_desc.data,
src_surface->surface_desc.u1.dwLinearSize);
+ else
+ memcpy(dst_map_desc.data, src_map_desc.data, src_map_desc.row_pitch *
src_desc->dwHeight);
+
+ wined3d_resource_unmap(dst_resource, dst_surface->sub_resource_idx);
+ wined3d_resource_unmap(src_resource, src_surface->sub_resource_idx);
}
if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
@@ -5321,11 +5310,12 @@ static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface,
IDirect3DTextu
else
dst_surface = NULL;
- if (src_surface && !dst_surface)
- return DDERR_NOTFOUND;
-
if (!src_surface || !dst_surface)
+ {
+ if (src_surface != dst_surface)
+ ERR("Loading surface with different mipmap structure.\n");
break;
+ }
}
wined3d_mutex_unlock();
@@ -5555,7 +5545,7 @@ static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
ddraw_surface2_PageUnlock,
};
-static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
+static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
{
/* IUnknown */
ddraw_surface1_QueryInterface,
@@ -6007,6 +5997,9 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const
DDSURFACEDESC2 *surface_
HeapFree(GetProcessHeap(), 0, texture);
return hr_ddraw_from_wined3d(hr);
}
+
+ wined3d_device_set_render_state(ddraw->wined3d_device,
WINED3D_RS_ZENABLE,
+ !!swapchain_desc.enable_auto_depth_stencil);
}
}
@@ -6102,24 +6095,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const
DDSURFACEDESC2 *surface_
if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
- /*
- * The ddraw RGB device allows to use system memory surfaces as rendering
target.
- * This does not cause problems because the RGB device does software
rasterization
- * though it will fail with hardware accelerated ddraw. In order to be partially
- * compatible with games requesting explicitly the RGB device, we ignore the
- * specified location and try to create rendering targets in video memory if
- * possible.
- */
- if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
- SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d,
WINED3DADAPTER_DEFAULT,
- WINED3D_DEVICE_TYPE_HAL, mode.format_id,
WINED3DUSAGE_RENDERTARGET,
- WINED3D_RTYPE_TEXTURE_2D, wined3d_desc.format)))
- {
- FIXME("Application wants to create rendering target in system memory,
using video memory instead\n");
- wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
- }
- else
- wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
+ wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
}
else
{
diff --git a/dll/directx/wine/ddraw/vertexbuffer.c
b/dll/directx/wine/ddraw/vertexbuffer.c
index 04d7adb94a..155a8dd3ff 100644
--- a/dll/directx/wine/ddraw/vertexbuffer.c
+++ b/dll/directx/wine/ddraw/vertexbuffer.c
@@ -159,6 +159,9 @@ static HRESULT WINAPI d3d_vertex_buffer7_Lock(IDirect3DVertexBuffer7
*iface,
TRACE("iface %p, flags %#x, data %p, data_size %p.\n", iface, flags, data,
data_size);
+ if (buffer->version != 7)
+ flags &= ~(DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS);
+
/* Writeonly: Pointless. Event: Unsupported by native according to the sdk
* nosyslock: Not applicable
*/
@@ -246,7 +249,7 @@ static HRESULT WINAPI d3d_vertex_buffer7_Unlock(IDirect3DVertexBuffer7
*iface)
* SrcIndex: Index of the first vertex in the src buffer to process
* D3DDevice: Device to use for transformation
* Flags: 0 for default, D3DPV_DONOTCOPYDATA to prevent copying
- * unchaned vertices
+ * unchanged vertices
*
* Returns:
* D3D_OK on success
diff --git a/dll/directx/wine/ddraw/viewport.c b/dll/directx/wine/ddraw/viewport.c
index 04eaa4b23a..a62cc319ec 100644
--- a/dll/directx/wine/ddraw/viewport.c
+++ b/dll/directx/wine/ddraw/viewport.c
@@ -1127,7 +1127,7 @@ struct d3d_viewport
*unsafe_impl_from_IDirect3DViewport2(IDirect3DViewport2 *ifa
/* IDirect3DViewport and IDirect3DViewport3 use the same iface. */
if (!iface) return NULL;
assert(iface->lpVtbl == (IDirect3DViewport2Vtbl *)&d3d_viewport_vtbl);
- return CONTAINING_RECORD((IDirect3DViewport3 *)iface, struct d3d_viewport,
IDirect3DViewport3_iface);
+ return CONTAINING_RECORD(iface, struct d3d_viewport, IDirect3DViewport3_iface);
}
struct d3d_viewport *unsafe_impl_from_IDirect3DViewport(IDirect3DViewport *iface)
@@ -1135,7 +1135,7 @@ struct d3d_viewport
*unsafe_impl_from_IDirect3DViewport(IDirect3DViewport *iface
/* IDirect3DViewport and IDirect3DViewport3 use the same iface. */
if (!iface) return NULL;
assert(iface->lpVtbl == (IDirect3DViewportVtbl *)&d3d_viewport_vtbl);
- return CONTAINING_RECORD((IDirect3DViewport3 *)iface, struct d3d_viewport,
IDirect3DViewport3_iface);
+ return CONTAINING_RECORD(iface, struct d3d_viewport, IDirect3DViewport3_iface);
}
void d3d_viewport_init(struct d3d_viewport *viewport, struct ddraw *ddraw)
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 375b675a93..fb678a5a5e 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -28,7 +28,7 @@ reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-2.16
reactos/dll/directx/wine/d3drm # Synced to WineStaging-2.16
reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-2.16
reactos/dll/directx/wine/d3dxof # Synced to WineStaging-2.9
-reactos/dll/directx/wine/ddraw # Synced to WineStaging-2.16
+reactos/dll/directx/wine/ddraw # Synced to Wine-3.0
reactos/dll/directx/wine/devenum # Synced to WineStaging-2.9
reactos/dll/directx/wine/dinput # Synced to WineStaging-2.16
reactos/dll/directx/wine/dinput8 # Synced to WineStaging-2.9