From d683a9106c60f585e28f9dda068b3ed0f7e9fd85 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 5 Feb 2010 04:57:10 +0100 Subject: Implement D3DXDeclaratorFromFVF with tests --- dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/d3dx9_36_private.h | 1 + dlls/d3dx9_36/mesh.c | 151 +++++++++++++++++++++++++++++++++++++- dlls/d3dx9_36/tests/mesh.c | 91 +++++++++++++++++++++++ dlls/d3dx9_36/util.c | 38 +++++++++- include/d3dx9mesh.h | 9 ++- 6 files changed, 288 insertions(+), 4 deletions(-) diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index 08bb7f5..875b561 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -118,7 +118,7 @@ @ stub D3DXCreateVolumeTextureFromResourceExW @ stub D3DXCreateVolumeTextureFromResourceW @ stdcall D3DXDebugMute(long) -@ stub D3DXDeclaratorFromFVF +@ stdcall D3DXDeclaratorFromFVF(long ptr) @ stub D3DXDisassembleEffect @ stub D3DXDisassembleShader @ stub D3DXFileCreate diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index cca4403..b3055b6 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -46,6 +46,7 @@ typedef struct _PixelFormatDesc { HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length); HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer, DWORD *length); +UINT vertex_element_size(D3DDECLTYPE type); const PixelFormatDesc *get_format_info(D3DFORMAT format); diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 91116b2..2dcab1a 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -2,7 +2,8 @@ * Mesh operations specific to D3DX9. * * Copyright (C) 2009 David Adam - * + * Copyright (C) 2010 Tony Wasserka + * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -167,6 +168,154 @@ HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWOR } /************************************************************************* + * D3DXDeclaratorFromFVF + */ +HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) +{ + unsigned int idx, idx2; + unsigned int offset; + BOOL has_pos = (fvf & D3DFVF_POSITION_MASK) != 0; + BOOL has_blend = (fvf & D3DFVF_XYZB5) > D3DFVF_XYZRHW; + BOOL has_blend_idx = has_blend && + (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB5) || + (fvf & D3DFVF_LASTBETA_D3DCOLOR) || + (fvf & D3DFVF_LASTBETA_UBYTE4)); + BOOL has_normal = (fvf & D3DFVF_NORMAL) != 0; + BOOL has_psize = (fvf & D3DFVF_PSIZE) != 0; + + BOOL has_diffuse = (fvf & D3DFVF_DIFFUSE) != 0; + BOOL has_specular = (fvf & D3DFVF_SPECULAR) !=0; + + DWORD num_textures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + DWORD texcoords = (fvf & 0xFFFF0000) >> 16; + + D3DVERTEXELEMENT9 end_element = D3DDECL_END(); + + unsigned int size; + DWORD num_blends = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1); + if (has_blend_idx) num_blends--; + + TRACE("fvf %u, Declaration %p\n", fvf, Declaration); + + if(fvf == D3DFVF_XYZB5) return D3DERR_INVALIDCALL; + + /* compute declaration size */ + size = has_pos + (has_blend && num_blends > 0) + has_blend_idx + has_normal + + has_psize + has_diffuse + has_specular + num_textures + 1; + + /* convert the declaration */ + Declaration[size-1] = end_element; + idx = 0; + + if (has_pos) { + if (!has_blend && (fvf & D3DFVF_XYZRHW)) { + Declaration[idx].Type = D3DDECLTYPE_FLOAT4; + Declaration[idx].Usage = D3DDECLUSAGE_POSITIONT; + } + else if (!has_blend && (fvf & D3DFVF_XYZW) == D3DFVF_XYZW) { + Declaration[idx].Type = D3DDECLTYPE_FLOAT4; + Declaration[idx].Usage = D3DDECLUSAGE_POSITION; + } + else { + Declaration[idx].Type = D3DDECLTYPE_FLOAT3; + Declaration[idx].Usage = D3DDECLUSAGE_POSITION; + } + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_blend && (num_blends > 0)) { + if (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR)) + Declaration[idx].Type = D3DDECLTYPE_D3DCOLOR; + else { + switch(num_blends) { + case 1: Declaration[idx].Type = D3DDECLTYPE_FLOAT1; break; + case 2: Declaration[idx].Type = D3DDECLTYPE_FLOAT2; break; + case 3: Declaration[idx].Type = D3DDECLTYPE_FLOAT3; break; + case 4: Declaration[idx].Type = D3DDECLTYPE_FLOAT4; break; + default: + ERR("Unexpected amount of blend values: %u\n", num_blends); + } + } + Declaration[idx].Usage = D3DDECLUSAGE_BLENDWEIGHT; + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_blend_idx) { + if (fvf & D3DFVF_LASTBETA_UBYTE4 || + (((fvf & D3DFVF_XYZB5) == D3DFVF_XYZB2) && (fvf & D3DFVF_LASTBETA_D3DCOLOR))) + Declaration[idx].Type = D3DDECLTYPE_UBYTE4; + else if (fvf & D3DFVF_LASTBETA_D3DCOLOR) + Declaration[idx].Type = D3DDECLTYPE_D3DCOLOR; + else + Declaration[idx].Type = D3DDECLTYPE_FLOAT1; + Declaration[idx].Usage = D3DDECLUSAGE_BLENDINDICES; + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_normal) { + Declaration[idx].Type = D3DDECLTYPE_FLOAT3; + Declaration[idx].Usage = D3DDECLUSAGE_NORMAL; + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_psize) { + Declaration[idx].Type = D3DDECLTYPE_FLOAT1; + Declaration[idx].Usage = D3DDECLUSAGE_PSIZE; + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_diffuse) { + Declaration[idx].Type = D3DDECLTYPE_D3DCOLOR; + Declaration[idx].Usage = D3DDECLUSAGE_COLOR; + Declaration[idx].UsageIndex = 0; + idx++; + } + + if (has_specular) { + Declaration[idx].Type = D3DDECLTYPE_D3DCOLOR; + Declaration[idx].Usage = D3DDECLUSAGE_COLOR; + Declaration[idx].UsageIndex = 1; + idx++; + } + + for (idx2 = 0; idx2 < num_textures; idx2++) { + unsigned int numcoords = (texcoords >> (idx2*2)) & 0x03; + switch (numcoords) { + case D3DFVF_TEXTUREFORMAT1: + Declaration[idx].Type = D3DDECLTYPE_FLOAT1; + break; + case D3DFVF_TEXTUREFORMAT2: + Declaration[idx].Type = D3DDECLTYPE_FLOAT2; + break; + case D3DFVF_TEXTUREFORMAT3: + Declaration[idx].Type = D3DDECLTYPE_FLOAT3; + break; + case D3DFVF_TEXTUREFORMAT4: + Declaration[idx].Type = D3DDECLTYPE_FLOAT4; + break; + } + Declaration[idx].Usage = D3DDECLUSAGE_TEXCOORD; + Declaration[idx].UsageIndex = idx2; + idx++; + } + + /* compute offsets and initialize the rest of the fields */ + for (idx = 0, offset = 0; idx < size-1; idx++) { + Declaration[idx].Stream = 0; + Declaration[idx].Method = D3DDECLMETHOD_DEFAULT; + Declaration[idx].Offset = offset; + offset += vertex_element_size(Declaration[idx].Type); + } + + return D3D_OK; +} + +/************************************************************************* * D3DXGetFVFVertexSize */ static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num) diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index 0f451a2..d2ecf2f 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 2010 Tony Wasserka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -225,6 +226,95 @@ static void D3DXComputeBoundingSphereTest(void) ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); } +static void D3DXDeclaratorFromFVFTest(void) +{ + D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; + HRESULT hr; + + int i; + + static const D3DVERTEXELEMENT9 exp1[6] = { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 0xC, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 0x18, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + {0, 0x1C, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, + {0, 0x20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END(), + }; + + static const D3DVERTEXELEMENT9 exp2[3] = { + {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0}, + {0, 0x10, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0}, + D3DDECL_END(), + }; + + static const D3DVERTEXELEMENT9 exp3[4] = { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 0xC, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 0x1C, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }; + + /* Note: passing NULL as declaration segfaults */ + hr = D3DXDeclaratorFromFVF(0, decl); + ok(hr == D3D_OK, "D3DXDeclaratorFromFVF returned %#x, expected %#x\n", hr, D3D_OK); + ok(decl[0].Stream == 0xFF, "D3DXDeclaratorFromFVF returned an incorrect vertex declaration\n"); /* end element */ + + hr = D3DXDeclaratorFromFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, decl); + ok(hr == D3D_OK, "D3DXDeclaratorFromFVF returned %#x, expected %#x\n", hr, D3D_OK); + + if (hr == D3D_OK) + { + for (i=0; i<4; i++) + { + ok(decl[i].Stream == exp1[i].Stream, "Returned stream %d, expected %d\n", decl[i].Stream, exp1[i].Stream); + ok(decl[i].Type == exp1[i].Type, "Returned type %d, expected %d\n", decl[i].Type, exp1[i].Type); + ok(decl[i].Method == exp1[i].Method, "Returned method %d, expected %d\n", decl[i].Method, exp1[i].Method); + ok(decl[i].Usage == exp1[i].Usage, "Returned usage %d, expected %d\n", decl[i].Usage, exp1[i].Usage); + ok(decl[i].UsageIndex == exp1[i].UsageIndex, "Returned usage index %d, expected %d\n", decl[i].UsageIndex, exp1[i].UsageIndex); + ok(decl[i].Offset == exp1[i].Offset, "Returned offset %d, expected %d\n", decl[1].Offset, exp1[i].Offset); + } + ok(decl[5].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } + + hr = D3DXDeclaratorFromFVF(D3DFVF_XYZRHW | D3DFVF_PSIZE, decl); + ok(hr == D3D_OK, "D3DXDeclaratorFromFVF returned %#x, expected %#x\n", hr, D3D_OK); + + if (hr == D3D_OK) + { + for (i=0; i<1; i++) + { + ok(decl[i].Stream == exp2[i].Stream, "Returned stream %d, expected %d\n", decl[i].Stream, exp2[i].Stream); + ok(decl[i].Type == exp2[i].Type, "Returned type %d, expected %d\n", decl[i].Type, exp1[i].Type); + ok(decl[i].Method == exp2[i].Method, "Returned method %d, expected %d\n", decl[i].Method, exp2[i].Method); + ok(decl[i].Usage == exp2[i].Usage, "Returned usage %d, expected %d\n", decl[i].Usage, exp2[i].Usage); + ok(decl[i].UsageIndex == exp2[i].UsageIndex, "Returned usage index %d, expected %d\n", decl[i].UsageIndex, exp2[i].UsageIndex); + ok(decl[i].Offset == exp2[i].Offset, "Returned offset %d, expected %d\n", decl[1].Offset, exp2[i].Offset); + } + ok(decl[2].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } + + hr = D3DXDeclaratorFromFVF(D3DFVF_XYZB5, decl); + ok(hr == D3DERR_INVALIDCALL, "D3DXDeclaratorFromFVF returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXDeclaratorFromFVF(D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4, decl); + ok(hr == D3D_OK, "D3DXDeclaratorFromFVF returned %#x, expected %#x\n", hr, D3D_OK); + + if (hr == D3D_OK) + { + for (i=0; i<2; i++) + { + ok(decl[i].Stream == exp3[i].Stream, "Returned stream %d, expected %d\n", decl[i].Stream, exp3[i].Stream); + ok(decl[i].Type == exp3[i].Type, "Returned type %d, expected %d\n", decl[i].Type, exp3[i].Type); + ok(decl[i].Method == exp3[i].Method, "Returned method %d, expected %d\n", decl[i].Method, exp3[i].Method); + ok(decl[i].Usage == exp3[i].Usage, "Returned usage %d, expected %d\n", decl[i].Usage, exp3[i].Usage); + ok(decl[i].UsageIndex == exp3[i].UsageIndex, "Returned usage index %d, expected %d\n", decl[i].UsageIndex, exp3[i].UsageIndex); + ok(decl[i].Offset == exp3[i].Offset, "Returned offset %d, expected %d\n", decl[1].Offset, exp3[i].Offset); + } + ok(decl[3].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } +} + static void D3DXGetFVFVertexSizeTest(void) { UINT got; @@ -459,6 +549,7 @@ START_TEST(mesh) D3DXBoundProbeTest(); D3DXComputeBoundingBoxTest(); D3DXComputeBoundingSphereTest(); + D3DXDeclaratorFromFVFTest(); D3DXGetFVFVertexSizeTest(); D3DXIntersectTriTest(); test_get_decl_vertex_size(); diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c index 748e6d1..11926ad 100644 --- a/dlls/d3dx9_36/util.c +++ b/dlls/d3dx9_36/util.c @@ -17,9 +17,13 @@ * */ -#include "wine/debug.h" +#include "windef.h" + #include "d3dx9_36_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3dx); /************************************************************ * pixel format table providing info about number of bytes per pixel, @@ -152,3 +156,35 @@ const PixelFormatDesc *get_format_info(D3DFORMAT format) while(formats[i].format != format && formats[i].format != D3DFMT_UNKNOWN) i++; return &formats[i]; } + +/************************************************************************* + * vertex_element_size + * + * Returns the size of a vertex element with the specified type in bytes + */ + +UINT vertex_element_size(D3DDECLTYPE type) +{ + switch (type) + { + case D3DDECLTYPE_FLOAT1: return 1 * 4; + case D3DDECLTYPE_FLOAT2: return 2 * 4; + case D3DDECLTYPE_FLOAT3: return 3 * 4; + case D3DDECLTYPE_FLOAT4: return 4 * 4; + case D3DDECLTYPE_D3DCOLOR: return 4 * 1; + case D3DDECLTYPE_UBYTE4: return 4 * 1; + case D3DDECLTYPE_SHORT2: return 2 * 2; + case D3DDECLTYPE_SHORT4: return 4 * 2; + case D3DDECLTYPE_UBYTE4N: return 4 * 1; + case D3DDECLTYPE_SHORT2N: return 2 * 2; + case D3DDECLTYPE_SHORT4N: return 4 * 2; + case D3DDECLTYPE_USHORT2N: return 2 * 2; + case D3DDECLTYPE_USHORT4N: return 4 * 2; + case D3DDECLTYPE_UDEC3: return 4; + case D3DDECLTYPE_DEC3N: return 4; + case D3DDECLTYPE_FLOAT16_2: return 2 * 2; + case D3DDECLTYPE_FLOAT16_4: return 4 * 2; + default: FIXME("Unhandled element type %#x, size will be incorrect.\n", type); + } + return 0; +} \ No newline at end of file diff --git a/include/d3dx9mesh.h b/include/d3dx9mesh.h index 9e0b333..fb1f155 100644 --- a/include/d3dx9mesh.h +++ b/include/d3dx9mesh.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 David Adam - * + * Copyright 2010 Tony Wasserka + * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -21,11 +22,17 @@ #ifndef __WINE_D3DX9MESH_H #define __WINE_D3DX9MESH_H +enum _MAX_FVF_DECL_SIZE +{ + MAX_FVF_DECL_SIZE = MAXD3DDECLLENGTH + 1 +}; + #ifdef __cplusplus extern "C" { #endif HRESULT WINAPI D3DXCreateBuffer(DWORD, LPD3DXBUFFER*); +HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD, D3DVERTEXELEMENT9[MAX_FVF_DECL_SIZE]); UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx); UINT WINAPI D3DXGetFVFVertexSize(DWORD); BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *); -- 1.6.4.4