[PATCH 2/6] ddraw: Use a less offensive handle table implementation for surfaces.

Henri Verbeet hverbeet at codeweavers.com
Fri Jul 30 03:15:24 CDT 2010


---
 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 f41a695..9ff703d 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 5814158..da6a5c4 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:
@@ -6874,71 +6855,6 @@ const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl =
 };
 
 /*****************************************************************************
- * 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
  *
  * Checks the current render target for attached depth stencils and sets the
diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c
index e213e24..7fe01f1 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 37eebff..15ed3c4 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 5579a6a..2fc5d50 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;
 
-- 
1.7.1




More information about the wine-patches mailing list