[PATCH 2/5] d3d9: Store wined3d vertex declarations in the fvf lookup table.

Henri Verbeet hverbeet at codeweavers.com
Wed Apr 11 15:52:03 CDT 2012


This also implicitly gets rid of the convFVF hack in
IDirect3DVertexDeclaration9Impl_Release().
---
 dlls/d3d9/d3d9_private.h      |   11 ++-
 dlls/d3d9/device.c            |  159 ++++++++++++++++++++++-------------------
 dlls/d3d9/vertexdeclaration.c |   35 +++-------
 3 files changed, 103 insertions(+), 102 deletions(-)

diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 6ad6eed..485ee12 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -156,6 +156,12 @@ typedef struct IDirect3D9Impl
 
 void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
 
+struct fvf_declaration
+{
+    struct wined3d_vertex_declaration *decl;
+    DWORD fvf;
+};
+
 /*****************************************************************************
  * IDirect3DDevice9 implementation structure
  */
@@ -169,8 +175,8 @@ typedef struct IDirect3DDevice9Impl
     /* Avoids recursion with nested ReleaseRef to 0 */
     BOOL                          inDestruction;
 
-    IDirect3DVertexDeclaration9  **convertedDecls;
-    unsigned int                 numConvertedDecls, declArraySize;
+    struct fvf_declaration *fvf_decls;
+    UINT fvf_decl_count, fvf_decl_size;
 
     BOOL                          notreset;
     BOOL                          in_scene;
@@ -394,7 +400,6 @@ typedef struct IDirect3DVertexDeclaration9Impl {
   LPDIRECT3DDEVICE9EX parentDevice;
 } IDirect3DVertexDeclaration9Impl;
 
