Commit 9d95bd5f authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ddraw: Support multiple devices per ddraw object.

parent 6fe8e64c
......@@ -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,20 +925,31 @@ 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;
LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry)
{
if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device,
device->state, WINED3D_SBT_ALL, &stateblock)))
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;
}
}
}
ddraw_destroy_swapchain(ddraw);
}
......@@ -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;
}
......@@ -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,
......
......@@ -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");
......
......@@ -892,8 +892,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)
{
......
......@@ -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,11 +6795,13 @@ 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);
}
}
}
if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
{
......
......@@ -1523,12 +1523,7 @@ 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))
ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
IDirect3DDevice_Release(d3dhal);
IDirectDrawSurface_Release(surf);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment