Hi Stefan

This is my first try at implementing the UpdateSemantics mesh method.
It works fine here on my local machine, passes the new tests, and
works with my little interactive demo(not included). I still have a
few questions though.

This implementation allocates new heap memory and I suspect that it
would be faster to re-use the already allocated memory. That would,
however, require quite a bit of re-engineering. Should I submit the
current version or wait and try to do an optimized version?

Btw should I roll all or some of the patches up into a single patch?

Any other comments about the patches in general?

Cheers,
Michael Mc Donnell
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index cedef32..976c758 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -2,6 +2,7 @@
  * Copyright 2008 David Adam
  * Copyright 2008 Luis Busquets
  * Copyright 2009 Henri Verbeet for CodeWeavers
+ * Copyright 2011 Google (Michael Mc Donnell)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -3305,6 +3306,165 @@ static void D3DXGenerateAdjacencyTest(void)
     if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh);
 }
 
+typedef struct
+{
+    HWND hwnd;
+    IDirect3D9 *d3d;
+    IDirect3DDevice9 *device;
+} TestContext;
+
+/*
+ * Initializes a TestContext. Use this to initialize DirectX.
+ */
+static TestContext* NewTestContext(void)
+{
+    HRESULT hr;
+    TestContext* testContext;
+    HWND hwnd;
+    IDirect3D9 *d3d;
+    IDirect3DDevice9 *device;
+    D3DPRESENT_PARAMETERS d3dpp;
+
+    hwnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+    if (!hwnd)
+    {
+        skip("Couldn't create application window\n");
+        return NULL;
+    }
+
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    if (!d3d)
+    {
+        skip("Couldn't create IDirect3D9 object\n");
+        DestroyWindow(hwnd);
+        return NULL;
+    }
+
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed = TRUE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
+    if (FAILED(hr))
+    {
+        skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
+        IDirect3D9_Release(d3d);
+        DestroyWindow(hwnd);
+        return NULL;
+    }
+
+    testContext = HeapAlloc(GetProcessHeap(), 0, sizeof(TestContext));
+    testContext->hwnd = hwnd;
+    testContext->d3d = d3d;
+    testContext->device = device;
+
+    return testContext;
+}
+
+static void FreeTestContext(TestContext *testContext)
+{
+    if (testContext == NULL)
+        return;
+
+    if (testContext->device != NULL)
+        IDirect3DDevice9_Release(testContext->device);
+
+    if (testContext->d3d != NULL)
+        IDirect3D9_Release(testContext->d3d);
+
+    if (testContext->hwnd != NULL)
+        DestroyWindow(testContext->hwnd);
+
+    HeapFree(GetProcessHeap(), 0, testContext);
+}
+
+typedef struct
+{
+    float x0, y0, z0; /* Position 0 */
+    float x1, y1, z1; /* Position 1 */
+    float nx, ny, nz; /* Normal */
+    DWORD color;
+} VertexTwoPositions;
+
+static void UpdateSemanticsTest(void)
+{
+    HRESULT hr;
+    TestContext *tc = NewTestContext();
+    LPD3DXMESH mesh;
+    D3DVERTEXELEMENT9 declaration0[] =
+    {
+         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
+         {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
+         {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
+         D3DDECL_END()
+    };
+    /* x0, y0, z0, x1, y1, z1 ,nx, ny, nz, color */
+    VertexTwoPositions vertices[] =
+    {
+        {  0.0f,  1.0f,  0.f,    1.0f,  0.0f,  0.f,    0.0f,  0.0f,  1.0f, 0xffff0000, },
+        {  1.0f, -1.0f,  0.f,   -1.0f, -1.0f,  0.f,    0.0f,  0.0f,  1.0f, 0xff00ff00, },
+        { -1.0f, -1.0f,  0.f,   -1.0f,  1.0f,  0.f,    0.0f,  0.0f,  1.0f, 0xff0000ff, },
+    };
+    unsigned int faces[] = {0, 1, 2};
+    unsigned int attributes[] = {0};
+    unsigned int numFaces = 1;
+    unsigned int numVertices = 3;
+    DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
+    LPVOID pVertices;
+    LPVOID pFaces;
+    LPDWORD pAttributes;
+    D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
+    D3DVERTEXELEMENT9 *pDecl;
+
+    if (tc == NULL)
+        return;
+
+    /* Create the test mesh */
+    hr = D3DXCreateMesh(numFaces, numVertices, options, declaration0, tc->device, &mesh);
+    if (FAILED(hr))
+    {
+        skip("Couldn't create test mesh %#x\n", hr);
+        goto cleanup;
+    }
+
+    mesh->lpVtbl->LockVertexBuffer(mesh, 0, &pVertices);
+    memcpy(pVertices, vertices, sizeof(vertices));
+    mesh->lpVtbl->UnlockVertexBuffer(mesh);
+
+    mesh->lpVtbl->LockIndexBuffer(mesh, 0, &pFaces);
+    memcpy(pFaces, faces, sizeof(faces));
+    mesh->lpVtbl->UnlockIndexBuffer(mesh);
+
+    mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &pAttributes);
+    memcpy(pAttributes, attributes, sizeof(attributes));
+    mesh->lpVtbl->UnlockAttributeBuffer(mesh);
+
+    /* Get the declaration and try to change it */
+    hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
+    if (FAILED(hr))
+    {
+        skip("Couldn't get mesh declaration %#x\n", hr);
+        goto cleanup;
+    }
+
+    for (pDecl = declaration; pDecl->Stream != 0xFF; pDecl++)
+    {
+        if (pDecl->Usage == D3DDECLUSAGE_POSITION)
+        {
+            /* Use second vertex position instead of first */
+            pDecl->Offset = 12;
+        }
+    }
+
+    hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
+    todo_wine ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
+
+cleanup:
+    if (mesh)
+        mesh->lpVtbl->Release(mesh);
+
+    FreeTestContext(tc);
+}
+
 START_TEST(mesh)
 {
     D3DXBoundProbeTest();
@@ -3322,4 +3482,5 @@ START_TEST(mesh)
     test_get_decl_vertex_size();
     test_fvf_decl_conversion();
     D3DXGenerateAdjacencyTest();
+    UpdateSemanticsTest();
 }
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 976c758..09bd27f 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -3408,6 +3408,7 @@ static void UpdateSemanticsTest(void)
     unsigned int attributes[] = {0};
     unsigned int numFaces = 1;
     unsigned int numVertices = 3;
+    int offset = 12;
     DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM;
     LPVOID pVertices;
     LPVOID pFaces;
@@ -3451,13 +3452,31 @@ static void UpdateSemanticsTest(void)
         if (pDecl->Usage == D3DDECLUSAGE_POSITION)
         {
             /* Use second vertex position instead of first */
-            pDecl->Offset = 12;
+            pDecl->Offset = offset;
         }
     }
 
     hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
     todo_wine ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
 
