Fixes Sim City 3000 Building Architect.
-- v2: ddraw/tests: Add tests for multiple devices. ddraw: Support multiple devices per ddraw object.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/ddraw.c | 36 ++++++++++++++++++++++++++ dlls/ddraw/ddraw_private.h | 52 ++++++++++++++++++++------------------ dlls/ddraw/device.c | 10 +------- dlls/ddraw/material.c | 4 +-- dlls/ddraw/viewport.c | 2 +- 5 files changed, 67 insertions(+), 37 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index efbe01f3b8b..7c4c3ce5b6c 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -420,6 +420,8 @@ static void ddraw_destroy_swapchain(struct ddraw *ddraw) *****************************************************************************/ static void ddraw_destroy(struct ddraw *This) { + unsigned int i; + IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL); IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
@@ -441,6 +443,31 @@ static void ddraw_destroy(struct ddraw *This) wined3d_device_decref(This->wined3d_device); wined3d_decref(This->wined3d);
+ for (i = 0; i < This->handle_table.entry_count; ++i) + { + struct ddraw_handle_entry *entry = &This->handle_table.entries[i]; + + switch (entry->type) + { + case DDRAW_HANDLE_FREE: + break; + + case DDRAW_HANDLE_MATERIAL: + { + struct d3d_material *m = entry->object; + FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m); + m->Handle = 0; + break; + } + + default: + FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); + break; + } + } + + ddraw_handle_table_destroy(&This->handle_table); + if (This->d3ddevice) This->d3ddevice->ddraw = NULL;
@@ -5128,6 +5155,15 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de
list_init(&ddraw->surface_list);
+ if (!ddraw_handle_table_init(&ddraw->handle_table, 64)) + { + ERR("Failed to initialize handle table.\n"); + ddraw_handle_table_destroy(&ddraw->handle_table); + wined3d_device_decref(ddraw->wined3d_device); + wined3d_decref(ddraw->wined3d); + return DDERR_OUTOFMEMORY; + } + if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, NULL, WINED3D_SBT_PRIMARY, &ddraw->state))) { ERR("Failed to create the primary stateblock, hr %#lx.\n", hr); diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 6fc93b91860..9506d4ea9cc 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -77,6 +77,31 @@ enum ddraw_device_state DDRAW_DEVICE_STATE_NOT_RESTORED, };
+#define DDRAW_INVALID_HANDLE ~0U + +enum ddraw_handle_type +{ + DDRAW_HANDLE_FREE, + DDRAW_HANDLE_MATERIAL, + DDRAW_HANDLE_MATRIX, + DDRAW_HANDLE_STATEBLOCK, + DDRAW_HANDLE_SURFACE, +}; + +struct ddraw_handle_entry +{ + void *object; + enum ddraw_handle_type type; +}; + +struct ddraw_handle_table +{ + struct ddraw_handle_entry *entries; + struct ddraw_handle_entry *free_entries; + UINT table_size; + UINT entry_count; +}; + struct ddraw { /* Interfaces */ @@ -128,6 +153,8 @@ struct ddraw */ struct list surface_list;
+ struct ddraw_handle_table handle_table; + /* FVF management */ struct FvfToDecl *decls; UINT numConvertedDecls, declArraySize; @@ -281,31 +308,6 @@ struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 * struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface); struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface);
-#define DDRAW_INVALID_HANDLE ~0U - -enum ddraw_handle_type -{ - DDRAW_HANDLE_FREE, - DDRAW_HANDLE_MATERIAL, - DDRAW_HANDLE_MATRIX, - DDRAW_HANDLE_STATEBLOCK, - DDRAW_HANDLE_SURFACE, -}; - -struct ddraw_handle_entry -{ - void *object; - enum ddraw_handle_type type; -}; - -struct ddraw_handle_table -{ - struct ddraw_handle_entry *entries; - struct ddraw_handle_entry *free_entries; - UINT table_size; - UINT entry_count; -}; - BOOL ddraw_handle_table_init(struct ddraw_handle_table *t, UINT initial_size); void ddraw_handle_table_destroy(struct ddraw_handle_table *t); DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddraw_handle_type type); diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index bc1d91ee00b..b86ec044fa4 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -303,14 +303,6 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) case DDRAW_HANDLE_FREE: break;
- case DDRAW_HANDLE_MATERIAL: - { - struct d3d_material *m = entry->object; - FIXME("Material handle %#lx (%p) not unset properly.\n", i + 1, m); - m->Handle = 0; - break; - } - case DDRAW_HANDLE_MATRIX: { /* No FIXME here because this might happen because of sloppy applications. */ @@ -2936,7 +2928,7 @@ static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface, { struct d3d_material *m;
- if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL))) + if (!(m = ddraw_get_object(&device->ddraw->handle_table, value - 1, DDRAW_HANDLE_MATERIAL))) { WARN("Invalid material handle.\n"); wined3d_mutex_unlock(); diff --git a/dlls/ddraw/material.c b/dlls/ddraw/material.c index d8cb41f1733..4f8266f00d2 100644 --- a/dlls/ddraw/material.c +++ b/dlls/ddraw/material.c @@ -143,7 +143,7 @@ static ULONG WINAPI d3d_material3_Release(IDirect3DMaterial3 *iface) if (material->Handle) { wined3d_mutex_lock(); - ddraw_free_handle(&material->ddraw->d3ddevice->handle_table, material->Handle - 1, DDRAW_HANDLE_MATERIAL); + ddraw_free_handle(&material->ddraw->handle_table, material->Handle - 1, DDRAW_HANDLE_MATERIAL); wined3d_mutex_unlock(); }
@@ -300,7 +300,7 @@ static HRESULT WINAPI d3d_material3_GetHandle(IDirect3DMaterial3 *iface, material->active_device = device_impl; if (!material->Handle) { - DWORD h = ddraw_allocate_handle(&device_impl->handle_table, material, DDRAW_HANDLE_MATERIAL); + DWORD h = ddraw_allocate_handle(&device_impl->ddraw->handle_table, material, DDRAW_HANDLE_MATERIAL); if (h == DDRAW_INVALID_HANDLE) { ERR("Failed to allocate a material handle.\n"); diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c index 4eda2fe4763..db235721f75 100644 --- a/dlls/ddraw/viewport.c +++ b/dlls/ddraw/viewport.c @@ -627,7 +627,7 @@ static HRESULT WINAPI d3d_viewport_SetBackground(IDirect3DViewport3 *iface, D3DM
wined3d_mutex_lock();
- if (!(m = ddraw_get_object(&viewport->ddraw->d3ddevice->handle_table, material - 1, DDRAW_HANDLE_MATERIAL))) + if (!(m = ddraw_get_object(&viewport->ddraw->handle_table, material - 1, DDRAW_HANDLE_MATERIAL))) { WARN("Invalid material handle %#lx.\n", material); wined3d_mutex_unlock();
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/ddraw.c | 8 ++++++++ dlls/ddraw/device.c | 10 +--------- dlls/ddraw/executebuffer.c | 4 ++-- dlls/ddraw/surface.c | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 7c4c3ce5b6c..e574318ecab 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -460,6 +460,14 @@ static void ddraw_destroy(struct ddraw *This) break; }
+ case DDRAW_HANDLE_SURFACE: + { + struct ddraw_surface *surf = entry->object; + FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf); + surf->Handle = 0; + break; + } + default: FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); break; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index b86ec044fa4..d34be880991 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -319,14 +319,6 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) break; }
- case DDRAW_HANDLE_SURFACE: - { - struct ddraw_surface *surf = entry->object; - FIXME("Texture handle %#lx (%p) not unset properly.\n", i + 1, surf); - surf->Handle = 0; - break; - } - default: FIXME("Handle %#lx (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); break; @@ -2760,7 +2752,7 @@ static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface, break; }
- surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE); + surf = ddraw_get_object(&device->ddraw->handle_table, value - 1, DDRAW_HANDLE_SURFACE); if (!surf) { WARN("Invalid texture handle.\n"); diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c index 320ce6649d4..f505eea37c6 100644 --- a/dlls/ddraw/executebuffer.c +++ b/dlls/ddraw/executebuffer.c @@ -347,13 +347,13 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer, struct d3d
instr += size;
- if (!(dst = ddraw_get_object(&device->handle_table, + if (!(dst = ddraw_get_object(&device->ddraw->handle_table, ci->hDestTexture - 1, DDRAW_HANDLE_SURFACE))) { WARN("Invalid destination texture handle %#lx.\n", ci->hDestTexture); continue; } - if (!(src = ddraw_get_object(&device->handle_table, + if (!(src = ddraw_get_object(&device->ddraw->handle_table, ci->hSrcTexture - 1, DDRAW_HANDLE_SURFACE))) { WARN("Invalid source texture handle %#lx.\n", ci->hSrcTexture); diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index a096c5d7d8e..0d231afb856 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -5449,7 +5449,7 @@ static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
if (!surface->Handle) { - DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE); + DWORD h = ddraw_allocate_handle(&device_impl->ddraw->handle_table, surface, DDRAW_HANDLE_SURFACE); if (h == DDRAW_INVALID_HANDLE) { ERR("Failed to allocate a texture handle.\n"); @@ -6060,7 +6060,7 @@ static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *paren
/* Having a texture handle set implies that the device still exists. */ if (surface->Handle) - ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE); + ddraw_free_handle(&surface->ddraw->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
/* Reduce the ddraw surface count. */ list_remove(&surface->surface_list_entry);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/ddraw.c | 8 ++++++-- dlls/ddraw/ddraw_private.h | 3 ++- dlls/ddraw/device.c | 13 +++++-------- dlls/ddraw/main.c | 4 ++-- dlls/ddraw/surface.c | 19 ++++++++++++------- dlls/ddraw/tests/d3d.c | 9 ++------- 6 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index e574318ecab..89bec3f7b1e 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; unsigned int i;
IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL); @@ -476,8 +477,10 @@ static void ddraw_destroy(struct ddraw *This)
ddraw_handle_table_destroy(&This->handle_table);
- 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); @@ -5162,6 +5165,7 @@ 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);
if (!ddraw_handle_table_init(&ddraw->handle_table, 64)) { diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 9506d4ea9cc..24cd7350eb0 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -138,7 +138,7 @@ struct ddraw
/* D3D things */ HWND d3d_window; - struct d3d_device *d3ddevice; + struct list d3ddevice_list; int d3dversion;
/* Various HWNDs */ @@ -331,6 +331,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 wined3d_streaming_buffer vertex_buffer, index_buffer; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index d34be880991..b0f0bd910dc 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -343,7 +343,10 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) /* Releasing the render target above may have released the last * reference to the ddraw object. */ if (This->ddraw) - This->ddraw->d3ddevice = NULL; + { + list_remove(&This->ddraw_entry); + This->ddraw = NULL; + }
/* Now free the structure */ free(This); @@ -6874,7 +6877,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(ddraw->state, WINED3D_RS_ZENABLE, d3d_device_update_depth_stencil(device)); @@ -6922,12 +6925,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 1ba2900704f..52f82e3c256 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -874,8 +874,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 0d231afb856..f122715a445 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -2016,6 +2016,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) @@ -2042,8 +2044,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();
@@ -6765,18 +6769,19 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ if (ddraw->cooperative_level & DDSCL_EXCLUSIVE) { struct wined3d_swapchain_desc swapchain_desc; + struct d3d_device *device;
wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc); swapchain_desc.backbuffer_width = mode.width; swapchain_desc.backbuffer_height = mode.height; swapchain_desc.backbuffer_format = mode.format_id;
- if (ddraw->d3ddevice) + LIST_FOR_EACH_ENTRY(device, &ddraw->d3ddevice_list, struct d3d_device, ddraw_entry) { - if (ddraw->d3ddevice->recording) - wined3d_stateblock_decref(ddraw->d3ddevice->recording); - ddraw->d3ddevice->recording = NULL; - ddraw->d3ddevice->update_state = ddraw->d3ddevice->state; + if (device->recording) + wined3d_stateblock_decref(device->recording); + device->recording = NULL; + device->update_state = device->state; } wined3d_stateblock_reset(ddraw->state);
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); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/tests/ddraw1.c | 80 +++++++++++++++++++++++++ dlls/ddraw/tests/ddraw2.c | 121 +++++++++++++++++++++++++++++++++++--- dlls/ddraw/tests/ddraw4.c | 98 +++++++++++++++++++++++++++--- dlls/ddraw/tests/ddraw7.c | 62 ++++++++++++++++--- 4 files changed, 338 insertions(+), 23 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index d8fcb188c40..8e78eb42728 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -15530,6 +15530,85 @@ static void test_pinned_sysmem(void) DestroyWindow(window); }
+static void test_multiple_devices(void) +{ + D3DTEXTUREHANDLE texture_handle, texture_handle2; + D3DMATERIALHANDLE mat_handle, mat_handle2; + IDirect3DViewport *viewport, *viewport2; + IDirect3DDevice *device, *device2; + IDirectDrawSurface *texture_surf; + IDirect3DMaterial *material; + DDSURFACEDESC surface_desc; + IDirect3DTexture *texture; + IDirectDraw *ddraw; + ULONG refcount; + HWND window; + HRESULT hr; + + window = create_window(); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + device2 = create_device_ex(ddraw, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice); + ok(!!device2, "got NULL.\n"); + + viewport = create_viewport(device, 0, 0, 640, 480); + viewport2 = create_viewport(device2, 0, 0, 640, 480); + + material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f); + hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + ok(mat_handle == mat_handle2, "got different handles.\n"); + + hr = IDirect3DMaterial_GetHandle(material, device2, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + todo_wine ok(mat_handle != mat_handle2, "got same handles.\n"); + + hr = IDirect3DViewport_SetBackground(viewport, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DViewport_SetBackground(viewport2, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + surface_desc.dwWidth = 256; + surface_desc.dwHeight = 256; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture_surf, NULL); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirectDrawSurface_QueryInterface(texture_surf, &IID_IDirect3DTexture2, (void **)&texture); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DTexture_GetHandle(texture, device2, &texture_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + ok(texture_handle != texture_handle2, "got same handles.\n"); + + IDirect3DTexture_Release(texture); + IDirectDrawSurface_Release(texture_surf); + IDirect3DMaterial_Release(material); + IDirect3DViewport_Release(viewport); + IDirect3DViewport_Release(viewport2); + + refcount = IDirect3DDevice_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirect3DDevice_Release(device2); + ok(!refcount, "Device has %lu references left.\n", refcount); + + IDirectDraw_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -15650,4 +15729,5 @@ START_TEST(ddraw1) test_filling_convention(); test_enum_devices(); test_pinned_sysmem(); + test_multiple_devices(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index f4cc5df0558..1ddb36b3b4f 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -462,7 +462,8 @@ static IDirectDraw2 *create_ddraw(void) return ddraw2; }
-static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWORD coop_level, const GUID *device_guid) +static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWORD coop_level, const GUID *device_guid, + IDirectDrawSurface **ret_surface) { /* Prefer 16 bit depth buffers because Nvidia gives us an unpadded D24 buffer if we ask * for 24 bit and handles such buffers incorrectly in DDBLT_DEPTHFILL. AMD only supports @@ -541,13 +542,17 @@ static IDirect3DDevice2 *create_device_ex(IDirectDraw2 *ddraw, HWND window, DWOR }
IDirect3D2_Release(d3d); - IDirectDrawSurface_Release(surface); + if (ret_surface) + *ret_surface = surface; + else + IDirectDrawSurface_Release(surface); + return device; }
static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level) { - return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice); + return create_device_ex(ddraw, window, coop_level, &IID_IDirect3DHALDevice, NULL); }
static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h) @@ -1330,7 +1335,7 @@ static void test_depth_blit(const GUID *device_guid) window = create_window(); ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); - if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); IDirectDraw2_Release(ddraw); @@ -1856,7 +1861,7 @@ static void test_zenable(const GUID *device_guid) window = create_window(); ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); - if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); IDirectDraw2_Release(ddraw); @@ -1971,7 +1976,7 @@ static void test_ck_rgba(const GUID *device_guid) window = create_window(); ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); - if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); IDirectDraw2_Release(ddraw); @@ -5204,7 +5209,7 @@ static void test_rt_caps(const GUID *device_guid) window = create_window(); ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); - if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); IDirectDraw2_Release(ddraw); @@ -15692,7 +15697,7 @@ static void test_texture_wrong_caps(const GUID *device_guid) window = create_window(); ddraw = create_ddraw(); ok(!!ddraw, "Failed to create a ddraw object.\n"); - if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -16442,6 +16447,105 @@ static void run_for_each_device_type(void (*test_func)(const GUID *)) test_func(&IID_IDirect3DRGBDevice); }
+static void test_multiple_devices(void) +{ + D3DTEXTUREHANDLE texture_handle, texture_handle2; + IDirectDrawSurface *surface, *texture_surf; + D3DMATERIALHANDLE mat_handle, mat_handle2; + IDirect3DViewport2 *viewport, *viewport2; + IDirect3DDevice2 *device, *device2; + IDirect3DMaterial2 *material; + DDSURFACEDESC surface_desc; + IDirect3DTexture2 *texture; + IDirectDraw2 *ddraw; + IDirect3D2 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + window = create_window(); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + if (!(device = create_device_ex(ddraw, window, DDSCL_NORMAL, &IID_IDirect3DHALDevice, &surface))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice2_GetDirect3D(device, &d3d); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + viewport = create_viewport(device, 0, 0, 640, 480); + viewport2 = create_viewport(device2, 0, 0, 640, 480); + hr = IDirect3DDevice2_SetCurrentViewport(device, viewport); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice2_SetCurrentViewport(device2, viewport); + ok(hr == DDERR_INVALIDPARAMS, "got %#lx.\n", hr); + hr = IDirect3DDevice2_SetCurrentViewport(device2, viewport2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f); + hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + ok(mat_handle == mat_handle2, "got different handles.\n"); + + hr = IDirect3DMaterial2_GetHandle(material, device2, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + todo_wine ok(mat_handle != mat_handle2, "got same handles.\n"); + + hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice2_SetLightState(device2, D3DLIGHTSTATE_MATERIAL, mat_handle); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle2); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DViewport2_SetBackground(viewport, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DViewport2_SetBackground(viewport2, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + surface_desc.dwWidth = 256; + surface_desc.dwHeight = 256; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture_surf, NULL); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirectDrawSurface_QueryInterface(texture_surf, &IID_IDirect3DTexture2, (void **)&texture); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DTexture2_GetHandle(texture, device2, &texture_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + ok(texture_handle == texture_handle2, "got different handles.\n"); + + IDirect3DTexture2_Release(texture); + IDirectDrawSurface_Release(texture_surf); + IDirect3DMaterial2_Release(material); + IDirect3DViewport2_Release(viewport); + IDirect3DViewport2_Release(viewport2); + + refcount = IDirect3DDevice2_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirect3DDevice2_Release(device2); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirectDrawSurface_Release(surface); + ok(!refcount, "Surface has %lu references left.\n", refcount); + + IDirectDraw2_Release(ddraw); + IDirect3D2_Release(d3d); + DestroyWindow(window); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -16567,4 +16671,5 @@ START_TEST(ddraw2) run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); test_enum_devices(); + test_multiple_devices(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 4811053a231..8c850ca2c93 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -450,7 +450,8 @@ static IDirectDraw4 *create_ddraw(void) return ddraw4; }
-static IDirect3DDevice3 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid) +static IDirect3DDevice3 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid, + IDirectDrawSurface4 **ret_surface) { IDirectDrawSurface4 *surface, *ds; IDirect3DDevice3 *device = NULL; @@ -539,16 +540,22 @@ static IDirect3DDevice3 *create_device_ex(HWND window, DWORD coop_level, const G
hr = IDirect3D3_CreateDevice(d3d3, device_guid, surface, &device, NULL); IDirect3D3_Release(d3d3); - IDirectDrawSurface4_Release(surface); if (FAILED(hr)) + { + IDirectDrawSurface4_Release(surface); return NULL; + } + if (ret_surface) + *ret_surface = surface; + else + IDirectDrawSurface4_Release(surface);
return device; }
static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level) { - return create_device_ex(window, coop_level, &IID_IDirect3DHALDevice); + return create_device_ex(window, coop_level, &IID_IDirect3DHALDevice, NULL); }
static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h) @@ -1506,7 +1513,7 @@ static void test_depth_blit(const GUID *device_guid) D3DRECT d3drect;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -2101,7 +2108,7 @@ static void test_zenable(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -2213,7 +2220,7 @@ static void test_ck_rgba(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -18750,7 +18757,7 @@ static void test_texture_wrong_caps(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -19506,6 +19513,82 @@ static void test_enum_devices(void) ok(!refcount, "Device has %lu references left.\n", refcount); }
+static void test_multiple_devices(void) +{ + D3DMATERIALHANDLE mat_handle, mat_handle2; + IDirect3DViewport3 *viewport, *viewport2; + IDirect3DDevice3 *device, *device2; + IDirect3DMaterial3 *material; + IDirectDrawSurface4 *surface; + IDirectDraw4 *ddraw; + IDirect3D3 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + window = create_window(); + if (!(device = create_device_ex(window, DDSCL_NORMAL, &IID_IDirect3DHALDevice, &surface))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice3_GetDirect3D(device, &d3d); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device2, NULL); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + viewport = create_viewport(device, 0, 0, 640, 480); + viewport2 = create_viewport(device2, 0, 0, 640, 480); + hr = IDirect3DDevice3_SetCurrentViewport(device, viewport); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice3_SetCurrentViewport(device2, viewport); + ok(hr == DDERR_INVALIDPARAMS, "got %#lx.\n", hr); + hr = IDirect3DDevice3_SetCurrentViewport(device2, viewport2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + material = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f); + hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + ok(mat_handle == mat_handle2, "got different handles.\n"); + + hr = IDirect3DMaterial3_GetHandle(material, device2, &mat_handle2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + todo_wine ok(mat_handle != mat_handle2, "got same handles.\n"); + + hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice3_SetLightState(device2, D3DLIGHTSTATE_MATERIAL, mat_handle); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle2); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DViewport3_SetBackground(viewport, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DViewport3_SetBackground(viewport2, mat_handle); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + IDirect3DMaterial3_Release(material); + IDirect3DViewport3_Release(viewport); + IDirect3DViewport3_Release(viewport2); + + refcount = IDirect3DDevice3_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirect3DDevice3_Release(device2); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirectDrawSurface4_Release(surface); + ok(!refcount, "Surface has %lu references left.\n", refcount); + IDirectDraw4_Release(ddraw); + IDirect3D3_Release(d3d); + DestroyWindow(window); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -19647,4 +19730,5 @@ START_TEST(ddraw4) run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); test_enum_devices(); + test_multiple_devices(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 2771a4ed368..2ec1ab611e4 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -498,7 +498,8 @@ static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 return DDENUMRET_OK; }
-static IDirect3DDevice7 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid) +static IDirect3DDevice7 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid, + IDirectDrawSurface7 **ret_surface) { IDirectDrawSurface7 *surface, *ds; IDirect3DDevice7 *device = NULL; @@ -586,9 +587,16 @@ static IDirect3DDevice7 *create_device_ex(HWND window, DWORD coop_level, const G
hr = IDirect3D7_CreateDevice(d3d7, device_guid, surface, &device); IDirect3D7_Release(d3d7); - IDirectDrawSurface7_Release(surface); if (FAILED(hr)) + { + IDirectDrawSurface7_Release(surface); return NULL; + } + + if (ret_surface) + *ret_surface = surface; + else + IDirectDrawSurface7_Release(surface);
return device; } @@ -615,7 +623,7 @@ static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
IDirect3D7_Release(d3d7);
- return create_device_ex(window, coop_level, device_guid); + return create_device_ex(window, coop_level, device_guid, NULL); }
static bool init_3d_test_context_guid(struct ddraw_test_context *context, const GUID *device_guid) @@ -625,7 +633,7 @@ static bool init_3d_test_context_guid(struct ddraw_test_context *context, const memset(context, 0, sizeof(*context));
context->window = create_window(); - if (!(context->device = create_device_ex(context->window, DDSCL_NORMAL, device_guid))) + if (!(context->device = create_device_ex(context->window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a D3D device.\n"); DestroyWindow(context->window); @@ -1586,7 +1594,7 @@ static void test_depth_blit(const GUID *device_guid) HWND window;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -1844,7 +1852,7 @@ static void test_zenable(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -1948,7 +1956,7 @@ static void test_ck_rgba(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -19134,7 +19142,7 @@ static void test_texture_wrong_caps(const GUID *device_guid) HRESULT hr;
window = create_window(); - if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid))) + if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid, NULL))) { skip("Failed to create a 3D device, skipping test.\n"); DestroyWindow(window); @@ -20001,6 +20009,43 @@ static void run_for_each_device_type(void (*test_func)(const GUID *)) winetest_pop_context(); }
+static void test_multiple_devices(void) +{ + IDirect3DDevice7 *device, *device2; + IDirectDrawSurface7 *surface; + IDirectDraw7 *ddraw; + IDirect3D7 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + window = create_window(); + if (!(device = create_device_ex(window, DDSCL_NORMAL, &IID_IDirect3DTnLHalDevice, &surface))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(hr == D3D_OK, "got %#lx.\n", hr); + hr = IDirect3DDevice7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device2); + ok(hr == D3D_OK, "got %#lx.\n", hr); + + refcount = IDirect3DDevice3_Release(device); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirect3DDevice3_Release(device2); + ok(!refcount, "Device has %lu references left.\n", refcount); + refcount = IDirectDrawSurface4_Release(surface); + ok(!refcount, "Surface has %lu references left.\n", refcount); + IDirectDraw4_Release(ddraw); + IDirect3D3_Release(d3d); + DestroyWindow(window); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -20176,4 +20221,5 @@ START_TEST(ddraw7) test_enum_devices(); run_for_each_device_type(test_user_memory); test_flip_3d(); + test_multiple_devices(); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144115
Your paranoid android.
=== w11pro64_amd (64 bit report) ===
ddraw: ddraw2.c:3268: Test failed: Got unexpected screen size 800x600. ddraw2.c:3357: Test failed: Expected surface width 1024, got 640. ddraw2.c:3359: Test failed: Expected surface height 768, got 480. ddraw2.c:3377: Test failed: Expected surface width 1024, got 640. ddraw2.c:3379: Test failed: Expected surface height 768, got 480. ddraw2.c:3392: Test failed: Expected surface width 1024, got 640. ddraw2.c:3394: Test failed: Expected surface height 768, got 480. ddraw2.c:3458: Test failed: Expected surface width 1024, got 640. ddraw2.c:3460: Test failed: Expected surface height 768, got 480. ddraw2.c:3514: Test failed: Expected resolution 1024x768, got 640x480. ddraw2.c:3531: Test failed: Expected surface width 1024, got 640. ddraw2.c:3533: Test failed: Expected surface height 768, got 480. ddraw2.c:3554: Test failed: Expected surface width 1024, got 640. ddraw2.c:3556: Test failed: Expected surface height 768, got 480. ddraw2.c:3569: Test failed: Expected surface width 1024, got 640. ddraw2.c:3571: Test failed: Expected surface height 768, got 480. ddraw2.c:3628: Test failed: Expected surface width 1024, got 640. ddraw2.c:3630: Test failed: Expected surface height 768, got 480. ddraw2.c:3684: Test failed: Expected resolution 1024x768, got 640x480. ddraw2.c:3701: Test failed: Expected surface width 1024, got 640. ddraw2.c:3703: Test failed: Expected surface height 768, got 480. ddraw2.c:3728: Test failed: Expected screen size 1024x768, got 0x0. ddraw2.c:3735: Test failed: Expected (0,0)-(1024,768), got (0,0)-(640,480). ddraw2.c:3747: Test failed: Expected surface width 1024, got 640. ddraw2.c:3749: Test failed: Expected surface height 768, got 480. ddraw2.c:3800: Test failed: Expected screen size 2 1024x768, got 0x0. ddraw2.c:3808: Test failed: Expected (0,0)-(1024,768), got (0,0)-(136,100). ddraw2.c:3820: Test failed: Expected surface width 1024, got 640. ddraw2.c:3822: Test failed: Expected surface height 768, got 480. ddraw2.c:3979: Test failed: Got unexpected screen width 800. ddraw2.c:3981: Test failed: Got unexpected screen height 600. ddraw2.c:4124: Test failed: Got unexpected screen width 800. ddraw2.c:4126: Test failed: Got unexpected screen height 600. ddraw2.c:4131: Test failed: Got unexpected screen width 800. ddraw2.c:4133: Test failed: Got unexpected screen height 600.
=== w11pro64_amd (64 bit report) ===
ddraw: ddraw4.c:3600: Test failed: Expected surface width 1024, got 640. ddraw4.c:3602: Test failed: Expected surface height 768, got 480. ddraw4.c:3620: Test failed: Expected surface width 1024, got 640. ddraw4.c:3622: Test failed: Expected surface height 768, got 480. ddraw4.c:3635: Test failed: Expected surface width 1024, got 640. ddraw4.c:3637: Test failed: Expected surface height 768, got 480. ddraw4.c:3694: Test failed: Expected surface width 1024, got 640. ddraw4.c:3696: Test failed: Expected surface height 768, got 480. ddraw4.c:3750: Test failed: Expected resolution 1024x768, got 640x480. ddraw4.c:3767: Test failed: Expected surface width 1024, got 640. ddraw4.c:3769: Test failed: Expected surface height 768, got 480. ddraw4.c:3790: Test failed: Expected surface width 1024, got 640. ddraw4.c:3792: Test failed: Expected surface height 768, got 480. ddraw4.c:3805: Test failed: Expected surface width 1024, got 640. ddraw4.c:3807: Test failed: Expected surface height 768, got 480. ddraw4.c:3864: Test failed: Expected surface width 1024, got 640. ddraw4.c:3866: Test failed: Expected surface height 768, got 480. ddraw4.c:3920: Test failed: Expected resolution 1024x768, got 640x480. ddraw4.c:3937: Test failed: Expected surface width 1024, got 640. ddraw4.c:3939: Test failed: Expected surface height 768, got 480. ddraw4.c:3964: Test failed: Expected screen size 1024x768, got 0x0. ddraw4.c:3971: Test failed: Expected (0,0)-(1024,768), got (0,0)-(640,480). ddraw4.c:3983: Test failed: Expected surface width 1024, got 640. ddraw4.c:3985: Test failed: Expected surface height 768, got 480. ddraw4.c:4036: Test failed: Expected screen size 2 1024x768, got 0x0. ddraw4.c:4044: Test failed: Expected (0,0)-(1024,768), got (0,0)-(136,100). ddraw4.c:4056: Test failed: Expected surface width 1024, got 640. ddraw4.c:4058: Test failed: Expected surface height 768, got 480. ddraw4.c:4232: Test failed: Got unexpected screen width 640. ddraw4.c:4234: Test failed: Got unexpected screen height 480. ddraw4.c:4239: Test failed: Got unexpected screen width 640. ddraw4.c:4241: Test failed: Got unexpected screen height 480. ddraw4.c:4263: Test failed: Got unexpected screen width 640. ddraw4.c:4265: Test failed: Got unexpected screen height 480. ddraw4.c:4270: Test failed: Got unexpected screen width 640. ddraw4.c:4272: Test failed: Got unexpected screen height 480. ddraw4.c:4294: Test failed: Got unexpected screen width 640. ddraw4.c:4296: Test failed: Got unexpected screen height 480. ddraw4.c:4329: Test failed: Got unexpected screen width 640. ddraw4.c:4331: Test failed: Got unexpected screen height 480. ddraw4.c:8551: Test failed: Failed to create surface, hr 0x80070057. ddraw4.c:8560: Test failed: Failed to create surface, hr 0x80070057. ddraw4.c:8573: Test failed: Failed to attach surface, hr 0x80070057.
v2: - removed now fixed todo in tests/d3d.c.
Some high-level questions:
* What about matrix and stateblock handles? Should we just move the whole table in one go?
* Should the table go in the ddraw object, or should it be global?
* Assuming that rendering to a given device is supposed to go to that device's RT specified at creation time, calling wined3d_device_context_set_rendertarget_views() from d3d_device_init() won't be enough to achieve that anymore. Presumably we need to do it on every draw call now.
* In fact, more generally, shouldn't state be specific to each device? That'll need more thought. We could probably use a per-device primary stateblock?
Matteo, Stefan, Henri, since you have a lot more background in this area, are there other potential concerns with having multiple devices that I might not be thinking of?
On Tue Mar 19 00:19:20 2024 +0000, Zebediah Figura wrote:
Some high-level questions:
- What about matrix and stateblock handles? Should we just move the
whole table in one go?
- Should the table go in the ddraw object, or should it be global?
- Assuming that rendering to a given device is supposed to go to that
device's RT specified at creation time, calling wined3d_device_context_set_rendertarget_views() from d3d_device_init() won't be enough to achieve that anymore. Presumably we need to do it on every draw call now.
- In fact, more generally, shouldn't state be specific to each device?
That'll need more thought. We could probably use a per-device primary stateblock? Matteo, Stefan, Henri, since you have a lot more background in this area, are there other potential concerns with having multiple devices that I might not be thinking of?
1, 2: I did a bit of more testing, and: - matrix, material and texture handles are usable even for devices created with a different ddraw object (so we should probably use a global handle table for those), so I will use a global handle table instead of per-ddraw one and add matrix handles to those; - stateblock handles are not usable cross-ddraw7 devices (so they should probably stay where they are).
3, 4.: It looks like currently all the state besides the mentioned render targets are handled in the per ddraw device stateblock which is applied before draw, or am I missing something? Should I probably just handle render targets per-draw?
3, 4.: It looks like currently all the state besides the mentioned render targets are handled in the per ddraw device stateblock which is applied before draw, or am I missing something? Should I probably just handle render targets per-draw?
I mean, if you do SetRenderState() on one device, and then GetRenderState() on another, I suspect that's not supposed to return the state that was set on the first device. But currently that's what this patch does; the state is stored in stateblock_state which is per ddraw.
Render target is a bit special since it doesn't go through wined3d_stateblock. It'd need to be set manually.
On Tue Mar 19 00:38:39 2024 +0000, Zebediah Figura wrote:
3, 4.: It looks like currently all the state besides the mentioned
render targets are handled in the per ddraw device stateblock which is applied before draw, or am I missing something? Should I probably just handle render targets per-draw? I mean, if you do SetRenderState() on one device, and then GetRenderState() on another, I suspect that's not supposed to return the state that was set on the first device. But currently that's what this patch does; the state is stored in stateblock_state which is per ddraw. Render target is a bit special since it doesn't go through wined3d_stateblock. It'd need to be set manually.
Oh yeah, the state object is copied from ddraw and not created. Yes, state objects should be created per device.
On Tue Mar 19 00:54:24 2024 +0000, Paul Gofman wrote:
Oh yeah, the state object is copied from ddraw and not created. Yes, state objects should be created per device.
Re the question if state shouldn't be specific to a d3d device: Yes, I guess in theory, but I have never seen an application try to create two IDirect3DDevices for the same IDirectDraw object.
Knowing how easy it is to crash your process or even BSOD Windows with doing a lot less weird ddraw things, I decided to ignore the problem until we find an app that actually tries to do this kind of thing.
On Wed Mar 20 21:29:14 2024 +0000, Stefan Dösinger wrote:
Re the question if state shouldn't be specific to a d3d device: Yes, I guess in theory, but I have never seen an application try to create two IDirect3DDevices for the same IDirectDraw object. Knowing how easy it is to crash your process or even BSOD Windows with doing a lot less weird ddraw things, I decided to ignore the problem until we find an app that actually tries to do this kind of thing.
Now I should have looked at the actual commits before commenting...
I'll give those tests a try on Windows XP tomorrow and see what happens.
There are other possibilities to consider: What kind of devices does Sim City 3000 Building Architect create? Are they HW devices, or RGB ones (aka software)? Is there maybe a refcounting bug that keeps the old device alive even though it shouldn't? Might it be happy with a different return value?
On Wed Mar 20 21:34:01 2024 +0000, Stefan Dösinger wrote:
Now I should have looked at the actual commits before commenting... I'll give those tests a try on Windows XP tomorrow and see what happens. There are other possibilities to consider: What kind of devices does Sim City 3000 Building Architect create? Are they HW devices, or RGB ones (aka software)? Is there maybe a refcounting bug that keeps the old device alive even though it shouldn't? Might it be happy with a different return value?
I have almost finished the update which implements that properly with deduplicating states per d3d device, hoping to finalize a bit of more tests and send that soon. Some bit of ad-hoc testing (on Win10) shows that state per different d3d devices is independent (which, well, was easy to expect).
WRT Sim City 3000 Building Architect, it just doesn't destroy one device before creating another and never uses first device later, almost anything which will let another device be created and function will let it work.
On Wed Mar 20 21:36:19 2024 +0000, Paul Gofman wrote:
I have almost finished the update which implements that properly with deduplicating states per d3d device, hoping to finalize a bit of more tests and send that soon. Some bit of ad-hoc testing (on Win10) shows that state per different d3d devices is independent (which, well, was easy to expect). WRT Sim City 3000 Building Architect, it just doesn't destroy one device before creating another and never uses first device later, almost anything which will let another device be created and function will let it work.
I ran the tests on my WinXP machine (r200 GPU) and they pass as-is.
I experimented a bit, and it seems that although background handles are per-device, they do work cross-device. Your tests already try to get a handle from device1 and set it as background on a viewport created from device2. I tried to clear the viewport and checked the color in the surface, and it properly picks up the material's color. I also tried with a separate material that never received a handle from device2.