From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/ddraw.c | 40 +++++++++++++++++++++++++++----------- dlls/ddraw/ddraw_private.h | 6 +++++- dlls/ddraw/device.c | 10 ++-------- dlls/ddraw/main.c | 4 ++-- dlls/ddraw/surface.c | 16 ++++++++++----- dlls/ddraw/tests/d3d.c | 9 ++------- dlls/ddraw/vertexbuffer.c | 2 +- 7 files changed, 52 insertions(+), 35 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 121944b1000..5cea4677439 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -420,6 +420,7 @@ static void ddraw_destroy_swapchain(struct ddraw *ddraw) *****************************************************************************/ static void ddraw_destroy(struct ddraw *This) { + struct d3d_device *device; IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL); IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
@@ -440,8 +441,10 @@ static void ddraw_destroy(struct ddraw *This) wined3d_device_decref(This->wined3d_device); wined3d_decref(This->wined3d);
- if (This->d3ddevice) - This->d3ddevice->ddraw = NULL; + LIST_FOR_EACH_ENTRY(device, &This->d3ddevice_list, struct d3d_device, ddraw_entry) + { + device->ddraw = NULL; + }
/* Now free the object */ free(This); @@ -793,7 +796,6 @@ static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface) static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, DWORD cooplevel, BOOL restore_mode_on_normal) { - struct wined3d_stateblock *stateblock; BOOL restore_state = FALSE; struct d3d_device *device; RECT clip_rect; @@ -923,18 +925,29 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED)) wined3d_device_set_multithreaded(ddraw->wined3d_device);
- device = ddraw->d3ddevice; if (ddraw->wined3d_swapchain) { - if (!(ddraw->flags & DDRAW_NO3D) && device) + if (!(ddraw->flags & DDRAW_NO3D)) { restore_state = TRUE;
- if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, - device->state, WINED3D_SBT_ALL, &stateblock))) + LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { - ERR("Failed to create stateblock, hr %#lx.\n", hr); - goto done; + if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, + device->state, WINED3D_SBT_ALL, &device->saved_state))) + { + struct list *entry; + + ERR("Failed to create stateblock, hr %#lx.\n", hr); + entry = &device->ddraw_entry; + while ((entry = list_prev(&ddraw->d3ddevice_list, entry))) + { + device = LIST_ENTRY(entry, struct d3d_device, ddraw_entry); + wined3d_stateblock_decref(device->saved_state); + device->saved_state = NULL; + } + goto done; + } } }
@@ -946,8 +959,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
if (restore_state) { - wined3d_stateblock_apply(stateblock, device->state); - wined3d_stateblock_decref(stateblock); + LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) + { + wined3d_stateblock_apply(device->saved_state, device->state); + wined3d_stateblock_decref(device->saved_state); + device->saved_state = NULL; + } }
if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)) @@ -5105,5 +5122,6 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de ddraw->immediate_context = wined3d_device_get_immediate_context(ddraw->wined3d_device);
list_init(&ddraw->surface_list); + list_init(&ddraw->d3ddevice_list); return DD_OK; } diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index e5a8327204c..1f0c94a9c6e 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -113,7 +113,7 @@ struct ddraw
/* D3D things */ HWND d3d_window; - struct d3d_device *d3ddevice; + struct list d3ddevice_list; int d3dversion;
/* Various HWNDs */ @@ -326,6 +326,7 @@ struct d3d_device struct wined3d_device *wined3d_device; struct wined3d_device_context *immediate_context; struct ddraw *ddraw; + struct list ddraw_entry; IUnknown *rt_iface; struct ddraw_surface *target, *target_ds;
@@ -362,6 +363,9 @@ struct d3d_device
struct wined3d_stateblock *recording, *state, *update_state; const struct wined3d_stateblock_state *stateblock_state; + + /* For temporary saving state during reset. */ + struct wined3d_stateblock *saved_state; };
HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface *target, IUnknown *rt_iface, diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index cdcc332f235..f64db3aa633 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -329,7 +329,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) * the device from it before so it doesn't try to save / restore state on the teared down device. */ if (This->ddraw) { - This->ddraw->d3ddevice = NULL; + list_remove(&This->ddraw_entry); This->ddraw = NULL; }
@@ -6907,7 +6907,7 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c if (version != 1) IUnknown_AddRef(device->rt_iface);
- ddraw->d3ddevice = device; + list_add_head(&ddraw->d3ddevice_list, &device->ddraw_entry);
wined3d_stateblock_set_render_state(device->state, WINED3D_RS_ZENABLE, d3d_device_update_depth_stencil(device)); @@ -6955,12 +6955,6 @@ HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_su return DDERR_OUTOFMEMORY; }
- if (ddraw->d3ddevice) - { - FIXME("Only one Direct3D device per DirectDraw object supported.\n"); - return DDERR_INVALIDPARAMS; - } - if (!(object = calloc(1, sizeof(*object)))) { ERR("Failed to allocate device memory.\n"); diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index fe45071c138..767547bbac4 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -914,8 +914,8 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) WARN("DirectDraw object %p has reference counts {%lu, %lu, %lu, %lu, %lu}.\n", ddraw, ddraw->ref7, ddraw->ref4, ddraw->ref3, ddraw->ref2, ddraw->ref1);
- if (ddraw->d3ddevice) - WARN("DirectDraw object %p has Direct3D device %p attached.\n", ddraw, ddraw->d3ddevice); + if (!list_empty(&ddraw->d3ddevice_list)) + WARN("DirectDraw object %p has Direct3D device(s) attached.\n", ddraw);
LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry) { diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 8073bcd4d48..813d19832c2 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -2013,6 +2013,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 * *****************************************************************************/ static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf) { + struct d3d_device *device; + TRACE("surface %p, attachment %p.\n", This, Surf);
if(Surf == This) @@ -2039,8 +2041,10 @@ static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct d This->next_attached = Surf;
/* Check if the WineD3D depth stencil needs updating */ - if (This->ddraw->d3ddevice) - d3d_device_update_depth_stencil(This->ddraw->d3ddevice); + LIST_FOR_EACH_ENTRY(device, &This->ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) + { + d3d_device_update_depth_stencil(device); + }
wined3d_mutex_unlock();
@@ -4361,7 +4365,7 @@ static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD Ma if (surface->draw_texture) wined3d_texture_set_lod(surface->draw_texture, MaxLOD);
- if ((device = surface->ddraw->d3ddevice)) + LIST_FOR_EACH_ENTRY(device, &surface->ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { wined3d_stateblock_texture_changed(device->state, surface->wined3d_texture); if (surface->draw_texture) @@ -6774,7 +6778,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ swapchain_desc.backbuffer_height = mode.height; swapchain_desc.backbuffer_format = mode.format_id;
- if ((device = ddraw->d3ddevice)) + LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { if (device->recording) wined3d_stateblock_decref(device->recording); @@ -6791,9 +6795,11 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ return hr_ddraw_from_wined3d(hr); }
- if (device) + LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) + { wined3d_stateblock_set_render_state(device->state, WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil); + } } }
diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index 5958df59df9..ec536a83729 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -1523,13 +1523,8 @@ static void BackBuffer3DCreateSurfaceTest(void) "GetSurfaceDesc returned caps %#lx.\n", created_ddsd.ddsCaps.dwCaps);
hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal); - /* Currently Wine only supports the creation of one Direct3D device - for a given DirectDraw instance. It has been created already - in D3D1_createObjects() - IID_IDirect3DRGBDevice */ - todo_wine ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); - - if (SUCCEEDED(hr)) - IDirect3DDevice_Release(d3dhal); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + IDirect3DDevice_Release(d3dhal);
IDirectDrawSurface_Release(surf); } diff --git a/dlls/ddraw/vertexbuffer.c b/dlls/ddraw/vertexbuffer.c index 14f3c8a3ef2..73cf0a37991 100644 --- a/dlls/ddraw/vertexbuffer.c +++ b/dlls/ddraw/vertexbuffer.c @@ -87,7 +87,7 @@ static ULONG WINAPI d3d_vertex_buffer7_Release(IDirect3DVertexBuffer7 *iface) * they are destroyed. */ wined3d_mutex_lock();
- if ((device = buffer->ddraw->d3ddevice)) + LIST_FOR_EACH_ENTRY(device, &buffer->ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { if (device->stateblock_state->streams[0].buffer == buffer->wined3d_buffer) wined3d_stateblock_set_stream_source(device->state, 0, NULL, 0, 0);