+    /* Check that declaration was written by getting it again */
+    ZeroMemory(declaration, sizeof(declaration));
+    hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
+    if (FAILED(hr))
+    {
+        skip("Couldn't get mesh declaration %#x\n", hr);
+        goto cleanup;
+    }
+    
+    for (pDecl = declaration; pDecl->Stream != 0xFF; pDecl++)
+    {
+        if (pDecl->Usage == D3DDECLUSAGE_POSITION)
+        {
+            todo_wine ok(pDecl->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
+                pDecl->Offset, offset);
+        }
+    }
+
 cleanup:
     if (mesh)
         mesh->lpVtbl->Release(mesh);
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 09bd27f..c0ca7ec 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -3477,6 +3477,27 @@ static void UpdateSemanticsTest(void)
         }
     }
 
+    /* UpdateSemantics does not check for a bigger vertex size */
+    ZeroMemory(declaration, sizeof(declaration));
+    hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
+    if (FAILED(hr))
+    {
+        skip("Couldn't get mesh declaration %#x\n", hr);
+        goto cleanup;
+    }
+    
+    for (pDecl = declaration; pDecl->Stream != 0xFF; pDecl++)
+    {
+        if (pDecl->Type == D3DDECLTYPE_FLOAT3)
+        {
+            pDecl->Type = D3DDECLTYPE_FLOAT4;
+        }
+    }
+
+    hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
+    todo_wine ok(hr == D3D_OK, "Test UpdateSematics for bigger vertex size, "
+        "got %#x expected D3D_OK\n", hr);
+
 cleanup:
     if (mesh)
         mesh->lpVtbl->Release(mesh);
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index c5954b3..988ea64 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2009 David Adam
  * Copyright (C) 2010 Tony Wasserka
  * Copyright (C) 2011 Dylan Smith
+ * Copyright (C) 2011 Google (Michael Mc Donnell)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -597,11 +598,28 @@ cleanup:
 
 static HRESULT WINAPI ID3DXMeshImpl_UpdateSemantics(ID3DXMesh *iface, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
 {
+    HRESULT hr;
     ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
+    IDirect3DVertexDeclaration9 *new_vertex_declaration;
 
-    FIXME("(%p)->(%p): stub\n", This, declaration);
+    TRACE("(%p)->(%p)\n", This, declaration);
 
-    return E_NOTIMPL;
+    /* Create new vertex declaration */
+    hr = IDirect3DDevice9_CreateVertexDeclaration(This->device,
+                                                  declaration,
+                                                  &new_vertex_declaration);
+    if (FAILED(hr))
+    {
+        WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexDeclaration.\n",hr);
+        return hr;
+    }
+
+    /* Free old vertex declaration */
+    IDirect3DVertexDeclaration9_Release(This->vertex_declaration);
+    /* Use new declaration */
+    This->vertex_declaration = new_vertex_declaration;
+
+    return D3D_OK;
 }
 
 /*** ID3DXMesh ***/
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index c0ca7ec..4da2894 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -3457,7 +3457,7 @@ static void UpdateSemanticsTest(void)
     }
 
     hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
-    todo_wine ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
+    ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
 
     /* Check that declaration was written by getting it again */
     ZeroMemory(declaration, sizeof(declaration));
@@ -3472,7 +3472,7 @@ static void UpdateSemanticsTest(void)
     {
         if (pDecl->Usage == D3DDECLUSAGE_POSITION)
         {
-            todo_wine ok(pDecl->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
+            ok(pDecl->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
                 pDecl->Offset, offset);
         }
     }
@@ -3495,7 +3495,7 @@ static void UpdateSemanticsTest(void)
     }
 
     hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
-    todo_wine ok(hr == D3D_OK, "Test UpdateSematics for bigger vertex size, "
+    ok(hr == D3D_OK, "Test UpdateSematics for bigger vertex size, "
         "got %#x expected D3D_OK\n", hr);
 
 cleanup:


Reply via email to