- convert D3D8 VertexDecl to D3D9 format (D3DVERTEXELEMENT9 vector)
[wine/multimedia.git] / dlls / wined3d / vertexdeclaration.c
blob1a3259e96897b30b4c670c7133bed240a0cfd8e3
1 /*
2 * vertex declaration implementation
4 * Copyright 2002-2005 Raphael Junqueira
5 * Copyright 2004 Jason Edmeades
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d_decl);
28 /**
29 * DirectX9 SDK download
30 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
32 * Exploring D3DX
33 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
35 * Using Vertex Shaders
36 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
38 * Dx9 New
39 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
41 * Dx9 Shaders
42 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
43 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
44 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
45 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
47 * Dx9 D3DX
48 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
50 * FVF
51 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
53 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
54 * http://developer.nvidia.com/view.asp?IO=vstovp
56 * NVIDIA: Memory Management with VAR
57 * http://developer.nvidia.com/view.asp?IO=var_memory_management
60 /** Vertex Shader Declaration 8 data types tokens */
61 #define MAX_VSHADER_DECL_TYPES 8
63 static CONST char* VertexDecl8_DataTypes[] = {
64 "D3DVSDT_FLOAT1",
65 "D3DVSDT_FLOAT2",
66 "D3DVSDT_FLOAT3",
67 "D3DVSDT_FLOAT4",
68 "D3DVSDT_D3DCOLOR",
69 "D3DVSDT_UBYTE4",
70 "D3DVSDT_SHORT2",
71 "D3DVSDT_SHORT4",
72 NULL
75 static CONST char* VertexDecl8_Registers[] = {
76 "D3DVSDE_POSITION",
77 "D3DVSDE_BLENDWEIGHT",
78 "D3DVSDE_BLENDINDICES",
79 "D3DVSDE_NORMAL",
80 "D3DVSDE_PSIZE",
81 "D3DVSDE_DIFFUSE",
82 "D3DVSDE_SPECULAR",
83 "D3DVSDE_TEXCOORD0",
84 "D3DVSDE_TEXCOORD1",
85 "D3DVSDE_TEXCOORD2",
86 "D3DVSDE_TEXCOORD3",
87 "D3DVSDE_TEXCOORD4",
88 "D3DVSDE_TEXCOORD5",
89 "D3DVSDE_TEXCOORD6",
90 "D3DVSDE_TEXCOORD7",
91 "D3DVSDE_POSITION2",
92 "D3DVSDE_NORMAL2",
93 NULL
96 typedef enum _D3DVSD_TOKENTYPE {
97 D3DVSD_TOKEN_NOP = 0,
98 D3DVSD_TOKEN_STREAM = 1,
99 D3DVSD_TOKEN_STREAMDATA = 2,
100 D3DVSD_TOKEN_TESSELLATOR = 3,
101 D3DVSD_TOKEN_CONSTMEM = 4,
102 D3DVSD_TOKEN_EXT = 5,
103 /* RESERVED = 6 */
104 D3DVSD_TOKEN_END = 7,
105 D3DVSD_FORCE_DWORD = 0x7FFFFFFF
106 } D3DVSD_TOKENTYPE;
108 typedef enum _D3DVSDE_REGISTER {
109 D3DVSDE_POSITION = 0,
110 D3DVSDE_BLENDWEIGHT = 1,
111 D3DVSDE_BLENDINDICES = 2,
112 D3DVSDE_NORMAL = 3,
113 D3DVSDE_PSIZE = 4,
114 D3DVSDE_DIFFUSE = 5,
115 D3DVSDE_SPECULAR = 6,
116 D3DVSDE_TEXCOORD0 = 7,
117 D3DVSDE_TEXCOORD1 = 8,
118 D3DVSDE_TEXCOORD2 = 9,
119 D3DVSDE_TEXCOORD3 = 10,
120 D3DVSDE_TEXCOORD4 = 11,
121 D3DVSDE_TEXCOORD5 = 12,
122 D3DVSDE_TEXCOORD6 = 13,
123 D3DVSDE_TEXCOORD7 = 14,
124 D3DVSDE_POSITION2 = 15,
125 D3DVSDE_NORMAL2 = 16
126 } D3DVSDE_REGISTER;
128 typedef enum _D3DVSDT_TYPE {
129 D3DVSDT_FLOAT1 = 0x00,
130 D3DVSDT_FLOAT2 = 0x01,
131 D3DVSDT_FLOAT3 = 0x02,
132 D3DVSDT_FLOAT4 = 0x03,
133 D3DVSDT_D3DCOLOR = 0x04,
134 D3DVSDT_UBYTE4 = 0x05,
135 D3DVSDT_SHORT2 = 0x06,
136 D3DVSDT_SHORT4 = 0x07
137 } D3DVSDT_TYPE;
140 #define D3DVSD_CONSTADDRESSSHIFT 0
141 #define D3DVSD_EXTINFOSHIFT 0
142 #define D3DVSD_STREAMNUMBERSHIFT 0
143 #define D3DVSD_VERTEXREGSHIFT 0
144 #define D3DVSD_CONSTRSSHIFT 16
145 #define D3DVSD_DATATYPESHIFT 16
146 #define D3DVSD_SKIPCOUNTSHIFT 16
147 #define D3DVSD_VERTEXREGINSHIFT 20
148 #define D3DVSD_EXTCOUNTSHIFT 24
149 #define D3DVSD_CONSTCOUNTSHIFT 25
150 #define D3DVSD_DATALOADTYPESHIFT 28
151 #define D3DVSD_STREAMTESSSHIFT 28
152 #define D3DVSD_TOKENTYPESHIFT 29
154 #define D3DVSD_CONSTADDRESSMASK (0x7F << D3DVSD_CONSTADDRESSSHIFT)
155 #define D3DVSD_EXTINFOMASK (0xFFFFFF << D3DVSD_EXTINFOSHIFT)
156 #define D3DVSD_STREAMNUMBERMASK (0xF << D3DVSD_STREAMNUMBERSHIFT)
157 #define D3DVSD_VERTEXREGMASK (0x1F << D3DVSD_VERTEXREGSHIFT)
158 #define D3DVSD_CONSTRSMASK (0x1FFF << D3DVSD_CONSTRSSHIFT)
159 #define D3DVSD_DATATYPEMASK (0xF << D3DVSD_DATATYPESHIFT)
160 #define D3DVSD_SKIPCOUNTMASK (0xF << D3DVSD_SKIPCOUNTSHIFT)
161 #define D3DVSD_EXTCOUNTMASK (0x1F << D3DVSD_EXTCOUNTSHIFT)
162 #define D3DVSD_VERTEXREGINMASK (0xF << D3DVSD_VERTEXREGINSHIFT)
163 #define D3DVSD_CONSTCOUNTMASK (0xF << D3DVSD_CONSTCOUNTSHIFT)
164 #define D3DVSD_DATALOADTYPEMASK (0x1 << D3DVSD_DATALOADTYPESHIFT)
165 #define D3DVSD_STREAMTESSMASK (0x1 << D3DVSD_STREAMTESSSHIFT)
166 #define D3DVSD_TOKENTYPEMASK (0x7 << D3DVSD_TOKENTYPESHIFT)
168 #define D3DVSD_END() 0xFFFFFFFF
169 #define D3DVSD_NOP() 0x00000000
171 DWORD IWineD3DVertexDeclarationImpl_ParseToken8(const DWORD* pToken) {
172 const DWORD token = *pToken;
173 DWORD tokenlen = 1;
175 switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */
176 case D3DVSD_TOKEN_NOP:
177 TRACE(" 0x%08lx NOP()\n", token);
178 break;
179 case D3DVSD_TOKEN_STREAM:
180 if (token & D3DVSD_STREAMTESSMASK) {
181 TRACE(" 0x%08lx STREAM_TESS()\n", token);
182 } else {
183 TRACE(" 0x%08lx STREAM(%lu)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT));
185 break;
186 case D3DVSD_TOKEN_STREAMDATA:
187 if (token & 0x10000000) {
188 TRACE(" 0x%08lx SKIP(%lu)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT));
189 } else {
190 DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
191 DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
192 TRACE(" 0x%08lx REG(%s, %s)\n", token, VertexDecl8_Registers[reg], VertexDecl8_DataTypes[type]);
194 break;
195 case D3DVSD_TOKEN_TESSELLATOR:
196 if (token & 0x10000000) {
197 DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
198 DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
199 TRACE(" 0x%08lx TESSUV(%s) as %s\n", token, VertexDecl8_Registers[reg], VertexDecl8_DataTypes[type]);
200 } else {
201 DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
202 DWORD regout = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
203 DWORD regin = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT);
204 TRACE(" 0x%08lx TESSNORMAL(%s, %s) as %s\n", token, VertexDecl8_Registers[regin], VertexDecl8_Registers[regout], VertexDecl8_DataTypes[type]);
206 break;
207 case D3DVSD_TOKEN_CONSTMEM:
209 DWORD i;
210 DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
211 DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
212 TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count);
213 ++pToken;
214 for (i = 0; i < count; ++i) {
215 #if 0
216 TRACE(" c[%lu] = (0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n",
217 constaddress,
218 *pToken,
219 *(pToken + 1),
220 *(pToken + 2),
221 *(pToken + 3));
222 #endif
223 TRACE(" c[%lu] = (%8f, %8f, %8f, %8f)\n",
224 constaddress,
225 *(const float*) pToken,
226 *(const float*) (pToken + 1),
227 *(const float*) (pToken + 2),
228 *(const float*) (pToken + 3));
229 pToken += 4;
230 ++constaddress;
232 tokenlen = (4 * count) + 1;
234 break;
235 case D3DVSD_TOKEN_EXT:
237 DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
238 DWORD extinfo = ((token & D3DVSD_EXTINFOMASK) >> D3DVSD_EXTINFOSHIFT);
239 TRACE(" 0x%08lx EXT(%lu, %lu)\n", token, count, extinfo);
240 /* todo ... print extension */
241 tokenlen = count + 1;
243 break;
244 case D3DVSD_TOKEN_END:
245 TRACE(" 0x%08lx END()\n", token);
246 break;
247 default:
248 TRACE(" 0x%08lx UNKNOWN\n", token);
249 /* argg error */
251 return tokenlen;
254 DWORD IWineD3DVertexDeclarationImpl_ParseToken9(const D3DVERTEXELEMENT9* pToken);
256 HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl* This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl* object) {
257 const DWORD* pToken = pDecl;
258 DWORD fvf = 0;
259 BOOL invalid_fvf = FALSE;
260 DWORD tex = D3DFVF_TEX0;
261 DWORD len = 0;
262 DWORD stream = 0;
263 DWORD token;
264 DWORD tokenlen;
265 DWORD tokentype;
266 DWORD nTokens = 0;
267 D3DVERTEXELEMENT9 convTo9[128];
269 TRACE("(%p) : pDecl(%p)\n", This, pDecl);
271 while (D3DVSD_END() != *pToken) {
272 token = *pToken;
273 tokenlen = IWineD3DVertexDeclarationImpl_ParseToken8(pToken);
274 tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
276 /** FVF generation block */
277 if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) {
278 /**
279 * how really works streams,
280 * in DolphinVS dx8 dsk sample they seems to decal reg numbers !!!
282 DWORD oldStream = stream;
283 stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
285 /* copy fvf if valid */
286 if (FALSE == invalid_fvf) {
287 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
288 tex = 0;
289 object->fvf[oldStream] = fvf;
290 object->allFVF |= fvf;
291 } else {
292 object->fvf[oldStream] = 0;
293 tex = 0;
296 /* reset valid/invalid fvf */
297 fvf = 0;
298 invalid_fvf = FALSE;
300 } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
301 DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
302 DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
304 convTo9[nTokens].Stream = stream;
305 convTo9[nTokens].Method = D3DDECLMETHOD_DEFAULT;
306 convTo9[nTokens].UsageIndex = 0;
307 convTo9[nTokens].Type = D3DDECLTYPE_UNUSED;
309 switch (reg) {
310 case D3DVSDE_POSITION:
311 convTo9[nTokens].Usage = D3DDECLUSAGE_POSITION;
312 convTo9[nTokens].Type = type;
313 switch (type) {
314 case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZ; break;
315 case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZRHW; break;
316 default:
317 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
318 invalid_fvf = TRUE;
319 if (type >= MAX_VSHADER_DECL_TYPES) {
320 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported and unrecognized type %08lx\n", type);
321 } else {
322 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
325 break;
327 case D3DVSDE_BLENDWEIGHT:
328 convTo9[nTokens].Usage = D3DDECLUSAGE_BLENDWEIGHT;
329 convTo9[nTokens].Type = type;
330 switch (type) {
331 case D3DVSDT_FLOAT1: fvf |= D3DFVF_XYZB1; break;
332 case D3DVSDT_FLOAT2: fvf |= D3DFVF_XYZB2; break;
333 case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZB3; break;
334 case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZB4; break;
335 default:
336 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
337 invalid_fvf = TRUE;
338 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
340 break;
342 case D3DVSDE_BLENDINDICES: /* seem to be B5 as said in MSDN Dx9SDK ?? */
343 convTo9[nTokens].Usage = D3DDECLUSAGE_BLENDINDICES;
344 convTo9[nTokens].Type = type;
345 switch (type) {
346 case D3DVSDT_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
347 default:
348 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
349 invalid_fvf = TRUE;
350 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDINDINCES register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
352 break;
354 case D3DVSDE_NORMAL: /* TODO: only FLOAT3 supported ... another choice possible ? */
355 convTo9[nTokens].Usage = D3DDECLUSAGE_NORMAL;
356 convTo9[nTokens].Type = type;
357 switch (type) {
358 case D3DVSDT_FLOAT3: fvf |= D3DFVF_NORMAL; break;
359 default:
360 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
361 invalid_fvf = TRUE;
362 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_NORMAL register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
364 break;
366 case D3DVSDE_PSIZE: /* TODO: only FLOAT1 supported ... another choice possible ? */
367 convTo9[nTokens].Usage = D3DDECLUSAGE_PSIZE;
368 convTo9[nTokens].Type = type;
369 switch (type) {
370 case D3DVSDT_FLOAT1: fvf |= D3DFVF_PSIZE; break;
371 default:
372 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
373 invalid_fvf = TRUE;
374 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_PSIZE register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
376 break;
378 case D3DVSDE_DIFFUSE: /* TODO: only D3DCOLOR supported */
379 convTo9[nTokens].Usage = D3DDECLUSAGE_COLOR;
380 convTo9[nTokens].UsageIndex = 0;
381 convTo9[nTokens].Type = type;
382 switch (type) {
383 case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_DIFFUSE; break;
384 default:
385 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
386 invalid_fvf = TRUE;
387 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_DIFFUSE register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
389 break;
391 case D3DVSDE_SPECULAR: /* TODO: only D3DCOLOR supported */
392 convTo9[nTokens].Usage = D3DDECLUSAGE_COLOR;
393 convTo9[nTokens].UsageIndex = 1;
394 convTo9[nTokens].Type = type;
395 switch (type) {
396 case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_SPECULAR; break;
397 default:
398 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
399 invalid_fvf = TRUE;
400 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_SPECULAR register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
402 break;
404 case D3DVSDE_TEXCOORD0:
405 case D3DVSDE_TEXCOORD1:
406 case D3DVSDE_TEXCOORD2:
407 case D3DVSDE_TEXCOORD3:
408 case D3DVSDE_TEXCOORD4:
409 case D3DVSDE_TEXCOORD5:
410 case D3DVSDE_TEXCOORD6:
411 case D3DVSDE_TEXCOORD7:
412 /* Fixme? - assume all tex coords in same stream */
414 int texNo = 1 + (reg - D3DVSDE_TEXCOORD0);
415 convTo9[nTokens].Usage = D3DDECLUSAGE_TEXCOORD;
416 convTo9[nTokens].UsageIndex = texNo;
417 convTo9[nTokens].Type = type;
418 tex = max(tex, texNo);
419 switch (type) {
420 case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
421 case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
422 case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
423 case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
424 default:
425 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
426 invalid_fvf = TRUE;
427 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
430 break;
432 case D3DVSDE_POSITION2: /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
433 case D3DVSDE_NORMAL2: /* FIXME i don't know what to do here ;( */
434 FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
435 break;
437 TRACE("VertexShader declaration define %lx as current FVF\n", fvf);
439 ++nTokens;
440 len += tokenlen;
441 pToken += tokenlen;
443 /* here D3DVSD_END() */
444 len += IWineD3DVertexDeclarationImpl_ParseToken8(pToken);
446 convTo9[nTokens].Stream = 0xFF;
447 convTo9[nTokens].Type = D3DDECLTYPE_UNUSED;
449 /* copy fvf if valid */
450 if (FALSE == invalid_fvf) {
451 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
452 object->fvf[stream] = fvf;
453 object->allFVF |= fvf;
454 } else {
455 object->fvf[stream] = 0;
457 TRACE("Completed, allFVF = %lx\n", object->allFVF);
459 /* compute size */
460 object->declaration8Length = len * sizeof(DWORD);
461 /* copy the declaration */
462 object->pDeclaration8 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declaration8Length);
463 memcpy(object->pDeclaration8, pDecl, object->declaration8Length);
465 /* compute convTo9 size */
466 object->declaration9NumElements = nTokens;
467 /* copy the convTo9 declaration */
468 object->pDeclaration9 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nTokens * sizeof(D3DVERTEXELEMENT9));
469 memcpy(object->pDeclaration9, convTo9, nTokens * sizeof(D3DVERTEXELEMENT9));
472 D3DVERTEXELEMENT9* pIt = object->pDeclaration9;
473 TRACE("dumping of D3D9 Convertion:\n");
474 while (0xFF != pIt->Stream) {
475 IWineD3DVertexDeclarationImpl_ParseToken9(pIt);
476 ++pIt;
478 IWineD3DVertexDeclarationImpl_ParseToken9(pIt);
481 /* returns */
482 return D3D_OK;
485 static CONST char* VertexDecl9_DeclUsages[] = {
486 "D3DDECLUSAGE_POSITION",
487 "D3DDECLUSAGE_BLENDWEIGHT",
488 "D3DDECLUSAGE_BLENDINDICES",
489 "D3DDECLUSAGE_NORMAL",
490 "D3DDECLUSAGE_PSIZE",
491 "D3DDECLUSAGE_TEXCOORD",
492 "D3DDECLUSAGE_TANGENT",
493 "D3DDECLUSAGE_BINORMAL",
494 "D3DDECLUSAGE_TESSFACTOR",
495 "D3DDECLUSAGE_POSITIONT",
496 "D3DDECLUSAGE_COLOR",
497 "D3DDECLUSAGE_FOG",
498 "D3DDECLUSAGE_DEPTH",
499 "D3DDECLUSAGE_SAMPLE",
500 NULL
503 static CONST char* VertexDecl9_DeclMethods[] = {
504 "D3DDECLMETHOD_DEFAULT",
505 "D3DDECLMETHOD_PARTIALU",
506 "D3DDECLMETHOD_PARTIALV",
507 "D3DDECLMETHOD_CROSSUV",
508 "D3DDECLMETHOD_UV",
509 "D3DDECLMETHOD_LOOKUP",
510 "D3DDECLMETHOD_LOOKUPPRESAMPLED",
511 NULL
514 static CONST char* VertexDecl9_DeclTypes[] = {
515 "D3DDECLTYPE_FLOAT1",
516 "D3DDECLTYPE_FLOAT2",
517 "D3DDECLTYPE_FLOAT3",
518 "D3DDECLTYPE_FLOAT4",
519 "D3DDECLTYPE_D3DCOLOR",
520 "D3DDECLTYPE_UBYTE4",
521 "D3DDECLTYPE_SHORT2",
522 "D3DDECLTYPE_SHORT4",
523 /* VS 2.0 */
524 "D3DDECLTYPE_UBYTE4N",
525 "D3DDECLTYPE_SHORT2N",
526 "D3DDECLTYPE_SHORT4N",
527 "D3DDECLTYPE_USHORT2N",
528 "D3DDECLTYPE_USHORT4N",
529 "D3DDECLTYPE_UDEC3",
530 "D3DDECLTYPE_DEC3N",
531 "D3DDECLTYPE_FLOAT16_2",
532 "D3DDECLTYPE_FLOAT16_4",
533 "D3DDECLTYPE_UNUSED",
534 NULL
537 DWORD IWineD3DVertexDeclarationImpl_ParseToken9(const D3DVERTEXELEMENT9* pToken) {
538 DWORD tokenlen = 1;
540 if (0xFF != pToken->Stream) {
541 TRACE(" D3DDECL(%u, %u, %s, %s, %s, %u)\n",
542 pToken->Stream,
543 pToken->Offset,
544 VertexDecl9_DeclTypes[pToken->Type],
545 VertexDecl9_DeclMethods[pToken->Method],
546 VertexDecl9_DeclUsages[pToken->Usage],
547 pToken->UsageIndex
549 } else {
550 TRACE(" D3DDECL_END()\n" );
552 return tokenlen;
555 HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl* This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl* object) {
556 const D3DVERTEXELEMENT9* pToken = pDecl;
557 DWORD fvf = 0;
558 BOOL invalid_fvf = FALSE;
559 DWORD tex = D3DFVF_TEX0;
560 DWORD len = 0;
561 DWORD stream = 0;
563 TRACE("(%p) : pDecl(%p)\n", This, pDecl);
565 while (0xFF != pToken->Stream) {
566 DWORD type = pToken->Type;
567 DWORD oldStream = stream;
568 stream = pToken->Stream;
570 IWineD3DVertexDeclarationImpl_ParseToken9(pToken);
572 if (D3DDECLMETHOD_DEFAULT != pToken->Method) {
573 WARN(
574 "%s register: Unsupported Method of %s (only D3DDECLMETHOD_DEFAULT for now) for VertexDeclaration (type %s)\n",
575 VertexDecl9_DeclUsages[pToken->Usage],
576 VertexDecl9_DeclMethods[pToken->Method],
577 VertexDecl9_DeclTypes[pToken->Type]
581 if (oldStream != stream) {
583 if (FALSE == invalid_fvf) {
584 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
585 tex = 0;
586 object->fvf[oldStream] = fvf;
587 object->allFVF |= fvf;
588 } else {
589 object->fvf[oldStream] = 0;
590 tex = 0;
593 /* reset valid/invalid fvf */
594 fvf = 0;
595 invalid_fvf = FALSE;
598 switch (pToken->Usage) {
599 case D3DDECLUSAGE_POSITION:
600 if (0 < pToken->UsageIndex) {
601 invalid_fvf = TRUE;
602 TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_POSITION register: unsupported type %s\n",
603 pToken->UsageIndex, VertexDecl9_DeclTypes[type]);
604 break;
606 switch (type) {
607 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZ; break;
608 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZRHW; break;
609 default:
610 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
611 invalid_fvf = TRUE;
612 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_POSITION register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
614 break;
616 case D3DDECLUSAGE_BLENDWEIGHT:
617 switch (type) {
618 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_XYZB1; break;
619 case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_XYZB2; break;
620 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZB3; break;
621 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZB4; break;
622 default:
623 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
624 invalid_fvf = TRUE;
625 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
627 break;
629 case D3DDECLUSAGE_BLENDINDICES:
630 switch (type) {
631 case D3DDECLTYPE_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
632 default:
633 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
634 invalid_fvf = TRUE;
635 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDINDINCES register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
637 break;
639 case D3DDECLUSAGE_NORMAL:
640 if (0 < pToken->UsageIndex) {
641 invalid_fvf = TRUE;
642 TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_NORMAL register: unsupported type %s\n",
643 pToken->UsageIndex, VertexDecl9_DeclTypes[type]);
644 break;
646 switch (type) {
647 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_NORMAL; break;
648 default:
649 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
650 invalid_fvf = TRUE;
651 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_NORMAL register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
653 break;
655 case D3DDECLUSAGE_PSIZE:
656 switch (type) {
657 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_PSIZE; break;
658 default:
659 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
660 invalid_fvf = TRUE;
661 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_PSIZE register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
663 break;
665 case D3DDECLUSAGE_TEXCOORD:
667 DWORD texNo = pToken->UsageIndex;
668 tex = max(tex, texNo);
669 switch (type) {
670 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
671 case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
672 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
673 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
674 default:
675 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
676 invalid_fvf = TRUE;
677 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_TEXCOORD[%lu] register: unsupported type %s\n", texNo, VertexDecl9_DeclTypes[type]);
680 break;
682 case D3DDECLUSAGE_COLOR:
684 DWORD colorNo = pToken->UsageIndex;
685 switch (type) {
686 case D3DDECLTYPE_D3DCOLOR:
687 switch (pToken->UsageIndex) {
688 case 0: fvf |= D3DFVF_DIFFUSE; break;
689 case 1: fvf |= D3DFVF_SPECULAR; break;
690 default:
691 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
692 invalid_fvf = TRUE;
693 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] unsupported COLOR register\n", colorNo);
695 break;
696 default:
697 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
698 invalid_fvf = TRUE;
699 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] register: unsupported type %s\n", colorNo, VertexDecl9_DeclTypes[type]);
702 break;
704 case D3DDECLUSAGE_TANGENT:
705 case D3DDECLUSAGE_BINORMAL:
706 case D3DDECLUSAGE_TESSFACTOR:
707 case D3DDECLUSAGE_POSITIONT:
708 case D3DDECLUSAGE_FOG:
709 case D3DDECLUSAGE_DEPTH:
710 case D3DDECLUSAGE_SAMPLE:
711 FIXME("%s Usage not supported yet by VertexDeclaration (type is %s)\n", VertexDecl9_DeclUsages[pToken->Usage], VertexDecl9_DeclTypes[type]);
712 break;
715 ++len;
716 ++pToken;
718 ++len; /* D3DDECL_END() */
720 /* copy fvf if valid */
721 if (FALSE == invalid_fvf) {
722 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
723 object->fvf[stream] = fvf;
724 object->allFVF |= fvf;
725 } else {
726 object->fvf[stream] = 0;
730 TRACE("Completed, allFVF = %lx\n", object->allFVF);
732 /* compute size */
733 object->declaration9NumElements = len;
734 /* copy the declaration */
735 object->pDeclaration9 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(D3DVERTEXELEMENT9));
736 memcpy(object->pDeclaration9, pDecl, len * sizeof(D3DVERTEXELEMENT9));
737 /* returns */
739 TRACE("Returns allFVF = %lx\n", object->allFVF);
741 return D3D_OK;
744 /* *******************************************
745 IWineD3DVertexDeclaration IUnknown parts follow
746 ******************************************* */
747 HRESULT WINAPI IWineD3DVertexDeclarationImpl_QueryInterface(IWineD3DVertexDeclaration *iface, REFIID riid, LPVOID *ppobj)
749 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
750 WARN("(%p)->(%s,%p) should not be called\n",This,debugstr_guid(riid),ppobj);
751 return E_NOINTERFACE;
754 ULONG WINAPI IWineD3DVertexDeclarationImpl_AddRef(IWineD3DVertexDeclaration *iface) {
755 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
756 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
757 return InterlockedIncrement(&This->ref);
760 ULONG WINAPI IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclaration *iface) {
761 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
762 ULONG ref;
763 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
764 ref = InterlockedDecrement(&This->ref);
765 if (ref == 0) {
766 HeapFree(GetProcessHeap(), 0, This->pDeclaration8);
767 HeapFree(GetProcessHeap(), 0, This->pDeclaration9);
768 HeapFree(GetProcessHeap(), 0, This);
770 return ref;
773 /* *******************************************
774 IWineD3DVertexDeclaration parts follow
775 ******************************************* */
777 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDeclaration *iface, IWineD3DDevice** ppDevice) {
778 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
779 TRACE("(%p) : returning %p\n", This, This->wineD3DDevice);
781 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
782 IWineD3DDevice_AddRef(*ppDevice);
784 return D3D_OK;
787 static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration8(IWineD3DVertexDeclaration* iface, DWORD* pData, DWORD* pSizeOfData) {
788 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
789 if (NULL == pData) {
790 *pSizeOfData = This->declaration8Length;
791 return D3D_OK;
793 if (*pSizeOfData < This->declaration8Length) {
794 *pSizeOfData = This->declaration8Length;
795 return D3DERR_MOREDATA;
797 TRACE("(%p) : GetVertexDeclaration8 copying to %p\n", This, pData);
798 memcpy(pData, This->pDeclaration8, This->declaration8Length);
799 return D3D_OK;
802 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration9(IWineD3DVertexDeclaration* iface, D3DVERTEXELEMENT9* pData, DWORD* pNumElements) {
803 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
804 if (NULL == pData) {
805 *pNumElements = This->declaration9NumElements;
806 return D3D_OK;
808 if (*pNumElements < This->declaration9NumElements) {
809 *pNumElements = This->declaration9NumElements;
810 return D3DERR_MOREDATA;
812 TRACE("(%p) : GetVertexDeclaration9 copying to %p\n", This, pData);
813 memcpy(pData, This->pDeclaration9, This->declaration9NumElements);
814 return D3D_OK;
817 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration* iface, UINT iDeclVersion, VOID* pData, DWORD* pSize) {
818 if (8 == iDeclVersion) {
819 return IWineD3DVertexDeclarationImpl_GetDeclaration8(iface, (DWORD*) pData, pSize);
821 return IWineD3DVertexDeclarationImpl_GetDeclaration9(iface, (D3DVERTEXELEMENT9*) pData, pSize);
824 IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl =
826 IWineD3DVertexDeclarationImpl_QueryInterface,
827 IWineD3DVertexDeclarationImpl_AddRef,
828 IWineD3DVertexDeclarationImpl_Release,
829 IWineD3DVertexDeclarationImpl_GetDevice,
830 IWineD3DVertexDeclarationImpl_GetDeclaration,