- fix typo in wined3d_interface.h
[wine/wine-gecko.git] / dlls / wined3d / vertexdeclaration.c
blob7cb989efb478209e96e9b9b06426573f59928357
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 HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl* This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl* object) {
255 const DWORD* pToken = pDecl;
256 DWORD fvf = 0;
257 BOOL invalid_fvf = FALSE;
258 DWORD tex = D3DFVF_TEX0;
259 DWORD len = 0;
260 DWORD stream = 0;
261 DWORD token;
262 DWORD tokenlen;
263 DWORD tokentype;
265 TRACE("(%p) : pDecl(%p)\n", This, pDecl);
267 while (D3DVSD_END() != *pToken) {
268 token = *pToken;
269 tokenlen = IWineD3DVertexDeclarationImpl_ParseToken8(pToken);
270 tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
272 /** FVF generation block */
273 if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) {
274 /**
275 * how really works streams,
276 * in DolphinVS dx8 dsk sample they seems to decal reg numbers !!!
278 DWORD oldStream = stream;
279 stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
281 /* copy fvf if valid */
282 if (FALSE == invalid_fvf) {
283 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
284 tex = 0;
285 object->fvf[oldStream] = fvf;
286 object->allFVF |= fvf;
287 } else {
288 object->fvf[oldStream] = 0;
289 tex = 0;
292 /* reset valid/invalid fvf */
293 fvf = 0;
294 invalid_fvf = FALSE;
296 } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
297 DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT);
298 DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
300 switch (reg) {
301 case D3DVSDE_POSITION:
302 switch (type) {
303 case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZ; break;
304 case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZRHW; break;
305 default:
306 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
307 invalid_fvf = TRUE;
308 if (type >= MAX_VSHADER_DECL_TYPES) {
309 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported and unrecognized type %08lx\n", type);
310 } else {
311 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
314 break;
316 case D3DVSDE_BLENDWEIGHT:
317 switch (type) {
318 case D3DVSDT_FLOAT1: fvf |= D3DFVF_XYZB1; break;
319 case D3DVSDT_FLOAT2: fvf |= D3DFVF_XYZB2; break;
320 case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZB3; break;
321 case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZB4; break;
322 default:
323 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
324 invalid_fvf = TRUE;
325 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
327 break;
329 case D3DVSDE_BLENDINDICES: /* seem to be B5 as said in MSDN Dx9SDK ?? */
330 switch (type) {
331 case D3DVSDT_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
332 default:
333 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
334 invalid_fvf = TRUE;
335 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDINDINCES register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
337 break;
339 case D3DVSDE_NORMAL: /* TODO: only FLOAT3 supported ... another choice possible ? */
340 switch (type) {
341 case D3DVSDT_FLOAT3: fvf |= D3DFVF_NORMAL; break;
342 default:
343 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
344 invalid_fvf = TRUE;
345 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_NORMAL register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
347 break;
349 case D3DVSDE_PSIZE: /* TODO: only FLOAT1 supported ... another choice possible ? */
350 switch (type) {
351 case D3DVSDT_FLOAT1: fvf |= D3DFVF_PSIZE; break;
352 default:
353 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
354 invalid_fvf = TRUE;
355 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_PSIZE register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
357 break;
359 case D3DVSDE_DIFFUSE: /* TODO: only D3DCOLOR supported */
360 switch (type) {
361 case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_DIFFUSE; break;
362 default:
363 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
364 invalid_fvf = TRUE;
365 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_DIFFUSE register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
367 break;
369 case D3DVSDE_SPECULAR: /* TODO: only D3DCOLOR supported */
370 switch (type) {
371 case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_SPECULAR; break;
372 default:
373 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
374 invalid_fvf = TRUE;
375 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_SPECULAR register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
377 break;
379 case D3DVSDE_TEXCOORD0:
380 case D3DVSDE_TEXCOORD1:
381 case D3DVSDE_TEXCOORD2:
382 case D3DVSDE_TEXCOORD3:
383 case D3DVSDE_TEXCOORD4:
384 case D3DVSDE_TEXCOORD5:
385 case D3DVSDE_TEXCOORD6:
386 case D3DVSDE_TEXCOORD7:
387 /* Fixme? - assume all tex coords in same stream */
389 int texNo = 1 + (reg - D3DVSDE_TEXCOORD0);
390 tex = max(tex, texNo);
391 switch (type) {
392 case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
393 case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
394 case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
395 case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
396 default:
397 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
398 invalid_fvf = TRUE;
399 TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexDecl8_DataTypes[type]);
402 break;
404 case D3DVSDE_POSITION2: /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
405 case D3DVSDE_NORMAL2: /* FIXME i don't know what to do here ;( */
406 FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
407 break;
409 TRACE("VertexShader declaration define %lx as current FVF\n", fvf);
411 len += tokenlen;
412 pToken += tokenlen;
414 /* here D3DVSD_END() */
415 len += IWineD3DVertexDeclarationImpl_ParseToken8(pToken);
417 /* copy fvf if valid */
418 if (FALSE == invalid_fvf) {
419 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
420 object->fvf[stream] = fvf;
421 object->allFVF |= fvf;
422 } else {
423 object->fvf[stream] = 0;
425 TRACE("Completed, allFVF = %lx\n", object->allFVF);
427 /* compute size */
428 object->declaration8Length = len * sizeof(DWORD);
429 /* copy the declaration */
430 object->pDeclaration8 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declaration8Length);
431 memcpy(object->pDeclaration8, pDecl, object->declaration8Length);
432 /* returns */
433 return D3D_OK;
436 static CONST char* VertexDecl9_DeclUsages[] = {
437 "D3DDECLUSAGE_POSITION",
438 "D3DDECLUSAGE_BLENDWEIGHT",
439 "D3DDECLUSAGE_BLENDINDICES",
440 "D3DDECLUSAGE_NORMAL",
441 "D3DDECLUSAGE_PSIZE",
442 "D3DDECLUSAGE_TEXCOORD",
443 "D3DDECLUSAGE_TANGENT",
444 "D3DDECLUSAGE_BINORMAL",
445 "D3DDECLUSAGE_TESSFACTOR",
446 "D3DDECLUSAGE_POSITIONT",
447 "D3DDECLUSAGE_COLOR",
448 "D3DDECLUSAGE_FOG",
449 "D3DDECLUSAGE_DEPTH",
450 "D3DDECLUSAGE_SAMPLE",
451 NULL
454 static CONST char* VertexDecl9_DeclMethods[] = {
455 "D3DDECLMETHOD_DEFAULT",
456 "D3DDECLMETHOD_PARTIALU",
457 "D3DDECLMETHOD_PARTIALV",
458 "D3DDECLMETHOD_CROSSUV",
459 "D3DDECLMETHOD_UV",
460 "D3DDECLMETHOD_LOOKUP",
461 "D3DDECLMETHOD_LOOKUPPRESAMPLED",
462 NULL
465 static CONST char* VertexDecl9_DeclTypes[] = {
466 "D3DDECLTYPE_FLOAT1",
467 "D3DDECLTYPE_FLOAT2",
468 "D3DDECLTYPE_FLOAT3",
469 "D3DDECLTYPE_FLOAT4",
470 "D3DDECLTYPE_D3DCOLOR",
471 "D3DDECLTYPE_UBYTE4",
472 "D3DDECLTYPE_SHORT2",
473 "D3DDECLTYPE_SHORT4",
474 /* VS 2.0 */
475 "D3DDECLTYPE_UBYTE4N",
476 "D3DDECLTYPE_SHORT2N",
477 "D3DDECLTYPE_SHORT4N",
478 "D3DDECLTYPE_USHORT2N",
479 "D3DDECLTYPE_USHORT4N",
480 "D3DDECLTYPE_UDEC3",
481 "D3DDECLTYPE_DEC3N",
482 "D3DDECLTYPE_FLOAT16_2",
483 "D3DDECLTYPE_FLOAT16_4",
484 "D3DDECLTYPE_UNUSED",
485 NULL
488 DWORD IWineD3DVertexDeclarationImpl_ParseToken9(const D3DVERTEXELEMENT9* pToken) {
489 DWORD tokenlen = 1;
491 if (0xFF != pToken->Stream) {
492 TRACE(" D3DDECL(%u, %u, %s, %s, %s, %u)\n",
493 pToken->Stream,
494 pToken->Offset,
495 VertexDecl9_DeclTypes[pToken->Type],
496 VertexDecl9_DeclMethods[pToken->Method],
497 VertexDecl9_DeclUsages[pToken->Usage],
498 pToken->UsageIndex
500 } else {
501 TRACE(" D3DDECL_END()\n" );
503 return tokenlen;
506 HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl* This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl* object) {
507 const D3DVERTEXELEMENT9* pToken = pDecl;
508 DWORD fvf = 0;
509 BOOL invalid_fvf = FALSE;
510 DWORD tex = D3DFVF_TEX0;
511 DWORD len = 0;
512 DWORD stream = 0;
514 TRACE("(%p) : pDecl(%p)\n", This, pDecl);
516 while (0xFF != pToken->Stream) {
517 DWORD type = pToken->Type;
518 DWORD oldStream = stream;
519 stream = pToken->Stream;
521 IWineD3DVertexDeclarationImpl_ParseToken9(pToken);
523 if (D3DDECLMETHOD_DEFAULT != pToken->Method) {
524 WARN(
525 "%s register: Unsupported Method of %s (only D3DDECLMETHOD_DEFAULT for now) for VertexDeclaration (type %s)\n",
526 VertexDecl9_DeclUsages[pToken->Usage],
527 VertexDecl9_DeclMethods[pToken->Method],
528 VertexDecl9_DeclTypes[pToken->Type]
532 if (oldStream != stream) {
534 if (FALSE == invalid_fvf) {
535 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
536 tex = 0;
537 object->fvf[oldStream] = fvf;
538 object->allFVF |= fvf;
539 } else {
540 object->fvf[oldStream] = 0;
541 tex = 0;
544 /* reset valid/invalid fvf */
545 fvf = 0;
546 invalid_fvf = FALSE;
549 switch (pToken->Usage) {
550 case D3DDECLUSAGE_POSITION:
551 if (0 < pToken->UsageIndex) {
552 invalid_fvf = TRUE;
553 TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_POSITION register: unsupported type %s\n",
554 pToken->UsageIndex, VertexDecl9_DeclTypes[type]);
555 break;
557 switch (type) {
558 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZ; break;
559 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZRHW; break;
560 default:
561 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
562 invalid_fvf = TRUE;
563 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_POSITION register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
565 break;
567 case D3DDECLUSAGE_BLENDWEIGHT:
568 switch (type) {
569 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_XYZB1; break;
570 case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_XYZB2; break;
571 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_XYZB3; break;
572 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_XYZB4; break;
573 default:
574 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
575 invalid_fvf = TRUE;
576 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDWEIGHT register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
578 break;
580 case D3DDECLUSAGE_BLENDINDICES:
581 switch (type) {
582 case D3DDECLTYPE_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
583 default:
584 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
585 invalid_fvf = TRUE;
586 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_BLENDINDINCES register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
588 break;
590 case D3DDECLUSAGE_NORMAL:
591 if (0 < pToken->UsageIndex) {
592 invalid_fvf = TRUE;
593 TRACE("Mismatched UsageIndex (%u) in VertexDeclaration for D3DDECLUSAGE_NORMAL register: unsupported type %s\n",
594 pToken->UsageIndex, VertexDecl9_DeclTypes[type]);
595 break;
597 switch (type) {
598 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_NORMAL; break;
599 default:
600 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
601 invalid_fvf = TRUE;
602 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_NORMAL register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
604 break;
606 case D3DDECLUSAGE_PSIZE:
607 switch (type) {
608 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_PSIZE; 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_PSIZE register: unsupported type %s\n", VertexDecl9_DeclTypes[type]);
614 break;
616 case D3DDECLUSAGE_TEXCOORD:
618 DWORD texNo = pToken->UsageIndex;
619 tex = max(tex, texNo);
620 switch (type) {
621 case D3DDECLTYPE_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
622 case D3DDECLTYPE_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
623 case D3DDECLTYPE_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
624 case D3DDECLTYPE_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
625 default:
626 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
627 invalid_fvf = TRUE;
628 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_TEXCOORD[%lu] register: unsupported type %s\n", texNo, VertexDecl9_DeclTypes[type]);
631 break;
633 case D3DDECLUSAGE_COLOR:
635 DWORD colorNo = pToken->UsageIndex;
636 switch (type) {
637 case D3DDECLTYPE_D3DCOLOR:
638 switch (pToken->UsageIndex) {
639 case 0: fvf |= D3DFVF_DIFFUSE; break;
640 case 1: fvf |= D3DFVF_SPECULAR; break;
641 default:
642 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
643 invalid_fvf = TRUE;
644 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] unsupported COLOR register\n", colorNo);
646 break;
647 default:
648 /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */
649 invalid_fvf = TRUE;
650 TRACE("Mismatched use in VertexDeclaration of D3DDECLUSAGE_COLOR[%lu] register: unsupported type %s\n", colorNo, VertexDecl9_DeclTypes[type]);
653 break;
655 case D3DDECLUSAGE_TANGENT:
656 case D3DDECLUSAGE_BINORMAL:
657 case D3DDECLUSAGE_TESSFACTOR:
658 case D3DDECLUSAGE_POSITIONT:
659 case D3DDECLUSAGE_FOG:
660 case D3DDECLUSAGE_DEPTH:
661 case D3DDECLUSAGE_SAMPLE:
662 FIXME("%s Usage not supported yet by VertexDeclaration (type is %s)\n", VertexDecl9_DeclUsages[pToken->Usage], VertexDecl9_DeclTypes[type]);
663 break;
666 ++len;
667 ++pToken;
669 ++len; /* D3DDECL_END() */
671 /* copy fvf if valid */
672 if (FALSE == invalid_fvf) {
673 fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
674 object->fvf[stream] = fvf;
675 object->allFVF |= fvf;
676 } else {
677 object->fvf[stream] = 0;
681 TRACE("Completed, allFVF = %lx\n", object->allFVF);
683 /* compute size */
684 object->declaration9NumElements = len;
685 /* copy the declaration */
686 object->pDeclaration9 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(D3DVERTEXELEMENT9));
687 memcpy(object->pDeclaration9, pDecl, len * sizeof(D3DVERTEXELEMENT9));
688 /* returns */
690 TRACE("Returns allFVF = %lx\n", object->allFVF);
692 return D3D_OK;
695 /* *******************************************
696 IWineD3DVertexDeclaration IUnknown parts follow
697 ******************************************* */
698 HRESULT WINAPI IWineD3DVertexDeclarationImpl_QueryInterface(IWineD3DVertexDeclaration *iface, REFIID riid, LPVOID *ppobj)
700 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
701 WARN("(%p)->(%s,%p) should not be called\n",This,debugstr_guid(riid),ppobj);
702 return E_NOINTERFACE;
705 ULONG WINAPI IWineD3DVertexDeclarationImpl_AddRef(IWineD3DVertexDeclaration *iface) {
706 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
707 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
708 return InterlockedIncrement(&This->ref);
711 ULONG WINAPI IWineD3DVertexDeclarationImpl_Release(IWineD3DVertexDeclaration *iface) {
712 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
713 ULONG ref;
714 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
715 ref = InterlockedDecrement(&This->ref);
716 if (ref == 0) {
717 HeapFree(GetProcessHeap(), 0, This->pDeclaration8);
718 HeapFree(GetProcessHeap(), 0, This->pDeclaration9);
719 HeapFree(GetProcessHeap(), 0, This);
721 return ref;
724 /* *******************************************
725 IWineD3DVertexDeclaration parts follow
726 ******************************************* */
728 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDevice(IWineD3DVertexDeclaration *iface, IWineD3DDevice** ppDevice) {
729 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
730 TRACE("(%p) : returning %p\n", This, This->wineD3DDevice);
732 *ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
733 IWineD3DDevice_AddRef(*ppDevice);
735 return D3D_OK;
738 static HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration8(IWineD3DVertexDeclaration* iface, DWORD* pData, DWORD* pSizeOfData) {
739 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
740 if (NULL == pData) {
741 *pSizeOfData = This->declaration8Length;
742 return D3D_OK;
744 if (*pSizeOfData < This->declaration8Length) {
745 *pSizeOfData = This->declaration8Length;
746 return D3DERR_MOREDATA;
748 TRACE("(%p) : GetVertexDeclaration8 copying to %p\n", This, pData);
749 memcpy(pData, This->pDeclaration8, This->declaration8Length);
750 return D3D_OK;
753 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration9(IWineD3DVertexDeclaration* iface, D3DVERTEXELEMENT9* pData, DWORD* pNumElements) {
754 IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
755 if (NULL == pData) {
756 *pNumElements = This->declaration9NumElements;
757 return D3D_OK;
759 if (*pNumElements < This->declaration9NumElements) {
760 *pNumElements = This->declaration9NumElements;
761 return D3DERR_MOREDATA;
763 TRACE("(%p) : GetVertexDeclaration9 copying to %p\n", This, pData);
764 memcpy(pData, This->pDeclaration9, This->declaration9NumElements);
765 return D3D_OK;
768 HRESULT WINAPI IWineD3DVertexDeclarationImpl_GetDeclaration(IWineD3DVertexDeclaration* iface, UINT iDeclVersion, VOID* pData, DWORD* pSize) {
769 if (8 == iDeclVersion) {
770 return IWineD3DVertexDeclarationImpl_GetDeclaration8(iface, (DWORD*) pData, pSize);
772 return IWineD3DVertexDeclarationImpl_GetDeclaration9(iface, (D3DVERTEXELEMENT9*) pData, pSize);
775 IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl =
777 IWineD3DVertexDeclarationImpl_QueryInterface,
778 IWineD3DVertexDeclarationImpl_AddRef,
779 IWineD3DVertexDeclarationImpl_Release,
780 IWineD3DVertexDeclarationImpl_GetDevice,
781 IWineD3DVertexDeclarationImpl_GetDeclaration,