-void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) DECLSPEC_HIDDEN;
 HRESULT d3d9_vertex_declaration_create(IDirect3DDevice9Impl *device,
         const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9Impl **declaration) DECLSPEC_HIDDEN;
 
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 3aeb437..440533c 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -234,36 +234,38 @@ static ULONG WINAPI IDirect3DDevice9Impl_AddRef(IDirect3DDevice9Ex *iface)
 
 static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevice9Ex *iface)
 {
-    IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
+    IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
     ULONG ref;
 
-    if (This->inDestruction) return 0;
-    ref = InterlockedDecrement(&This->ref);
+    if (device->inDestruction)
+        return 0;
+
+    ref = InterlockedDecrement(&device->ref);
 
     TRACE("%p decreasing refcount to %u.\n", iface, ref);
 
-    if (ref == 0) {
-      unsigned i;
-      This->inDestruction = TRUE;
+    if (!ref)
+    {
+        unsigned i;
+        device->inDestruction = TRUE;
 
-      wined3d_mutex_lock();
-      for(i = 0; i < This->numConvertedDecls; i++) {
-          /* Unless Wine is buggy or the app has a bug the refcount will be 0, because decls hold a reference to the
-           * device
-           */
-          IDirect3DVertexDeclaration9Impl_Destroy(This->convertedDecls[i]);
-      }
-      HeapFree(GetProcessHeap(), 0, This->convertedDecls);
+        wined3d_mutex_lock();
+        for (i = 0; i < device->fvf_decl_count; ++i)
+        {
+            wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
+        }
+        HeapFree(GetProcessHeap(), 0, device->fvf_decls);
 
-      wined3d_device_uninit_3d(This->wined3d_device);
-      wined3d_device_release_focus_window(This->wined3d_device);
-      wined3d_device_decref(This->wined3d_device);
-      wined3d_mutex_unlock();
+        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_device_release_focus_window(device->wined3d_device);
+        wined3d_device_decref(device->wined3d_device);
+        wined3d_mutex_unlock();
 
-      IDirect3D9Ex_Release(&This->d3d_parent->IDirect3D9Ex_iface);
+        IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
 
-      HeapFree(GetProcessHeap(), 0, This);
+        HeapFree(GetProcessHeap(), 0, device);
     }
+
     return ref;
 }
 
@@ -2136,91 +2138,100 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(IDirect3DDevice9
     return hr;
 }
 
-static IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) {
-    HRESULT hr;
-    D3DVERTEXELEMENT9* elements = NULL;
-    IDirect3DVertexDeclaration9* pDecl = NULL;
+static struct wined3d_vertex_declaration *device_get_fvf_declaration(IDirect3DDevice9Impl *device, DWORD fvf)
+{
+    struct wined3d_vertex_declaration *wined3d_declaration;
+    struct fvf_declaration *fvf_decls = device->fvf_decls;
+    IDirect3DVertexDeclaration9Impl *d3d9_declaration;
+    D3DVERTEXELEMENT9 *elements;
     int p, low, high; /* deliberately signed */
-    IDirect3DVertexDeclaration9  **convertedDecls = This->convertedDecls;
+    HRESULT hr;
 
     TRACE("Searching for declaration for fvf %08x... ", fvf);
 
     low = 0;
-    high = This->numConvertedDecls - 1;
-    while(low <= high) {
+    high = device->fvf_decl_count - 1;
+    while (low <= high)
+    {
         p = (low + high) >> 1;
         TRACE("%d ", p);
-        if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF == fvf) {
-            TRACE("found %p\n", convertedDecls[p]);
-            return convertedDecls[p];
-        } else if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF < fvf) {
+
+        if (fvf_decls[p].fvf == fvf)
+        {
+            TRACE("found %p.\n", fvf_decls[p].decl);
+            return fvf_decls[p].decl;
+        }
+
+        if (fvf_decls[p].fvf < fvf)
             low = p + 1;
-        } else {
+        else
             high = p - 1;
-        }
     }
     TRACE("not found. Creating and inserting at position %d.\n", low);
 
-    hr = vdecl_convert_fvf(fvf, &elements);
-    if (hr != S_OK) return NULL;
-
-    hr = IDirect3DDevice9Impl_CreateVertexDeclaration(&This->IDirect3DDevice9Ex_iface, elements,
-            &pDecl);
-    HeapFree(GetProcessHeap(), 0, elements); /* CreateVertexDeclaration makes a copy */
-    if (hr != S_OK) return NULL;
-
-    if(This->declArraySize == This->numConvertedDecls) {
-        int grow = max(This->declArraySize / 2, 8);
-        convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
-                                     sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
-        if(!convertedDecls) {
-            /* This will destroy it */
-            IDirect3DVertexDeclaration9_Release(pDecl);
+    if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
+        return NULL;
+
+    hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
+    HeapFree(GetProcessHeap(), 0, elements);
+    if (FAILED(hr))
+        return NULL;
+
+    if (device->fvf_decl_size == device->fvf_decl_count)
+    {
+        UINT grow = max(device->fvf_decl_size / 2, 8);
+
+        fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
+        if (!fvf_decls)
+        {
+            IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
             return NULL;
         }
-        This->convertedDecls = convertedDecls;
-        This->declArraySize += grow;
+        device->fvf_decls = fvf_decls;
+        device->fvf_decl_size += grow;
     }
 
-    memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(IDirect3DVertexDeclaration9Impl *) * (This->numConvertedDecls - low));
-    convertedDecls[low] = pDecl;
-    This->numConvertedDecls++;
+    d3d9_declaration->convFVF = fvf;
+    wined3d_declaration = d3d9_declaration->wineD3DVertexDeclaration;
+    wined3d_vertex_declaration_incref(wined3d_declaration);
+    IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
+
+    memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
+    fvf_decls[low].decl = wined3d_declaration;
+    fvf_decls[low].fvf = fvf;
+    ++device->fvf_decl_count;
 
-    /* Will prevent the decl from being destroyed */
-    ((IDirect3DVertexDeclaration9Impl *) pDecl)->convFVF = fvf;
-    IDirect3DVertexDeclaration9_Release(pDecl); /* Does not destroy now */
+    TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
 
-    TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
-    return pDecl;
+    return wined3d_declaration;
 }
 
-static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD FVF)
+static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
 {
     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
-    IDirect3DVertexDeclaration9 *decl;
+    struct wined3d_vertex_declaration *decl;
     HRESULT hr;
 
-    TRACE("iface %p, fvf %#x.\n", iface, FVF);
+    TRACE("iface %p, fvf %#x.\n", iface, fvf);
 
-    if (!FVF)
+    if (!fvf)
     {
-        WARN("%#x is not a valid FVF\n", FVF);
+        WARN("%#x is not a valid FVF.\n", fvf);
         return D3D_OK;
     }
 
     wined3d_mutex_lock();
-    decl = getConvertedDecl(This, FVF);
-    wined3d_mutex_unlock();
-
-    if (!decl)
+    if (!(decl = device_get_fvf_declaration(This, fvf)))
     {
-         /* Any situation when this should happen, except out of memory? */
-         ERR("Failed to create a converted vertex declaration\n");
-         return D3DERR_DRIVERINTERNALERROR;
+        wined3d_mutex_unlock();
+        ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
+        return D3DERR_DRIVERINTERNALERROR;
     }
 
-    hr = IDirect3DDevice9Impl_SetVertexDeclaration(iface, decl);
-    if (FAILED(hr)) ERR("Failed to set vertex declaration\n");
+    hr = wined3d_device_set_vertex_declaration(This->wined3d_device, decl);
+    if (FAILED(hr))
+        ERR("Failed to set vertex declaration.\n");
+    wined3d_mutex_unlock();
 
     return hr;
 }
