| /* | |
| * 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 Convertion:\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); | |
| } | |
| IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl = | |
| { | |
| IWineD3DVertexDeclarationImpl_QueryInterface, | |
| IWineD3DVertexDeclarationImpl_AddRef, | |
| IWineD3DVertexDeclarationImpl_Release, | |
| IWineD3DVertexDeclarationImpl_GetDevice, | |
| IWineD3DVertexDeclarationImpl_GetDeclaration, | |
| }; |