From: Paul Gofman pgofman@codeweavers.com
--- dlls/ddraw/device.c | 10 +----- dlls/ddraw/main.c | 83 +++++++++++++++++++++++++++++++++++++------ dlls/ddraw/material.c | 4 +-- dlls/ddraw/viewport.c | 2 +- 4 files changed, 76 insertions(+), 23 deletions(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index bc1d91ee00b..725c925e602 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(NULL, value - 1, DDRAW_HANDLE_MATERIAL))) { WARN("Invalid material handle.\n"); wined3d_mutex_unlock(); diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index 1ba2900704f..261c2dac0e6 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -37,6 +37,9 @@ static HINSTANCE instance; /* value of ForceRefreshRate */ DWORD force_refresh_rate = 0;
+static struct ddraw_handle_table global_handle_table; +static SRWLOCK global_handle_table_lock = SRWLOCK_INIT; + /* Structure for converting DirectDrawEnumerateA to DirectDrawEnumerateExA */ struct callback_info { @@ -136,6 +139,13 @@ 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) { struct ddraw_handle_entry *entry; + DWORD ret = DDRAW_INVALID_HANDLE; + + if (!t) + { + t = &global_handle_table; + AcquireSRWLockExclusive(&global_handle_table_lock); + }
if (t->free_entries) { @@ -145,13 +155,14 @@ DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddr if (entry->type != DDRAW_HANDLE_FREE) { ERR("Handle %#lx (%p) is in the free list, but has type %#x.\n", idx, entry->object, entry->type); - return DDRAW_INVALID_HANDLE; + goto done; } t->free_entries = entry->object; entry->object = object; entry->type = type;
- return idx; + ret = idx; + goto done; }
if (!(t->entry_count < t->table_size)) @@ -163,7 +174,7 @@ DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddr if (!(new_entries = realloc(t->entries, new_size * sizeof(*t->entries)))) { ERR("Failed to grow the handle table.\n"); - return DDRAW_INVALID_HANDLE; + goto done; } t->entries = new_entries; t->table_size = new_size; @@ -173,25 +184,36 @@ DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddr entry->object = object; entry->type = type;
- return t->entry_count++; + ret = t->entry_count++; + +done: + if (t == &global_handle_table) + ReleaseSRWLockExclusive(&global_handle_table_lock); + return ret; }
void *ddraw_free_handle(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type) { struct ddraw_handle_entry *entry; - void *object; + void *object = NULL; + + if (!t) + { + t = &global_handle_table; + AcquireSRWLockExclusive(&global_handle_table_lock); + }
if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count) { WARN("Invalid handle %#lx passed.\n", handle); - return NULL; + goto done; }
entry = &t->entries[handle]; if (entry->type != type) { WARN("Handle %#lx (%p) is not of type %#x.\n", handle, entry->object, type); - return NULL; + goto done; }
object = entry->object; @@ -199,27 +221,39 @@ void *ddraw_free_handle(struct ddraw_handle_table *t, DWORD handle, enum ddraw_h entry->type = DDRAW_HANDLE_FREE; t->free_entries = entry;
+done: + if (t == &global_handle_table) + ReleaseSRWLockExclusive(&global_handle_table_lock); return object; }
void *ddraw_get_object(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type) { - struct ddraw_handle_entry *entry; + struct ddraw_handle_entry *entry = NULL; + + if (!t) + { + t = &global_handle_table; + AcquireSRWLockExclusive(&global_handle_table_lock); + }
if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count) { WARN("Invalid handle %#lx passed.\n", handle); - return NULL; + goto done; }
entry = &t->entries[handle]; if (entry->type != type) { WARN("Handle %#lx (%p) is not of type %#x.\n", handle, entry->object, type); - return NULL; + entry = NULL; }
- return entry->object; +done: + if (t == &global_handle_table) + ReleaseSRWLockExclusive(&global_handle_table_lock); + return entry ? entry->object : NULL; }
HRESULT WINAPI GetSurfaceFromDC(HDC dc, IDirectDrawSurface4 **surface, HDC *device_dc) @@ -815,6 +849,12 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) return FALSE; }
+ if (!ddraw_handle_table_init(&global_handle_table, 64)) + { + UnregisterClassA(DDRAW_WINDOW_CLASS_NAME, inst); + return FALSE; + } + /* On Windows one can force the refresh rate that DirectDraw uses by * setting an override value in dxdiag. This is documented in KB315614 * (main article), KB230002, and KB217348. By comparing registry dumps @@ -866,6 +906,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) if (WARN_ON(ddraw)) { struct ddraw *ddraw; + unsigned int i;
LIST_FOR_EACH_ENTRY(ddraw, &global_ddraw_list, struct ddraw, ddraw_list_entry) { @@ -884,6 +925,26 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) surface->ref2, surface->ref1, surface->gamma_count); } } + + for (i = 0; i < global_handle_table.entry_count; ++i) + { + struct ddraw_handle_entry *entry = &global_handle_table.entries[i]; + + switch (entry->type) + { + case DDRAW_HANDLE_FREE: + break; + + case DDRAW_HANDLE_MATERIAL: + WARN("Material handle %#x (%p) not unset properly.\n", i + 1, entry->object); + break; + + default: + WARN("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type); + break; + } + } + ddraw_handle_table_destroy(&global_handle_table); }
if (reserved) break; diff --git a/dlls/ddraw/material.c b/dlls/ddraw/material.c index d8cb41f1733..efc739c8dbb 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(NULL, 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(NULL, 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..98b03c60d72 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(NULL, material - 1, DDRAW_HANDLE_MATERIAL))) { WARN("Invalid material handle %#lx.\n", material); wined3d_mutex_unlock();