@@ -3466,8 +3477,8 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IDirect3D9Impl *parent, struct
 
     /* Initialize the converted declaration array. This creates a valid pointer
      * and when adding decls HeapReAlloc() can be used without further checking. */
-    device->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0);
-    if (!device->convertedDecls)
+    device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
+    if (!device->fvf_decls)
     {
         ERR("Failed to allocate FVF vertex declaration map memory.\n");
         wined3d_mutex_lock();
diff --git a/dlls/d3d9/vertexdeclaration.c b/dlls/d3d9/vertexdeclaration.c
index a003d88..4636b14 100644
--- a/dlls/d3d9/vertexdeclaration.c
+++ b/dlls/d3d9/vertexdeclaration.c
@@ -219,44 +219,29 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLA
 
     TRACE("%p increasing refcount to %u.\n", iface, ref);
 
-    if(ref == 1) {
+    if (ref == 1)
+    {
         IDirect3DDevice9Ex_AddRef(This->parentDevice);
-        if (!This->convFVF)
-        {
-            wined3d_mutex_lock();
-            wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
-            wined3d_mutex_unlock();
-        }
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
+        wined3d_mutex_unlock();
     }
 
     return ref;
 }
 
-void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
-
-    if(This->ref != 0) {
-        /* Should not happen unless wine has a bug or the application releases references it does not own */
-        ERR("Destroying vdecl with ref != 0\n");
-    }
-
-    wined3d_mutex_lock();
-    wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
-    wined3d_mutex_unlock();
-}
-
 static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) {
     IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("%p decreasing refcount to %u.\n", iface, ref);
 
-    if (ref == 0) {
+    if (!ref)
+    {
         IDirect3DDevice9Ex *parentDevice = This->parentDevice;
-
-        if(!This->convFVF) {
-            IDirect3DVertexDeclaration9Impl_Destroy(iface);
-        }
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
+        wined3d_mutex_unlock();
 
         /* Release the device last, as it may cause the device to be destroyed. */
         IDirect3DDevice9Ex_Release(parentDevice);
-- 
1.7.3.4




More information about the wine-patches mailing list