/* * vertex declaration implementation * * Copyright 2002-2005 Raphael Junqueira * Copyright 2004 Jason Edmeades * Copyright 2004 Christian Costa * * 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 * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl); /** * DirectX9 SDK download * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp * * Exploring D3DX * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp * * Using Vertex Shaders * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp * * Dx9 New * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp * * Dx9 Shaders * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp * * Dx9 D3DX * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp * * FVF * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp * * NVIDIA: DX8 Vertex Shader to NV Vertex Program * http://developer.nvidia.com/view.asp?IO=vstovp * * NVIDIA: Memory Management with VAR * http://developer.nvidia.com/view.asp?IO=var_memory_management */ /** Vertex Shader Declaration 8 data types tokens */ #define MAX_VSHADER_DECL_TYPES 8 static CONST char* VertexDecl8_DataTypes[] = { "D3DVSDT_FLOAT1", "D3DVSDT_FLOAT2", "D3DVSDT_FLOAT3", "D3DVSDT_FLOAT4", "D3DVSDT_D3DCOLOR", "D3DVSDT_UBYTE4", "D3DVSDT_SHORT2", "D3DVSDT_SHORT4", NULL }; static CONST char* VertexDecl8_Registers[] = { "D3DVSDE_POSITION", "D3DVSDE_BLENDWEIGHT", "D3DVSDE_BLENDINDICES", "D3DVSDE_NORMAL", "D3DVSDE_PSIZE", "D3DVSDE_DIFFUSE", "D3DVSDE_SPECULAR", "D3DVSDE_TEXCOORD0", "D3DVSDE_TEXCOORD1", "D3DVSDE_TEXCOORD2", "D3DVSDE_TEXCOORD3", "D3DVSDE_TEXCOORD4", "D3DVSDE_TEXCOORD5", "D3DVSDE_TEXCOORD6", "D3DVSDE_TEXCOORD7", "D3DVSDE_POSITION2", "D3DVSDE_NORMAL2", NULL }; typedef enum _D3DVSD_TOKENTYPE { D3DVSD_TOKEN_NOP = 0, D3DVSD_TOKEN_STREAM = 1, D3DVSD_TOKEN_STREAMDATA = 2, D3DVSD_TOKEN_TESSELLATOR = 3, D3DVSD_TOKEN_CONSTMEM = 4, D3DVSD_TOKEN_EXT = 5, /* RESERVED = 6 */ D3DVSD_TOKEN_END = 7, D3DVSD_FORCE_DWORD = 0x7FFFFFFF } D3DVSD_TOKENTYPE; typedef enum _D3DVSDE_REGISTER { D3DVSDE_POSITION = 0, D3DVSDE_BLENDWEIGHT = 1, D3DVSDE_BLENDINDICES = 2, D3DVSDE_NORMAL = 3, D3DVSDE_PSIZE = 4, D3DVSDE_DIFFUSE = 5, D3DVSDE_SPECULAR = 6, D3DVSDE_TEXCOORD0 = 7, D3DVSDE_TEXCOORD1 = 8, D3DVSDE_TEXCOORD2 = 9, D3DVSDE_TEXCOORD3 = 10, D3DVSDE_TEXCOORD4 = 11, D3DVSDE_TEXCOORD5 = 12, D3DVSDE_TEXCOORD6 = 13, D3DVSDE_TEXCOORD7 = 14, D3DVSDE_POSITION2 = 15, D3DVSDE_NORMAL2 = 16 } D3DVSDE_REGISTER; typedef enum _D3DVSDT_TYPE { D3DVSDT_FLOAT1 = 0x00, D3DVSDT_FLOAT2 = 0x01, D3DVSDT_FLOAT3 = 0x02, D3DVSDT_FLOAT4 = 0x03, D3DVSDT_D3DCOLOR = 0x04, D3DVSDT_UBYTE4 = 0x05, D3DVSDT_SHORT2 = 0x06, D3DVSDT_SHORT4 = 0x07 } D3DVSDT_TYPE; #define D3DVSD_CONSTADDRESSSHIFT 0 #define D3DVSD_EXTINFOSHIFT 0 #define D3DVSD_STREAMNUMBERSHIFT 0 #define D3DVSD_VERTEXREGSHIFT 0 #define D3DVSD_CONSTRSSHIFT 16 #define D3DVSD_DATATYPESHIFT 16 #define D3DVSD_SKIPCOUNTSHIFT 16 #define D3DVSD_VERTEXREGINSHIFT 20 #define D3DVSD_EXTCOUNTSHIFT 24 #define D3DVSD_CONSTCOUNTSHIFT 25 #define D3DVSD_DATALOADTYPESHIFT 28 #define D3DVSD_STREAMTESSSHIFT 28 #define D3DVSD_TOKENTYPESHIFT 29 #define D3DVSD_CONSTADDRESSMASK (0x7F << D3DVSD_CONSTADDRESSSHIFT) #define D3DVSD_EXTINFOMASK (0xFFFFFF << D3DVSD_EXTINFOSHIFT) #define D3DVSD_STREAMNUMBERMASK (0xF << D3DVSD_STREAMNUMBERSHIFT) #define D3DVSD_VERTEXREGMASK (0x1F << D3DVSD_VERTEXREGSHIFT) #define D3DVSD_CONSTRSMASK (0x1FFF << D3DVSD_CONSTRSSHIFT) #define D3DVSD_DATATYPEMASK (0xF << D3DVSD_DATATYPESHIFT) #define D3DVSD_SKIPCOUNTMASK (0xF << D3DVSD_SKIPCOUNTSHIFT) #define D3DVSD_EXTCOUNTMASK (0x1F << D3DVSD_EXTCOUNTSHIFT) #define D3DVSD_VERTEXREGINMASK (0xF << D3DVSD_VERTEXREGINSHIFT) #define D3DVSD_CONSTCOUNTMASK (0xF << D3DVSD_CONSTCOUNTSHIFT) #define D3DVSD_DATALOADTYPEMASK (0x1 << D3DVSD_DATALOADTYPESHIFT) #define D3DVSD_STREAMTESSMASK (0x1 << D3DVSD_STREAMTESSSHIFT) #define D3DVSD_TOKENTYPEMASK (0x7 << D3DVSD_TOKENTYPESHIFT) #define D3DVSD_END() 0xFFFFFFFF #define D3DVSD_NOP() 0x00000000 DWORD IWineD3DVertexDeclarationImpl_ParseToken8(const DWORD* pToken) { const DWORD token = *pToken; DWORD tokenlen = 1; switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */ case D3DVSD_TOKEN_NOP: TRACE(" 0x%08lx NOP()\n", token); break; case D3DVSD_TOKEN_STREAM: if (token & D3DVSD_STREAMTESSMASK) { TRACE(" 0x%08lx STREAM_TESS()\n", token); } else { TRACE(" 0x%08lx STREAM(%lu)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT)); } break; case D3DVSD_TOKEN_STREAMDATA: if (token & 0x10000000) { TRACE(" 0x%08lx SKIP(%lu)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT)); } else { DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); TRACE(" 0x%08lx REG(%s, %s)\n", token, VertexDecl8_Registers[reg], VertexDecl8_DataTypes[type]); } break; case D3DVSD_TOKEN_TESSELLATOR: if (token & 0x10000000) { DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); TRACE(" 0x%08lx TESSUV(%s) as %s\n", token, VertexDecl8_Registers[reg], VertexDecl8_DataTypes[type]); } else { DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); DWORD regout = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); DWORD regin = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT); TRACE(" 0x%08lx TESSNORMAL(%s, %s) as %s\n", token, VertexDecl8_Registers[regin], VertexDecl8_Registers[regout], VertexDecl8_DataTypes[type]); } break; case D3DVSD_TOKEN_CONSTMEM: { DWORD i; DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT); TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count); ++pToken; for (i = 0; i < count; ++i) { #if 0 TRACE(" c[%lu] = (0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", constaddress, *pToken, *(pToken + 1), *(pToken + 2), *(pToken + 3)); #endif TRACE(" c[%lu] = (%8f, %8f, %8f, %8f)\n", constaddress, *(const float*) pToken, *(const float*) (pToken + 1), *(const float*) (pToken + 2), *(const float*) (pToken + 3)); pToken += 4; ++constaddress; } tokenlen = (4 * count) + 1; } break; case D3DVSD_TOKEN_EXT: { DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); DWORD extinfo = ((token & D3DVSD_EXTINFOMASK) >> D3DVSD_EXTINFOSHIFT); TRACE(" 0x%08lx EXT(%lu, %lu)\n", token, count, extinfo); /* todo ... print extension */ tokenlen = count + 1; } break; case D3DVSD_TOKEN_END: TRACE(" 0x%08lx END()\n", token); break; default: TRACE(" 0x%08lx UNKNOWN\n", token); /* argg error */ } return tokenlen; } DWORD IWineD3DVertexDeclarationImpl_ParseToken9(const D3DVERTEXELEMENT9* pToken); HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl* This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl* object) { const DWORD* pToken = pDecl; DWORD fvf = 0; BOOL invalid_fvf = FALSE; DWORD tex = D3DFVF_TEX0; DWORD len = 0; DWORD stream = 0; DWORD token; DWORD tokenlen; DWORD tokentype; DWORD nTokens = 0; D3DVERTEXELEMENT9 convTo9[128]; TRACE("(%p) : pDecl(%p)\n", This, pDecl); while (D3DVSD_END() != *pToken) { token = *pToken; tokenlen = IWineD3DVertexDeclarationImpl_ParseToken8(pToken); tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); /** FVF generation block */ if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) { /** * how really works streams, * in DolphinVS dx8 dsk sample they seems to decal reg numbers !!! */ DWORD oldStream = stream; stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT); /* copy fvf if valid */ if (FALSE == invalid_fvf) { fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; tex = 0; object->fvf[oldStream] = fvf; object->allFVF |= fvf; } else { object->fvf[oldStream] = 0; tex = 0; } /* reset valid/invalid fvf */ fvf = 0; invalid_fvf = FALSE; } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) { DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); convTo9[nTokens].Stream = stream; convTo9[nTokens].Method = D3DDECLMETHOD_DEFAULT; convTo9[nTokens].UsageIndex = 0; convTo9[nTokens].Type = D3DDECLTYPE_UNUSED; switch (reg) { case D3DVSDE_POSITION: convTo9[nTokens].Usage = D3DDECLUSAGE_POSITION; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZ; break; case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZRHW; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; if (type >= MAX_VSHADER_DECL_TYPES) { TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported and unrecognized type %08lx\n", type); } else { TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } } break; case D3DVSDE_BLENDWEIGHT: convTo9[nTokens].Usage = D3DDECLUSAGE_BLENDWEIGHT; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_FLOAT1: fvf |= D3DFVF_XYZB1; break; case D3DVSDT_FLOAT2: fvf |= D3DFVF_XYZB2; break; case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZB3; break; case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZB4; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_BLENDINDICES: /* seem to be B5 as said in MSDN Dx9SDK ?? */ convTo9[nTokens].Usage = D3DDECLUSAGE_BLENDINDICES; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDINDINCES register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_NORMAL: /* TODO: only FLOAT3 supported ... another choice possible ? */ convTo9[nTokens].Usage = D3DDECLUSAGE_NORMAL; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_FLOAT3: fvf |= D3DFVF_NORMAL; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_NORMAL register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_PSIZE: /* TODO: only FLOAT1 supported ... another choice possible ? */ convTo9[nTokens].Usage = D3DDECLUSAGE_PSIZE; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_FLOAT1: fvf |= D3DFVF_PSIZE; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_PSIZE register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_DIFFUSE: /* TODO: only D3DCOLOR supported */ convTo9[nTokens].Usage = D3DDECLUSAGE_COLOR; convTo9[nTokens].UsageIndex = 0; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_DIFFUSE; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_DIFFUSE register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_SPECULAR: /* TODO: only D3DCOLOR supported */ convTo9[nTokens].Usage = D3DDECLUSAGE_COLOR; convTo9[nTokens].UsageIndex = 1; convTo9[nTokens].Type = type; switch (type) { case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_SPECULAR; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_SPECULAR register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } break; case D3DVSDE_TEXCOORD0: case D3DVSDE_TEXCOORD1: case D3DVSDE_TEXCOORD2: case D3DVSDE_TEXCOORD3: case D3DVSDE_TEXCOORD4: case D3DVSDE_TEXCOORD5: case D3DVSDE_TEXCOORD6: case D3DVSDE_TEXCOORD7: /* Fixme? - assume all tex coords in same stream */ { int texNo = 1 + (reg - D3DVSDE_TEXCOORD0); convTo9[nTokens].Usage = D3DDECLUSAGE_TEXCOORD; convTo9[nTokens].UsageIndex = texNo; convTo9[nTokens].Type = type; tex = max(tex, texNo); switch (type) { case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break; case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break; case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break; case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexDecl8_DataTypes[type]); } } break; case D3DVSDE_POSITION2: /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */ case D3DVSDE_NORMAL2: /* FIXME i don't know what to do here ;( */ FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token); break; } TRACE("VertexShader declaration define %lx as current FVF\n", fvf); } ++nTokens; len += tokenlen; pToken += tokenlen; } /* here D3DVSD_END() */ len += IWineD3DVertexDeclarationImpl_ParseToken8(pToken); convTo9[nTokens].Stream = 0xFF; convTo9[nTokens].Type = D3DDECLTYPE_UNUSED; /* copy fvf if valid */ if (FALSE == invalid_fvf) { fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; object->fvf[stream] = fvf; object->allFVF |= fvf; } else { object->fvf[stream] = 0; } TRACE("Completed, allFVF = %lx\n", object->allFVF); /* compute size */ object->declaration8Length = len * sizeof(DWORD); /* copy the declaration */ object->pDeclaration8 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declaration8Length); memcpy(object->pDeclaration8, pDecl, object->declaration8Length); /* compute convTo9 size */ object->declaration9NumElements = nTokens; /* copy the convTo9 declaration */ object->pDeclaration9 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nTokens * sizeof(D3DVERTEXELEMENT9)); memcpy(object->pDeclaration9, convTo9, nTokens * sizeof(D3DVERTEXELEMENT9)); { D3DVERTEXELEMENT9* pIt = object->pDeclaration9; TRACE("dumping of D3D9 Conversion:\n"); while (0xFF != pIt->Stream) { IWineD3DVertexDeclarationImpl_ParseToken9(pIt); ++pIt; } IWineD3DVertexDeclarationImpl_ParseToken9(pIt); } /* returns */ return D3D_OK; } static CONST char* VertexDecl9_DeclUsages[] = { "D3DDECLUSAGE_POSITION", "D3DDECLUSAGE_BLENDWEIGHT", "D3DDECLUSAGE_BLENDINDICES", "D3DDECLUSAGE_NORMAL", "D3DDECLUSAGE_PSIZE", "D3DDECLUSAGE_TEXCOORD", "D3DDECLUSAGE_TANGENT", "D3DDECLUSAGE_BINORMAL", "D3DDECLUSAGE_TESSFACTOR", "D3DDECLUSAGE_POSITIONT", "D3DDECLUSAGE_COLOR", "D3DDECLUSAGE_FOG", "D3DDECLUSAGE_DEPTH", "D3DDECLUSAGE_SAMPLE", NULL }; static CONST char* VertexDecl9_DeclMethods[] = { "D3DDECLMETHOD_DEFAULT", "D3DDECLMETHOD_PARTIALU", "D3DDECLMETHOD_PARTIALV", "D3DDECLMETHOD_CROSSUV", "D3DDECLMETHOD_UV", "D3DDECLMETHOD_LOOKUP", "D3DDECLMETHOD_LOOKUPPRESAMPLED", NULL }; static CONST char* VertexDecl9_DeclTypes[] = { "D3DDECLTYPE_FLOAT1", "D3DDECLTYPE_FLOAT2", "D3DDECLTYPE_FLOAT3", "D3DDECLTYPE_FLOAT4", "D3DDECLTYPE_D3DCOLOR", "D3DDECLTYPE_UBYTE4", "D3DDECLTYPE_SHORT2", "D3DDECLTYPE_SHORT4", /* VS 2.0 */ "D3DDECLTYPE_UBYTE4N", "D3DDECLTYPE_SHORT2N", "D3DDECLTYPE_SHORT4N", "D3DDECLTYPE_USHORT2N", "D3DDECLTYPE_USHORT4N", "D3DDECLTYPE_UDEC3", "D3DDECLTYPE_DEC3N", "D3DDECLTYPE_FLOAT16_2", "D3DDECLTYPE_FLOAT16_4", "D3DDECLTYPE_UNUSED", NULL }; DWORD IWineD3DVertexDeclarationImpl_ParseToken9(const D3DVERTEXELEMENT9* pToken) { DWORD tokenlen = 1; if (0xFF != pToken->Stream) { TRACE(" D3DDECL(%u, %u, %s, %s, %s, %u)\n", pToken->Stream, pToken->Offset, VertexDecl9_DeclTypes[pToken->Type], VertexDecl9_DeclMethods[pToken->Method], VertexDecl9_DeclUsages[pToken->Usage], pToken->UsageIndex ); } else { TRACE(" D3DDECL_END()\n" ); } return tokenlen; } HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl* This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl* object) { const D3DVERTEXELEMENT9* pToken = pDecl; DWORD fvf = 0; BOOL invalid_fvf = FALSE; DWORD tex = D3DFVF_TEX0; DWORD len = 0; DWORD stream = 0; TRACE("(%p) : pDecl(%p)\n", This, pDecl); while (0xFF != pToken->Stream) { DWORD type = pToken->Type; DWORD oldStream = stream; stream = pToken->Stream; IWineD3DVertexDeclarationImpl_ParseToken9(pToken); if (D3DDECLMETHOD_DEFAULT != pToken->Method) { WARN( "%s register: Unsupported Method of %s (only D3DDECLMETHOD_DEFAULT for now) for VertexDeclaration (type %s)\n", VertexDecl9_DeclUsages[pToken->Usage], VertexDecl9_DeclMethods[pToken->Method], VertexDecl9_DeclTypes[pToken->Type] ); } if (oldStream != stream) { if (FALSE == invalid_fvf) { fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; tex = 0; object->fvf[oldStream] = fvf; object->allFVF |= fvf; } else { object->fvf[oldStream] = 0; tex = 0; } /* reset valid/invalid fvf */ fvf = 0; invalid_fvf = FALSE; } switch (pToken->Usage) { case D3DDECLUSAGE_POSITION: if (0 < pToken->UsageIndex) { invalid_fvf = TRUE; TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_POSITION register: unsupported type %s\n", pToken->UsageIndex, VertexDecl9_DeclTypes[type]); break; } switch (type) { case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZ; break; case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZRHW; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_POSITION register: unsupported type %s\n", VertexDecl9_DeclTypes[type]); } break; case D3DDECLUSAGE_BLENDWEIGHT: switch (type) { case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_XYZB1; break; case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_XYZB2; break; case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZB3; break; case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZB4; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl9_DeclTypes[type]); } break; case D3DDECLUSAGE_BLENDINDICES: switch (type) { case D3DDECLTYPE_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDINDINCES register: unsupported type %s\n", VertexDecl9_DeclTypes[type]); } break; case D3DDECLUSAGE_NORMAL: if (0 < pToken->UsageIndex) { invalid_fvf = TRUE; TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_NORMAL register: unsupported type %s\n", pToken->UsageIndex, VertexDecl9_DeclTypes[type]); break; } switch (type) { case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_NORMAL; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_NORMAL register: unsupported type %s\n", VertexDecl9_DeclTypes[type]); } break; case D3DDECLUSAGE_PSIZE: switch (type) { case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_PSIZE; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_PSIZE register: unsupported type %s\n", VertexDecl9_DeclTypes[type]); } break; case D3DDECLUSAGE_TEXCOORD: { DWORD texNo = pToken->UsageIndex; tex = max(tex, texNo); switch (type) { case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break; case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break; case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break; case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_TEXCOORD[%lu] register: unsupported type %s\n", texNo, VertexDecl9_DeclTypes[type]); } } break; case D3DDECLUSAGE_COLOR: { DWORD colorNo = pToken->UsageIndex; switch (type) { case D3DDECLTYPE_D3DCOLOR: switch (pToken->UsageIndex) { case 0: fvf |= D3DFVF_DIFFUSE; break; case 1: fvf |= D3DFVF_SPECULAR; break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] unsupported COLOR register\n", colorNo); } break; default: /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ invalid_fvf = TRUE; TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] register: unsupported type %s\n", colorNo, VertexDecl9_DeclTypes[type]); } } break; case D3DDECLUSAGE_TANGENT: case D3DDECLUSAGE_BINORMAL: case D3DDECLUSAGE_TESSFACTOR: case D3DDECLUSAGE_POSITIONT: case D3DDECLUSAGE_FOG: case D3DDECLUSAGE_DEPTH: case D3DDECLUSAGE_SAMPLE: FIXME("%s Usage not supported yet by VertexDeclaration (type is %s)\n", VertexDecl9_DeclUsages[pToken->Usage], VertexDecl9_DeclTypes[type]); break; } ++len; ++pToken; } ++len; /* D3DDECL_END() */ /* copy fvf if valid */ if (FALSE == invalid_fvf) { fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; object->fvf[stream] = fvf; object->allFVF |= fvf; } else { object->fvf[stream] = 0; } TRACE("Completed, allFVF = %lx\n", object->allFVF); /* compute size */ object->declaration9NumElements = len; /* copy the declaration */ object->pDeclaration9 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(D3DVERTEXELEMENT9)); memcpy(object->pDeclaration9, pDecl, len * sizeof(D3DVERTEXELEMENT9)); /* returns */ TRACE("Returns allFVF = %lx\n", object->allFVF); return D3D_OK; } /* ******************************************* IWineD3DVertexDeclaration IUnknown parts follow ******************************************* */ HRESULT WINAPI IWineD3DVertexDeclarationImpl_QueryInterface(IWineD3DVertexDeclaration *iface, REFIID riid, LPVOID *ppobj) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj); if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IWineD3DVertexDeclaration)){ IUnknown_AddRef(iface); *ppobj = This; return D3D_OK; } return E_NOINTERFACE; } ULONG WINAPI IWineD3DVertexDeclarationImpl_AddRef(IWineD3DVertexDeclaration *iface) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref); return InterlockedIncrement(&This->ref); } ULONG WINAPI IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclaration *iface) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; ULONG ref; TRACE("(%p) : Releasing from %ld\n", This, This->ref); ref = InterlockedDecrement(&This->ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->pDeclaration8); HeapFree(GetProcessHeap(), 0, This->pDeclaration9); HeapFree(GetProcessHeap(), 0, This); } return ref; } /* ******************************************* IWineD3DVertexDeclaration parts follow ******************************************* */ HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDeclaration *iface, IWineD3DDevice** ppDevice) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; TRACE("(%p) : returning %p\n", This, This->wineD3DDevice); *ppDevice = (IWineD3DDevice *) This->wineD3DDevice; IWineD3DDevice_AddRef(*ppDevice); return D3D_OK; } static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration8(IWineD3DVertexDeclaration* iface, DWORD* pData, DWORD* pSizeOfData) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; if (NULL == pData) { *pSizeOfData = This->declaration8Length; return D3D_OK; } if (*pSizeOfData < This->declaration8Length) { *pSizeOfData = This->declaration8Length; return D3DERR_MOREDATA; } TRACE("(%p) : GetVertexDeclaration8 copying to %p\n", This, pData); memcpy(pData, This->pDeclaration8, This->declaration8Length); return D3D_OK; } HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration9(IWineD3DVertexDeclaration* iface, D3DVERTEXELEMENT9* pData, DWORD* pNumElements) { IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; if (NULL == pData) { *pNumElements = This->declaration9NumElements; return D3D_OK; } if (*pNumElements < This->declaration9NumElements) { *pNumElements = This->declaration9NumElements; return D3DERR_MOREDATA; } TRACE("(%p) : GetVertexDeclaration9 copying to %p\n", This, pData); memcpy(pData, This->pDeclaration9, This->declaration9NumElements); return D3D_OK; } HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration* iface, UINT iDeclVersion, VOID* pData, DWORD* pSize) { if (8 == iDeclVersion) { return IWineD3DVertexDeclarationImpl_GetDeclaration8(iface, (DWORD*) pData, pSize); } return IWineD3DVertexDeclarationImpl_GetDeclaration9(iface, (D3DVERTEXELEMENT9*) pData, pSize); } const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl = { IWineD3DVertexDeclarationImpl_QueryInterface, IWineD3DVertexDeclarationImpl_AddRef, IWineD3DVertexDeclarationImpl_Release, IWineD3DVertexDeclarationImpl_GetDevice, IWineD3DVertexDeclarationImpl_GetDeclaration, };