Stefan Dösinger : d3d8: Convert fvfs to vertex declarations.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 21 09:47:33 CDT 2007


Module: wine
Branch: master
Commit: 527295e57f70358fd9dd6b5004da8bf3cd716ea3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=527295e57f70358fd9dd6b5004da8bf3cd716ea3

Author: Stefan Dösinger <stefandoesinger at gmx.at>
Date:   Tue Jun 19 22:20:26 2007 +0200

d3d8: Convert fvfs to vertex declarations.

---

 dlls/d3d8/d3d8_private.h |   10 +++++++
 dlls/d3d8/device.c       |   64 +++++++++++++++++++++++++++++++++++++++++++--
 dlls/d3d8/directx.c      |    9 ++++++
 3 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 3182427..229762b 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -167,6 +167,12 @@ extern const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl;
 
 typedef void * shader_handle;
 
+struct FvfToDecl
+{
+    DWORD fvf;
+    IWineD3DVertexDeclaration *decl;
+};
+
 struct IDirect3DDevice8Impl
 {
     /* IUnknown fields */
@@ -179,6 +185,10 @@ struct IDirect3DDevice8Impl
     shader_handle                *shader_handles;
     shader_handle                *free_shader_handles;
 
+    /* FVF management */
+    struct FvfToDecl       *decls;
+    UINT                    numConvertedDecls, declArraySize;
+
     /* Avoids recursion with nested ReleaseRef to 0 */
     BOOL                          inDestruction;
 };
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index f7bc68f..0b2436d 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -97,9 +97,16 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        int i;
+
         TRACE("Releasing wined3d device %p\n", This->WineD3DDevice);
         EnterCriticalSection(&d3d8_cs);
         This->inDestruction = TRUE;
+
+        for(i = 0; i < This->numConvertedDecls; i++) {
+            IWineD3DVertexDeclaration_Release(This->decls[i].decl);
+        }
+
         IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroyDepthStencilSurface, D3D8CB_DestroySwapChain);
         IWineD3DDevice_Release(This->WineD3DDevice);
         HeapFree(GetProcessHeap(), 0, This->shader_handles);
@@ -1566,6 +1573,59 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8
     return hrc;
 }
 
+IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8Impl *This, DWORD fvf)
+{
+    HRESULT hr;
+    IWineD3DVertexDeclaration* pDecl = NULL;
+    int p, low, high; /* deliberately signed */
+    struct FvfToDecl *convertedDecls = This->decls;
+
+    TRACE("Searching for declaration for fvf %08x... ", fvf);
+
+    low = 0;
+    high = This->numConvertedDecls - 1;
+    while(low <= high) {
+        p = (low + high) >> 1;
+        TRACE("%d ", p);
+        if(convertedDecls[p].fvf == fvf) {
+            TRACE("found %p\n", convertedDecls[p].decl);
+            return convertedDecls[p].decl;
+        } else if(convertedDecls[p].fvf < fvf) {
+            low = p + 1;
+        } else {
+            high = p - 1;
+        }
+    }
+    TRACE("not found. Creating and inserting at position %d.\n", low);
+
+    hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->WineD3DDevice,
+                                                       &pDecl,
+                                                       (IUnknown *) This,
+                                                       fvf);
+    if (FAILED(hr)) return NULL;
+
+    if(This->declArraySize == This->numConvertedDecls) {
+        int grow = This->declArraySize / 2;
+        convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
+                                     sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
+        if(!convertedDecls) {
+            /* This will destroy it */
+            IWineD3DVertexDeclaration_Release(pDecl);
+            return NULL;
+        }
+        This->decls = convertedDecls;
+        This->declArraySize += grow;
+    }
+
+    memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
+    convertedDecls[low].decl = pDecl;
+    convertedDecls[low].fvf = fvf;
+    This->numConvertedDecls++;
+
+    TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
+    return pDecl;
+}
+
 static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD pShader) {
     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
     HRESULT hrc = D3D_OK;
@@ -1575,9 +1635,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa
     if (VS_HIGHESTFIXEDFXF >= pShader) {
         TRACE("Setting FVF, %d %d\n", VS_HIGHESTFIXEDFXF, pShader);
         IWineD3DDevice_SetFVF(This->WineD3DDevice, pShader);
-
-	/* Call SetVertexShader with a NULL shader to set the vertexshader in the stateblock to NULL. */
-        IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, NULL);
+        IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, IDirect3DDevice8Impl_FindDecl(This, pShader));
         IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
     } else {
         TRACE("Setting shader\n");
diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c
index 62d833a..54c87e6 100644
--- a/dlls/d3d8/directx.c
+++ b/dlls/d3d8/directx.c
@@ -472,6 +472,15 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapte
         *ppReturnedDeviceInterface = NULL;
     }
 
+    object->declArraySize = 16;
+    object->decls = HeapAlloc(GetProcessHeap(), 0, object->declArraySize * sizeof(*object->decls));
+    if(!object->decls) {
+        ERR("Out of memory\n");
+        IWineD3DDevice_Release(object->WineD3DDevice);
+        HeapFree(GetProcessHeap(), 0, object);
+        *ppReturnedDeviceInterface = NULL;
+        hr = E_OUTOFMEMORY;
+    }
     return hr;
 }
 




More information about the wine-cvs mailing list