Implementation of the ID3DXMatrixStack interface, with a few tests

=Jérôme Gardou jerome
Mon Oct 27 13:32:47 CDT 2008


---
 dlls/d3dx8/d3dx8_private.h |    8 ++-
 dlls/d3dx8/math.c          |  143 +++++++++++++++++++++++++++++++++++--------
 dlls/d3dx8/tests/math.c    |   30 +++++++++
 3 files changed, 152 insertions(+), 29 deletions(-)

diff --git a/dlls/d3dx8/d3dx8_private.h b/dlls/d3dx8/d3dx8_private.h
index 923f285..6d116c5 100644
--- a/dlls/d3dx8/d3dx8_private.h
+++ b/dlls/d3dx8/d3dx8_private.h
@@ -79,6 +79,11 @@ struct ID3DXFontImpl
 /*****************************************************************************
  * ID3DXMatrixStackImpl implementation structure
  */
+typedef struct D3DXMatrixStackNode {
+    D3DMATRIX* matrix ;
+    struct D3DXMatrixStackNode* next ;
+} D3DXMatrixStackNode;
+
 struct ID3DXMatrixStackImpl
 {
   /* IUnknown fields */
@@ -86,8 +91,7 @@ struct ID3DXMatrixStackImpl
   LONG                   ref;
 
   /* ID3DXMatrixStack fields */
-  int current;
-  D3DXMATRIX *stack;
+  D3DXMatrixStackNode* top;
 };
 
 #endif /*__WINE_D3DX8_PRIVATE_H */
diff --git a/dlls/d3dx8/math.c b/dlls/d3dx8/math.c
index 3bc171f..cad9cdc 100644
--- a/dlls/d3dx8/math.c
+++ b/dlls/d3dx8/math.c
@@ -584,6 +584,8 @@ D3DXMATRIX* WINAPI D3DXMatrixTranspose(D3DXMATRIX *pout, CONST D3DXMATRIX *pm)
 HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack)
 {
     ID3DXMatrixStackImpl* object;
+    if(ppstack == NULL)
+        return D3DERR_INVALIDCALL ;
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXMatrixStackImpl));
     if ( object == NULL )
@@ -593,7 +595,21 @@ HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, LPD3DXMATRIXSTACK* ppstack)
     }
     object->lpVtbl = &ID3DXMatrixStack_Vtbl;
     object->ref = 1;
-    object->current = 0;
+    object->top = HeapAlloc(GetProcessHeap(), 0, sizeof(D3DXMatrixStackNode)) ;
+    if (object->top == NULL) {
+         *ppstack = NULL ;
+         HeapFree(GetProcessHeap(), 0, object) ;
+         return E_OUTOFMEMORY ;
+    }
+    object->top->matrix = HeapAlloc(GetProcessHeap(), 0, sizeof(D3DMATRIX)) ;
+    if (object->top->matrix == NULL) {
+         *ppstack = NULL ;
+         HeapFree(GetProcessHeap(), 0, object->top) ;
+         HeapFree(GetProcessHeap(), 0, object) ;
+         return E_OUTOFMEMORY ;
+    }
+    D3DXMatrixIdentity(object->top->matrix) ;
+    object->top->next = NULL ;
     *ppstack = (LPD3DXMATRIXSTACK)object;
     return D3D_OK;
 }
@@ -624,7 +640,15 @@ static ULONG WINAPI ID3DXMatrixStackImpl_Release(ID3DXMatrixStack* iface)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
     ULONG ref = InterlockedDecrement(&This->ref);
-    if ( !ref ) HeapFree(GetProcessHeap(), 0, This);
+    if ( !ref )  {
+        while (This->top->next != NULL) {
+            This->lpVtbl->Pop(iface) ;
+        }
+        /*Freeing the last one*/
+        HeapFree(GetProcessHeap(),0, This->top->matrix) ;
+        HeapFree(GetProcessHeap(), 0, This->top) ;
+        HeapFree(GetProcessHeap(), 0, This);
+    }
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
     return ref;
 }
@@ -632,106 +656,171 @@ static ULONG WINAPI ID3DXMatrixStackImpl_Release(ID3DXMatrixStack* iface)
 static D3DXMATRIX* WINAPI ID3DXMatrixStackImpl_GetTop(ID3DXMatrixStack *iface)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return NULL;
+    return This->top->matrix ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_LoadIdentity(ID3DXMatrixStack *iface)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixIdentity(This->top->matrix) ;
     return D3D_OK;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_LoadMatrix(ID3DXMatrixStack *iface, LPD3DXMATRIX pm)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
+    if(iface == NULL || pm == NULL)
+        return D3DERR_INVALIDCALL ;
+    CopyMemory(This->top->matrix, pm, sizeof(D3DMATRIX)) ;
     return D3D_OK;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_MultMatrix(ID3DXMatrixStack *iface, LPD3DXMATRIX pm)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
+    if(iface == NULL || pm == NULL)
+        return D3DERR_INVALIDCALL ;
+    D3DXMatrixMultiply(This->top->matrix, This->top->matrix, pm) ;
     return D3D_OK;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_MultMatrixLocal(ID3DXMatrixStack *iface, LPD3DXMATRIX pm)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
