From 51a315386e8ecfce65e23c6bb8639d1d20b88f1b Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 30 Jul 2010 10:15:24 +0200 Subject: [PATCH] ddraw: Use a less offensive handle table implementation for surfaces. --- dlls/ddraw/ddraw_private.h | 15 +--- dlls/ddraw/device.c | 136 +++++++------------------------------ dlls/ddraw/direct3d.c | 3 - dlls/ddraw/surface.c | 3 +- dlls/ddraw/texture.c | 11 +-- 5 files changed, 35 insertions(+), 133 deletions(-) diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index f41a695b865..9ff703d9739 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -322,17 +322,6 @@ extern const IParentVtbl IParent_Vtbl DECLSPEC_HIDDEN; /***************************************************************************** * IDirect3DDevice implementation *****************************************************************************/ -typedef enum -{ - DDrawHandle_Unknown = 0, - DDrawHandle_Texture = 1, -} DDrawHandleTypes; - -struct HandleEntry -{ - void *ptr; - DDrawHandleTypes type; -}; #define DDRAW_INVALID_HANDLE ~0U @@ -342,6 +331,7 @@ enum ddraw_handle_type DDRAW_HANDLE_MATERIAL, DDRAW_HANDLE_MATRIX, DDRAW_HANDLE_STATEBLOCK, + DDRAW_HANDLE_SURFACE, }; struct ddraw_handle_entry @@ -401,8 +391,6 @@ struct IDirect3DDeviceImpl DWORD buffer_size; /* Handle management */ - struct HandleEntry *Handles; - DWORD numHandles; struct ddraw_handle_table handle_table; D3DMATRIXHANDLE world, proj, view; }; @@ -419,7 +407,6 @@ extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN; /* Helper functions */ HRESULT IDirect3DImpl_GetCaps(IWineD3D *WineD3D, D3DDEVICEDESC *Desc123, D3DDEVICEDESC7 *Desc7) DECLSPEC_HIDDEN; -DWORD IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This) DECLSPEC_HIDDEN; WINED3DZBUFFERTYPE IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This) DECLSPEC_HIDDEN; static inline IDirect3DDeviceImpl *device_from_device1(IDirect3DDevice *iface) diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 581415822a5..da6a5c42711 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -366,30 +366,7 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface) } /* The texture handles should be unset by now, but there might be some bits - * missing in our reference counting(needs test). Do a sanity check - */ - for(i = 0; i < This->numHandles; i++) - { - if(This->Handles[i].ptr) - { - switch(This->Handles[i].type) - { - case DDrawHandle_Texture: - { - IDirectDrawSurfaceImpl *surf = This->Handles[i].ptr; - FIXME("Texture Handle %d not unset properly\n", i + 1); - surf->Handle = 0; - } - break; - - default: - FIXME("Unknown handle %d not unset properly\n", i + 1); - } - } - } - - HeapFree(GetProcessHeap(), 0, This->Handles); - + * missing in our reference counting(needs test). Do a sanity check. */ for (i = 0; i < This->handle_table.entry_count; ++i) { struct ddraw_handle_entry *entry = &This->handle_table.entries[i]; @@ -423,6 +400,14 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface) break; } + case DDRAW_HANDLE_SURFACE: + { + IDirectDrawSurfaceImpl *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; @@ -627,18 +612,21 @@ IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface, IDirect3DTexture2 *Tex2) { IDirect3DDeviceImpl *This = device_from_device2(iface); - DWORD swap; IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1); IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2); + DWORD h1, h2; + TRACE("(%p)->(%p,%p)\n", This, surf1, surf2); EnterCriticalSection(&ddraw_cs); - This->Handles[surf1->Handle - 1].ptr = surf2; - This->Handles[surf2->Handle - 1].ptr = surf1; - swap = surf2->Handle; - surf2->Handle = surf1->Handle; - surf1->Handle = swap; + h1 = surf1->Handle - 1; + h2 = surf2->Handle - 1; + This->handle_table.entries[h1].object = surf2; + This->handle_table.entries[h2].object = surf1; + surf2->Handle = h1 + 1; + surf1->Handle = h2 + 1; + LeaveCriticalSection(&ddraw_cs); return D3D_OK; @@ -2883,6 +2871,8 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, { case D3DRENDERSTATE_TEXTUREHANDLE: { + IDirectDrawSurfaceImpl *surf; + if(Value == 0) { hr = IWineD3DDevice_SetTexture(This->wineD3DDevice, @@ -2891,25 +2881,16 @@ IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, break; } - if(Value > This->numHandles) + surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE); + if (!surf) { - FIXME("Specified handle %d out of range\n", Value); + WARN("Invalid texture handle.\n"); hr = DDERR_INVALIDPARAMS; break; } - if(This->Handles[Value - 1].type != DDrawHandle_Texture) - { - FIXME("Handle %d isn't a texture handle\n", Value); - hr = DDERR_INVALIDPARAMS; - break; - } - else - { - IDirectDrawSurfaceImpl *surf = This->Handles[Value - 1].ptr; - IDirect3DTexture2 *tex = surf ? (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl : NULL; - hr = IDirect3DDevice3_SetTexture(iface, 0, tex); - break; - } + + hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl); + break; } case D3DRENDERSTATE_TEXTUREMAPBLEND: @@ -6873,71 +6854,6 @@ const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl = Thunk_IDirect3DDeviceImpl_1_GetDirect3D }; -/***************************************************************************** - * IDirect3DDeviceImpl_CreateHandle - * - * Not called from the VTable - * - * Some older interface versions operate with handles, which are basically - * DWORDs which identify an interface, for example - * IDirect3DDevice::SetRenderState with DIRECT3DRENDERSTATE_TEXTUREHANDLE - * - * Those handle could be just casts to the interface pointers or vice versa, - * but that is not 64 bit safe and would mean blindly derefering a DWORD - * passed by the app. Instead there is a dynamic array in the device which - * keeps a DWORD to pointer information and a type for the handle. - * - * Basically this array only grows, when a handle is freed its pointer is - * just set to NULL. There will be much more reads from the array than - * insertion operations, so a dynamic array is fine. - * - * Params: - * This: D3DDevice implementation for which this handle should be created - * - * Returns: - * A free handle on success - * 0 on failure - * - *****************************************************************************/ -DWORD -IDirect3DDeviceImpl_CreateHandle(IDirect3DDeviceImpl *This) -{ - DWORD i; - struct HandleEntry *oldHandles = This->Handles; - - TRACE("(%p)\n", This); - - for(i = 0; i < This->numHandles; i++) - { - if(This->Handles[i].ptr == NULL && - This->Handles[i].type == DDrawHandle_Unknown) - { - TRACE("Reusing freed handle %d\n", i + 1); - return i + 1; - } - } - - TRACE("Growing the handle array\n"); - - This->numHandles++; - This->Handles = HeapAlloc(GetProcessHeap(), 0, sizeof(struct HandleEntry) * This->numHandles); - if(!This->Handles) - { - ERR("Out of memory\n"); - This->Handles = oldHandles; - This->numHandles--; - return 0; - } - if(oldHandles) - { - memcpy(This->Handles, oldHandles, (This->numHandles - 1) * sizeof(struct HandleEntry)); - HeapFree(GetProcessHeap(), 0, oldHandles); - } - - TRACE("Returning %d\n", This->numHandles); - return This->numHandles; -} - /***************************************************************************** * IDirect3DDeviceImpl_UpdateDepthStencil * diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c index e213e24edcf..7fe01f10967 100644 --- a/dlls/ddraw/direct3d.c +++ b/dlls/ddraw/direct3d.c @@ -805,9 +805,6 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface, object->material = 0; object->target = target; - object->Handles = NULL; - object->numHandles = 0; - if (!ddraw_handle_table_init(&object->handle_table, 64)) { ERR("Failed to initialize handle table.\n"); diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 37eebff89fb..15ed3c425a2 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -250,8 +250,7 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This) /* Having a texture handle set implies that the device still exists */ if(This->Handle) { - This->ddraw->d3ddevice->Handles[This->Handle - 1].ptr = NULL; - This->ddraw->d3ddevice->Handles[This->Handle - 1].type = DDrawHandle_Unknown; + ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_SURFACE); } /* Reduce the ddraw surface count */ diff --git a/dlls/ddraw/texture.c b/dlls/ddraw/texture.c index 5579a6a9887..2fc5d5076ed 100644 --- a/dlls/ddraw/texture.c +++ b/dlls/ddraw/texture.c @@ -211,12 +211,15 @@ IDirect3DTextureImpl_GetHandle(IDirect3DTexture2 *iface, EnterCriticalSection(&ddraw_cs); if(!This->Handle) { - This->Handle = IDirect3DDeviceImpl_CreateHandle(d3d); - if(This->Handle) + DWORD h = ddraw_allocate_handle(&d3d->handle_table, This, DDRAW_HANDLE_SURFACE); + if (h == DDRAW_INVALID_HANDLE) { - d3d->Handles[This->Handle - 1].ptr = This; - d3d->Handles[This->Handle - 1].type = DDrawHandle_Texture; + ERR("Failed to allocate a texture handle.\n"); + LeaveCriticalSection(&ddraw_cs); + return DDERR_OUTOFMEMORY; } + + This->Handle = h + 1; } *lpHandle = This->Handle;