+    if(iface == NULL || pm == NULL)
+        return D3DERR_INVALIDCALL ;
+    D3DXMatrixMultiply(This->top->matrix, pm, This->top->matrix) ;
     return D3D_OK;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_Pop(ID3DXMatrixStack *iface)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+    if(This->top->next != NULL) {
+        D3DXMatrixStackNode* current = This->top ;
+        This->top = current->next ;
+        HeapFree(GetProcessHeap(), 0, current->matrix) ;
+        HeapFree(GetProcessHeap(), 0, current) ;
+    } else 
+        D3DXMatrixIdentity(This->top->matrix) ;
+
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_Push(ID3DXMatrixStack *iface)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
+    D3DXMatrixStackNode* current ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    current = HeapAlloc(GetProcessHeap(), 0, sizeof(D3DXMatrixStackNode)) ;
+    current->next = This->top ;
+    current->matrix = HeapAlloc(GetProcessHeap(), 0, sizeof(D3DMATRIX)) ;
+    CopyMemory(current->matrix, This->top->matrix, sizeof(D3DMATRIX)) ;
+    This->top = current ;
     return D3D_OK;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateAxis(ID3DXMatrixStack *iface, LPD3DXVECTOR3 pv, FLOAT angle)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL || pv == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixRotationAxis( &tmp, pv, angle );
+    D3DXMatrixMultiply(This->top->matrix, This->top->matrix, &tmp) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateAxisLocal(ID3DXMatrixStack *iface, LPD3DXVECTOR3 pv, FLOAT angle)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL || pv == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixRotationAxis( &tmp, pv, angle );
+    D3DXMatrixMultiply(This->top->matrix, &tmp, This->top->matrix) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateYawPitchRoll(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixRotationYawPitchRoll( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, This->top->matrix, &tmp) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateYawPitchRollLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixRotationYawPitchRoll( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, &tmp, This->top->matrix) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_Scale(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixScaling( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, &tmp, This->top->matrix) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_ScaleLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixScaling( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, &tmp, This->top->matrix) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_Translate(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixTranslation( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, This->top->matrix, &tmp) ;
+    return D3D_OK ;
 }
 
 static HRESULT WINAPI ID3DXMatrixStackImpl_TranslateLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
 {
     ID3DXMatrixStackImpl *This = (ID3DXMatrixStackImpl *)iface;
-    FIXME("(%p) : stub\n",This);
-    return D3D_OK;
+    D3DXMATRIX tmp ;
+    if(iface == NULL)
+        return D3DERR_INVALIDCALL ;
+
+    D3DXMatrixTranslation( &tmp, x, y, z);
+    D3DXMatrixMultiply(This->top->matrix, &tmp, This->top->matrix) ;
+    return D3D_OK ;
 }
 
 static const ID3DXMatrixStackVtbl ID3DXMatrixStack_Vtbl =
diff --git a/dlls/d3dx8/tests/math.c b/dlls/d3dx8/tests/math.c
index 6a4b44d..4d38d6c 100644
--- a/dlls/d3dx8/tests/math.c
+++ b/dlls/d3dx8/tests/math.c
@@ -1396,6 +1396,35 @@ static void D3X8Vector4Test(void)
     expect_vec4(expectedtrans,gottrans);
 }
 
+static void D3DXMatrixStackTest(void)
+{
+    LPD3DXMATRIXSTACK MatrixStack = NULL;
+    D3DMATRIX* matrix_ptr = NULL;
+    ULONG ref ;
+    D3DXCreateMatrixStack(0 ,&MatrixStack) ;
+    ok(MatrixStack != NULL, "Could not create the ID3DXMatrixStack interface\n") ;
+
+    matrix_ptr = ID3DXMatrixStack_GetTop(MatrixStack) ;
+    ok(matrix_ptr != NULL, "Expected GetTop to return a non NULL matrix pointer\n") ;
+    ok(D3DXMatrixIsIdentity(matrix_ptr) == TRUE, "Expected top matrix of the new stack being identity\n") ;
+    ref = ID3DXMatrixStack_AddRef(MatrixStack) ;
+    ok(ref == 2, "Expected 2, got %d : expected GetTop to not addref\n", ref);
+
+    ID3DXMatrixStack_Push(MatrixStack) ;
+    ref = ID3DXMatrixStack_AddRef(MatrixStack) ;
+    ok(ref == 3, "Expected 3, got %d : expected Push to not addref\n", ref);
+    ID3DXMatrixStack_Pop(MatrixStack) ;
+    ID3DXMatrixStack_Pop(MatrixStack) ;
+    matrix_ptr = ID3DXMatrixStack_GetTop(MatrixStack) ;
+    ok(matrix_ptr != NULL, "Expected GetTop to return a non NULL matrix pointer\n") ;
+    ok(D3DXMatrixIsIdentity(matrix_ptr) == TRUE, "Expected top matrix of the stack being identity after over popping\n") ;
+    
+    /*Release everything*/
+    do {
+    ref = ID3DXMatrixStack_Release(MatrixStack) ;
+    } while ( ref != 0) ;
+}
+
 START_TEST(math)
 {
     D3DXColorTest();
@@ -1405,4 +1434,5 @@ START_TEST(math)
     D3X8Vector2Test();
     D3X8Vector3Test();
     D3X8Vector4Test();
+    D3DXMatrixStackTest() ;
 }
-- 
1.5.4.3


--------------030208040004000407050400--



More information about the wine-patches mailing list