Correct the number of parameters expected for the LRP function.
[wine] / dlls / wined3d / vertexshader.c
1 /*
2  * shaders implementation
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include "config.h"
24
25 #include <math.h>
26 #include <stdio.h>
27
28 #include "wined3d_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
31
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
33
34 /* Shader debugging - Change the following line to enable debugging of software
35       vertex shaders                                                             */
36 #if 0 /* Musxt not be 1 in cvs version */
37 # define VSTRACE(A) TRACE A
38 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
39 #else
40 # define VSTRACE(A)
41 # define TRACE_VSVECTOR(name)
42 #endif
43
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
45
46 /**
47  * DirectX9 SDK download
48  *  http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
49  *
50  * Exploring D3DX
51  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
52  *
53  * Using Vertex Shaders
54  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
55  *
56  * Dx9 New
57  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
58  *
59  * Dx9 Shaders
60  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
61  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
62  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
63  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
64  *
65  * Dx9 D3DX
66  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
67  *
68  * FVF
69  *  http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
70  *
71  * NVIDIA: DX8 Vertex Shader to NV Vertex Program
72  *  http://developer.nvidia.com/view.asp?IO=vstovp
73  *
74  * NVIDIA: Memory Management with VAR
75  *  http://developer.nvidia.com/view.asp?IO=var_memory_management
76  */
77
78 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
79 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
80
81 typedef void (*shader_fct_t)();
82
83 typedef struct SHADER_OPCODE {
84   unsigned int  opcode;
85   const char*   name;
86   const char*   glname;
87   CONST UINT    num_params;
88   shader_fct_t  soft_fct;
89   DWORD         min_version;
90   DWORD         max_version;
91 } SHADER_OPCODE;
92
93 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
94
95 /*******************************
96  * vshader functions software VM
97  */
98
99 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
100   d->x = s0->x + s1->x;
101   d->y = s0->y + s1->y;
102   d->z = s0->z + s1->z;
103   d->w = s0->w + s1->w;
104   VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
105                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
106 }
107
108 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
109   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
110   VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
111                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
112 }
113
114 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
115   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
116   VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
117           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
118 }
119
120 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
121   d->x = 1.0f;
122   d->y = s0->y * s1->y;
123   d->z = s0->z;
124   d->w = s1->w;
125   VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
126           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
127 }
128
129 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
130   union {
131     float f;
132     DWORD d;
133   } tmp;
134
135   tmp.f = floorf(s0->w);
136   d->x  = powf(2.0f, tmp.f);
137   d->y  = s0->w - tmp.f;
138   tmp.f = powf(2.0f, s0->w);
139   tmp.d &= 0xFFFFFF00U;
140   d->z  = tmp.f;
141   d->w  = 1.0f;
142   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
143                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
144 }
145
146 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
147   d->x = 1.0f;
148   d->y = (0.0f < s0->x) ? s0->x : 0.0f;
149   d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
150   d->w = 1.0f;
151   VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
152                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
153 }
154
155 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
156   float tmp_f = fabsf(s0->w);
157   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
158   VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
159                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
160 }
161
162 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
163   d->x = s0->x * s1->x + s2->x;
164   d->y = s0->y * s1->y + s2->y;
165   d->z = s0->z * s1->z + s2->z;
166   d->w = s0->w * s1->w + s2->w;
167   VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
168           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, s2->x, s2->y, s2->z, s2->w, d->x, d->y, d->z, d->w));
169 }
170
171 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
172   d->x = (s0->x >= s1->x) ? s0->x : s1->x;
173   d->y = (s0->y >= s1->y) ? s0->y : s1->y;
174   d->z = (s0->z >= s1->z) ? s0->z : s1->z;
175   d->w = (s0->w >= s1->w) ? s0->w : s1->w;
176   VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
177           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
178 }
179
180 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
181   d->x = (s0->x < s1->x) ? s0->x : s1->x;
182   d->y = (s0->y < s1->y) ? s0->y : s1->y;
183   d->z = (s0->z < s1->z) ? s0->z : s1->z;
184   d->w = (s0->w < s1->w) ? s0->w : s1->w;
185   VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
186           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
187 }
188
189 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
190   d->x = s0->x;
191   d->y = s0->y;
192   d->z = s0->z;
193   d->w = s0->w;
194   VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
195           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
196 }
197
198 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
199   d->x = s0->x * s1->x;
200   d->y = s0->y * s1->y;
201   d->z = s0->z * s1->z;
202   d->w = s0->w * s1->w;
203   VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
205 }
206
207 void vshader_nop(void) {
208     /* NOPPPP ahhh too easy ;) */
209     VSTRACE(("executing nop\n"));
210 }
211
212 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
213   d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
214   VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
215           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
216 }
217
218 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
219   float tmp_f = fabsf(s0->w);
220   d->x = d->y = d->z = d->w = (0.0f == tmp_f) ? HUGE_VAL : ((1.0f != tmp_f) ? 1.0f / sqrtf(tmp_f) : 1.0f);
221   VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
222           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
223 }
224
225 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
226   d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
227   d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
228   d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
229   d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
230   VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
231           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
232 }
233
234 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
235   d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
236   d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
237   d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
238   d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
239   VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
240           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
241 }
242
243 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
244   d->x = s0->x - s1->x;
245   d->y = s0->y - s1->y;
246   d->z = s0->z - s1->z;
247   d->w = s0->w - s1->w;
248   VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
249           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
250 }
251
252 /**
253  * Version 1.1 specific
254  */
255
256 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
257   d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
258   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
259           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
260 }
261
262 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
263   float tmp_f = fabsf(s0->w);
264   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
265   VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
266           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
267 }
268
269 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
270   d->x = s0->x - floorf(s0->x);
271   d->y = s0->y - floorf(s0->y);
272   d->z = 0.0f;
273   d->w = 1.0f;
274   VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
275           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
276 }
277
278 typedef FLOAT D3DMATRIX44[4][4];
279 typedef FLOAT D3DMATRIX43[4][3];
280 typedef FLOAT D3DMATRIX34[4][4];
281 typedef FLOAT D3DMATRIX33[4][3];
282 typedef FLOAT D3DMATRIX32[4][2];
283
284 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
285   /*
286    * Buggy CODE: here only if cast not work for copy/paste
287   WINED3DSHADERVECTOR* mat2 = mat1 + 1;
288   WINED3DSHADERVECTOR* mat3 = mat1 + 2;
289   WINED3DSHADERVECTOR* mat4 = mat1 + 3;
290   d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
291   d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
292   d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
293   d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
294   */
295   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
298   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
299   VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
300   VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
301   VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
302   VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
303 }
304
305 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
307   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
308   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
309   d->w = 1.0f;
310   VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
311   VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
312   VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
313   VSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
314 }
315
316 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
317   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318   d->y = mat[2][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
320   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
321   VSTRACE(("executing m3x4(1): mat=(%f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
322   VSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323   VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
324   VSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
325 }
326
327 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
328   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[2][2] * s0->z;
329   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[2][2] * s0->z;
330   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
331   d->w = 1.0f;
332   VSTRACE(("executing m3x3(1): mat=(%f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
333   VSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
334   VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
335   VSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
336 }
337
338 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX32 mat) {
339   FIXME("check\n");
340   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
341   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
342   d->z = 0.0f;
343   d->w = 1.0f;
344 }
345
346 /**
347  * Version 2.0 specific
348  */
349 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
350   d->x = s0->x * (s1->x - s2->x) + s2->x;
351   d->y = s0->y * (s1->y - s2->y) + s2->y;
352   d->z = s0->z * (s1->z - s2->z) + s2->z;
353   d->w = s0->w * (s1->w - s2->w) + s2->x;
354 }
355
356 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
357   d->x = s0->y * s1->z - s0->z * s1->y;
358   d->y = s0->z * s1->x - s0->x * s1->z;
359   d->z = s0->x * s1->y - s0->y * s1->x;
360   d->w = 0.9f; /* w is undefined, so set it to something safeish */
361
362   VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
363              s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
364 }
365
366 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
367
368   d->x = fabsf(s0->x);
369   d->y = fabsf(s0->y);
370   d->z = fabsf(s0->z);
371   d->w = fabsf(s0->w);
372   VSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
373              s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
374 }
375
376     /* Stubs */
377 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
378     FIXME(" : Stub\n");
379 }
380
381 void vshader_texkill(WINED3DSHADERVECTOR* d) {
382     FIXME(" : Stub\n");
383 }
384
385 void vshader_tex(WINED3DSHADERVECTOR* d) {
386     FIXME(" : Stub\n");
387 }
388 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
389     FIXME(" : Stub\n");
390 }
391
392 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393     FIXME(" : Stub\n");
394 }
395
396 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
397     FIXME(" : Stub\n");
398 }
399
400 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401     FIXME(" : Stub\n");
402 }
403
404 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405     FIXME(" : Stub\n");
406 }
407
408 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409     FIXME(" : Stub\n");
410 }
411
412 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
413     FIXME(" : Stub\n");
414 }
415
416 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
417     FIXME(" : Stub\n");
418 }
419
420 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421     FIXME(" : Stub\n");
422 }
423
424 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
425     FIXME(" : Stub\n");
426 }
427
428 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
429     FIXME(" : Stub\n");
430 }
431
432 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
433     FIXME(" : Stub\n");
434 }
435
436 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
437     FIXME(" : Stub\n");
438 }
439
440 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
441 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
442     FIXME(" : Stub\n");
443 }
444
445 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
446     FIXME(" : Stub\n");
447 }
448
449 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
450     FIXME(" : Stub\n");
451 }
452
453 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
454     FIXME(" : Stub\n");
455 }
456
457 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
458     FIXME(" : Stub\n");
459 }
460
461 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
462     FIXME(" : Stub\n");
463 }
464
465 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
466     FIXME(" : Stub\n");
467 }
468
469 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
470     FIXME(" : Stub\n");
471 }
472
473 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
474     FIXME(" : Stub\n");
475 }
476
477 void vshader_call(WINED3DSHADERVECTOR* d) {
478     FIXME(" : Stub\n");
479 }
480
481 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
482     FIXME(" : Stub\n");
483 }
484
485 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486     FIXME(" : Stub\n");
487 }
488
489 void vshader_ret(WINED3DSHADERVECTOR* d) {
490     FIXME(" : Stub\n");
491 }
492
493 void vshader_endloop(WINED3DSHADERVECTOR* d) {
494     FIXME(" : Stub\n");
495 }
496
497 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
498     FIXME(" : Stub\n");
499 }
500
501 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
502     FIXME(" : Stub\n");
503 }
504
505 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
506     FIXME(" : Stub\n");
507 }
508
509 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
510     FIXME(" : Stub\n");
511 }
512
513 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514     FIXME(" : Stub\n");
515 }
516
517 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
518     FIXME(" : Stub\n");
519 }
520
521 void vshader_endrep(void) {
522     FIXME(" : Stub\n");
523 }
524
525 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
526     FIXME(" : Stub\n");
527 }
528
529 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
530     FIXME(" : Stub\n");
531 }
532
533 void vshader_else(WINED3DSHADERVECTOR* d) {
534     FIXME(" : Stub\n");
535 }
536
537 void vshader_label(WINED3DSHADERVECTOR* d) {
538     FIXME(" : Stub\n");
539 }
540
541 void vshader_endif(WINED3DSHADERVECTOR* d) {
542     FIXME(" : Stub\n");
543 }
544
545 void vshader_break(WINED3DSHADERVECTOR* d) {
546     FIXME(" : Stub\n");
547 }
548
549 void vshader_breakc(WINED3DSHADERVECTOR* d) {
550     FIXME(" : Stub\n");
551 }
552
553 void vshader_mova(WINED3DSHADERVECTOR* d) {
554     FIXME(" : Stub\n");
555 }
556
557 void vshader_defb(WINED3DSHADERVECTOR* d) {
558     FIXME(" : Stub\n");
559 }
560
561 void vshader_defi(WINED3DSHADERVECTOR* d) {
562     FIXME(" : Stub\n");
563 }
564
565 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
566     FIXME(" : Stub\n");
567 }
568
569 void vshader_dsx(WINED3DSHADERVECTOR* d) {
570     FIXME(" : Stub\n");
571 }
572
573 void vshader_dsy(WINED3DSHADERVECTOR* d) {
574     FIXME(" : Stub\n");
575 }
576
577 void vshader_texldd(WINED3DSHADERVECTOR* d) {
578     FIXME(" : Stub\n");
579 }
580
581 void vshader_setp(WINED3DSHADERVECTOR* d) {
582     FIXME(" : Stub\n");
583 }
584
585 void vshader_texldl(WINED3DSHADERVECTOR* d) {
586     FIXME(" : Stub\n");
587 }
588
589 void vshader_breakp(WINED3DSHADERVECTOR* d) {
590     FIXME(" : Stub\n");
591 }
592
593
594 /**
595  * log, exp, frc, m*x* seems to be macros ins ... to see
596  */
597 static CONST SHADER_OPCODE vshader_ins [] = {
598     {D3DSIO_NOP,  "nop", "NOP", 0, vshader_nop, 0, 0},
599     {D3DSIO_MOV,  "mov", "MOV", 2, vshader_mov, 0, 0},
600     {D3DSIO_ADD,  "add", "ADD", 3, vshader_add, 0, 0},
601     {D3DSIO_SUB,  "sub", "SUB", 3, vshader_sub, 0, 0},
602     {D3DSIO_MAD,  "mad", "MAD", 4, vshader_mad, 0, 0},
603     {D3DSIO_MUL,  "mul", "MUL", 3, vshader_mul, 0, 0},
604     {D3DSIO_RCP,  "rcp", "RCP",  2, vshader_rcp, 0, 0},
605     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, vshader_rsq, 0, 0},
606     {D3DSIO_DP3,  "dp3",  "DP3", 3, vshader_dp3, 0, 0},
607     {D3DSIO_DP4,  "dp4",  "DP4", 3, vshader_dp4, 0, 0},
608     {D3DSIO_MIN,  "min",  "MIN", 3, vshader_min, 0, 0},
609     {D3DSIO_MAX,  "max",  "MAX", 3, vshader_max, 0, 0},
610     {D3DSIO_SLT,  "slt",  "SLT", 3, vshader_slt, 0, 0},
611     {D3DSIO_SGE,  "sge",  "SGE", 3, vshader_sge, 0, 0},
612     {D3DSIO_ABS,  "abs",  "ABS", 2, vshader_abs, 0, 0},
613     {D3DSIO_EXP,  "exp",  "EX2", 2, vshader_exp, 0, 0},
614     {D3DSIO_LOG,  "log",  "LG2", 2, vshader_log, 0, 0},
615     {D3DSIO_LIT,  "lit",  "LIT", 2, vshader_lit, 0, 0},
616     {D3DSIO_DST,  "dst",  "DST", 3, vshader_dst, 0, 0},
617     {D3DSIO_LRP,  "lrp",  "LRP", 4, vshader_lrp, 0, 0},
618     {D3DSIO_FRC,  "frc",  "FRC", 2, vshader_frc, 0, 0},
619     {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
620     {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
621     {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
622     {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
623     {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
624     /** FIXME: use direct access so add the others opcodes as stubs */
625     /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
626         They can be easly managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
627     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, vshader_call,    0, 0},
628     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, vshader_callnz,  0, 0},
629     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, vshader_loop,    0, 0},
630     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, vshader_ret,     0, 0},
631     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, vshader_endloop, 0, 0},
632     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, vshader_label,   0, 0},
633     /* DCL is a specil operation */
634     {D3DSIO_DCL,      "dcl",      NULL,   1, vshader_dcl,     0, 0},
635     {D3DSIO_POW,      "pow",      "POW",  3, vshader_pow,     0, 0},
636     {D3DSIO_CRS,      "crs",      "XPS",  3, vshader_crs,     0, 0},
637     /* TODO: sng can possibly be performed as
638         RCP tmp, vec
639         MUL out, tmp, vec*/
640     {D3DSIO_SGN,      "sng",      NULL,   2, vshader_sng,     0, 0},
641     /* TODO: xyz normalise can be performed is VS_ARB using one tempory register,
642         DP3 tmp , vec, vec;
643         RSQ tmp, tmp.x;
644         MUL vec.xyz, vec, tmp;
645     but I think this is better because it accounts for w properly.
646         DP3 tmp , vec, vec;
647         RSQ tmp, tmp.x;
648         MUL vec, vec, tmp;
649     
650     */
651     {D3DSIO_NRM,      "nrm",      NULL,   2, vshader_nrm,     0, 0},
652     {D3DSIO_SINCOS,   "sincos",   NULL,   2, vshader_sincos,  0, 0},
653     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   2, vshader_rep,     0, 0},
654     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, vshader_endrep,  0, 0},
655     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   2, vshader_if,      0, 0},
656     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, vshader_ifc,     0, 0},
657     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   2, vshader_else,    0, 0},
658     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   2, vshader_endif,   0, 0},
659     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   2, vshader_break,   0, 0},
660     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, vshader_breakc,  0, 0},
661     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, vshader_mova,    0, 0},
662     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, vshader_defb,    0, 0},
663     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, vshader_defi,    0, 0},
664
665     {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL,   1, vshader_texcoord,    D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666     {D3DSIO_TEXCOORD, "texcrd",   GLNAME_REQUIRE_GLSL,   2, vshader_texcoord,    D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
667     {D3DSIO_TEXKILL,  "texkill",  GLNAME_REQUIRE_GLSL,   1, vshader_texkill,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
668     {D3DSIO_TEX,      "tex",      GLNAME_REQUIRE_GLSL,   1, vshader_tex,         D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
669     {D3DSIO_TEX,      "texld",    GLNAME_REQUIRE_GLSL,   2, vshader_texld,       D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
670     {D3DSIO_TEXBEM,   "texbem",   GLNAME_REQUIRE_GLSL,   2, vshader_texbem,      D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
671     {D3DSIO_TEXBEML,  "texbeml",  GLNAME_REQUIRE_GLSL,   2, vshader_texbeml,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
672     {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL,   2, vshader_texreg2ar,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
673     {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL,   2, vshader_texreg2gb,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674     {D3DSIO_TEXM3x2PAD,   "texm3x2pad",   GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2pad,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
675     {D3DSIO_TEXM3x2TEX,   "texm3x2tex",   GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2tex,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
676     {D3DSIO_TEXM3x3DIFF,  "texm3x3diff",  GLNAME_REQUIRE_GLSL,   2, vshader_texm3x3diff,  D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
677     {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  GLNAME_REQUIRE_GLSL,   3, vshader_texm3x3spec,  D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
678     {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe",  GLNAME_REQUIRE_GLSL,   2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
679
680     {D3DSIO_EXPP,     "expp",     "EXP", 2, vshader_expp, 0, 0},
681     {D3DSIO_LOGP,     "logp",     "LOG", 2, vshader_logp, 0, 0},
682     {D3DSIO_CND,      "cnd",      GLNAME_REQUIRE_GLSL,   4, vshader_cnd,         D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
683     /* def is a special opperation */
684     {D3DSIO_DEF,      "def",      NULL,   5, vshader_def,         D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
685     {D3DSIO_TEXREG2RGB,   "texreg2rgb",   GLNAME_REQUIRE_GLSL,   2, vshader_texreg2rgb,  D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
686     {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL,   2, vshader_texdp3tex,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
687     {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
688     {D3DSIO_TEXDP3,       "texdp3", GLNAME_REQUIRE_GLSL,  2, vshader_texdp3,     D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
689     {D3DSIO_TEXM3x3,      "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3,    D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
690     {D3DSIO_TEXDEPTH,     "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth,   D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
691     {D3DSIO_CMP,      "cmp",      GLNAME_REQUIRE_GLSL,   4, vshader_cmp,     D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
692     {D3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL,   3, vshader_bem,     D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
693     /* TODO: dp2add can be made out of multiple instuctions */
694     {D3DSIO_DP2ADD,   "dp2add",   GLNAME_REQUIRE_GLSL,   2, vshader_dp2add,  0, 0},
695     {D3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL,   2, vshader_dsx,     0, 0},
696     {D3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL,   2, vshader_dsy,     0, 0},
697     {D3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL,   2, vshader_texldd,  0, 0},
698     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, vshader_setp,    0, 0},
699     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, vshader_texldl,  0, 0},
700     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   2, vshader_breakp,  0, 0},
701     {D3DSIO_PHASE,    "phase",    GLNAME_REQUIRE_GLSL,   0, vshader_nop,     0, 0},
702     {0,               NULL,       NULL,   0, NULL,            0, 0}
703 };
704
705
706 inline static const SHADER_OPCODE* vshader_program_get_opcode(const DWORD code) {
707     DWORD i = 0;
708     /** TODO: use dichotomic search or hash table */
709     while (NULL != vshader_ins[i].name) {
710         if ((code & D3DSI_OPCODE_MASK) == vshader_ins[i].opcode) {
711             return &vshader_ins[i];
712         }
713         ++i;
714     }
715     FIXME("Unsupported opcode %lx\n",code);
716     return NULL;
717 }
718
719 inline static void vshader_program_dump_param(const DWORD param, int input) {
720   static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
721   static const char swizzle_reg_chars[] = "xyzw";
722
723   DWORD reg = param & 0x00001FFF;
724   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
725
726   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
727
728   switch (regtype) {
729   case D3DSPR_TEMP:
730     TRACE("R[%lu]", reg);
731     break;
732   case D3DSPR_INPUT:
733     TRACE("v%lu", reg);
734     break;
735   case D3DSPR_CONST:
736     TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
737     break;
738   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
739     TRACE("a[%lu]", reg);
740     break;
741   case D3DSPR_RASTOUT:
742     TRACE("%s", rastout_reg_names[reg]);
743     break;
744   case D3DSPR_ATTROUT:
745     TRACE("oD[%lu]", reg);
746     break;
747   case D3DSPR_TEXCRDOUT:
748     TRACE("oT[%lu]", reg);
749     break;
750   default:
751     FIXME("Unknown %lu %u reg %lu\n",regtype,  D3DSPR_ATTROUT, reg);
752     break;
753   }
754
755   if (!input) {
756     /** operand output */
757     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
758       if (param & D3DSP_WRITEMASK_0) TRACE(".x");
759       if (param & D3DSP_WRITEMASK_1) TRACE(".y");
760       if (param & D3DSP_WRITEMASK_2) TRACE(".z");
761       if (param & D3DSP_WRITEMASK_3) TRACE(".w");
762     }
763   } else {
764     /** operand input */
765     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
766     DWORD swizzle_x = swizzle & 0x03;
767     DWORD swizzle_y = (swizzle >> 2) & 0x03;
768     DWORD swizzle_z = (swizzle >> 4) & 0x03;
769     DWORD swizzle_w = (swizzle >> 6) & 0x03;
770     /**
771      * swizzle bits fields:
772      *  WWZZYYXX
773      */
774     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
775       if (swizzle_x == swizzle_y &&
776             swizzle_x == swizzle_z &&
777             swizzle_x == swizzle_w) {
778                 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
779             } else {
780                 TRACE(".%c%c%c%c",
781                     swizzle_reg_chars[swizzle_x],
782                     swizzle_reg_chars[swizzle_y],
783                     swizzle_reg_chars[swizzle_z],
784                     swizzle_reg_chars[swizzle_w]);
785       }
786     }
787   }
788 }
789
790 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
791   static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
792   static const char swizzle_reg_chars[] = "xyzw";
793    /* the unknown mask is for bits not yet accounted for by any other mask... */
794 #define UNKNOWN_MASK 0xC000
795
796    /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
797 #define EXTENDED_REG 0x1800
798
799   DWORD reg = param & D3DSP_REGNUM_MASK; /* 0x00001FFF;  isn't this D3DSP_REGNUM_MASK? */
800   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
801
802   if(param & UNKNOWN_MASK) { /* if this register has any of the unknown bits set then report them*/
803       FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype, (param & EXTENDED_REG), param & UNKNOWN_MASK);
804   }
805
806   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
807
808   switch (regtype /*<< D3DSP_REGTYPE_SHIFT*/) {
809   case D3DSPR_TEMP:
810     TRACE("r%lu", reg);
811     break;
812   case D3DSPR_INPUT:
813     TRACE("v%lu", reg);
814     break;
815   case D3DSPR_CONST:
816     TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
817     break;
818   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
819     TRACE("a%lu", reg);
820     break;
821   case D3DSPR_RASTOUT:
822     TRACE("%s", rastout_reg_names[reg]);
823     break;
824   case D3DSPR_ATTROUT:
825     TRACE("oD%lu", reg);
826     break;
827   case D3DSPR_TEXCRDOUT:
828     TRACE("oT%lu", reg);
829     break;
830   case D3DSPR_CONSTINT:
831     TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
832     break;
833   case D3DSPR_CONSTBOOL:
834     TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
835     break;
836   case D3DSPR_LABEL:
837     TRACE("l%lu", reg);
838     break;
839   case D3DSPR_LOOP:
840     TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
841     break;
842   default:
843     FIXME("Unknown %lu reg %lu\n",regtype, reg);
844     break;
845   }
846
847   if (!input) {
848     /** operand output */
849     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
850       if (param & D3DSP_WRITEMASK_0) TRACE(".x");
851       if (param & D3DSP_WRITEMASK_1) TRACE(".y");
852       if (param & D3DSP_WRITEMASK_2) TRACE(".z");
853       if (param & D3DSP_WRITEMASK_3) TRACE(".w");
854     }
855   } else {
856     /** operand input */
857     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
858     DWORD swizzle_x = swizzle & 0x03;
859     DWORD swizzle_y = (swizzle >> 2) & 0x03;
860     DWORD swizzle_z = (swizzle >> 4) & 0x03;
861     DWORD swizzle_w = (swizzle >> 6) & 0x03;
862     /**
863      * swizzle bits fields:
864      *  WWZZYYXX
865      */
866     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
867       if (swizzle_x == swizzle_y &&
868         swizzle_x == swizzle_z &&
869         swizzle_x == swizzle_w) {
870             TRACE(".%c", swizzle_reg_chars[swizzle_x]);
871       } else {
872         TRACE(".%c%c%c%c",
873         swizzle_reg_chars[swizzle_x],
874         swizzle_reg_chars[swizzle_y],
875         swizzle_reg_chars[swizzle_z],
876         swizzle_reg_chars[swizzle_w]);
877       }
878     }
879   }
880 }
881
882 inline static BOOL vshader_is_version_token(DWORD token) {
883   return 0xFFFE0000 == (token & 0xFFFE0000);
884 }
885
886 inline static BOOL vshader_is_comment_token(DWORD token) {
887   return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
888 }
889
890 inline static void vshader_program_add_param(const DWORD param, int input, char *hwLine, BOOL namedArrays, CHAR constantsUsedBitmap[]) {
891   /*static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" }; */
892   static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
893   static const char swizzle_reg_chars[] = "xyzw";
894
895   DWORD reg = param & 0x00001FFF;
896   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
897   char  tmpReg[255];
898
899   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
900       strcat(hwLine, " -");
901   } else {
902       strcat(hwLine, " ");
903   }
904
905   switch (regtype) {
906   case D3DSPR_TEMP:
907     sprintf(tmpReg, "T%lu", reg);
908     strcat(hwLine, tmpReg);
909     break;
910   case D3DSPR_INPUT:
911     /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
912     if (namedArrays) {
913         sprintf(tmpReg, "namedVertex%lu", reg);
914     } else {
915     /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
916         sprintf(tmpReg, "vertex.attrib[%lu]", reg);
917     }
918     strcat(hwLine, tmpReg);
919     break;
920   case D3DSPR_CONST:
921     /* FIXME: some constants are named so we need a constants map*/
922     if (constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
923         if (param & D3DVS_ADDRMODE_RELATIVE) {
924             FIXME("Relitive addressing not expected for a named constant %lu\n", reg);
925         }
926         sprintf(tmpReg, "const%lu", reg);
927     } else {
928         sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
929     }
930     strcat(hwLine, tmpReg);
931     break;
932   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
933     sprintf(tmpReg, "A%lu", reg);
934     strcat(hwLine, tmpReg);
935     break;
936   case D3DSPR_RASTOUT:
937     sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
938     strcat(hwLine, tmpReg);
939     break;
940   case D3DSPR_ATTROUT:
941     if (reg==0) {
942        strcat(hwLine, "result.color.primary");
943     } else {
944        strcat(hwLine, "result.color.secondary");
945     }
946     break;
947   case D3DSPR_TEXCRDOUT:
948     sprintf(tmpReg, "result.texcoord[%lu]", reg);
949     strcat(hwLine, tmpReg);
950     break;
951   default:
952     FIXME("Unknown reg type %ld %ld\n", regtype, reg);
953     break;
954   }
955
956   if (!input) {
957     /** operand output */
958     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
959       strcat(hwLine, ".");
960       if (param & D3DSP_WRITEMASK_0) {
961           strcat(hwLine, "x");
962       }
963       if (param & D3DSP_WRITEMASK_1) {
964           strcat(hwLine, "y");
965       }
966       if (param & D3DSP_WRITEMASK_2) {
967           strcat(hwLine, "z");
968       }
969       if (param & D3DSP_WRITEMASK_3) {
970           strcat(hwLine, "w");
971       }
972     }
973   } else {
974     /** operand input */
975     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
976     DWORD swizzle_x = swizzle & 0x03;
977     DWORD swizzle_y = (swizzle >> 2) & 0x03;
978     DWORD swizzle_z = (swizzle >> 4) & 0x03;
979     DWORD swizzle_w = (swizzle >> 6) & 0x03;
980     /**
981      * swizzle bits fields:
982      *  WWZZYYXX
983      */
984     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
985       if (swizzle_x == swizzle_y &&
986         swizzle_x == swizzle_z &&
987         swizzle_x == swizzle_w)
988       {
989         sprintf(tmpReg, ".%c", swizzle_reg_chars[swizzle_x]);
990         strcat(hwLine, tmpReg);
991       } else {
992         sprintf(tmpReg, ".%c%c%c%c",
993         swizzle_reg_chars[swizzle_x],
994         swizzle_reg_chars[swizzle_y],
995         swizzle_reg_chars[swizzle_z],
996         swizzle_reg_chars[swizzle_w]);
997         strcat(hwLine, tmpReg);
998       }
999     }
1000   }
1001 }
1002
1003 DWORD MacroExpansion[4*4];
1004
1005 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1006   int i;
1007   int nComponents = 0;
1008   DWORD opcode =0;
1009   switch(macro_opcode) {
1010     case D3DSIO_M4x4:
1011       nComponents = 4;
1012       opcode = D3DSIO_DP4;
1013       break;
1014     case D3DSIO_M4x3:
1015       nComponents = 3;
1016       opcode = D3DSIO_DP4;
1017       break;
1018     case D3DSIO_M3x4:
1019       nComponents = 4;
1020       opcode = D3DSIO_DP3;
1021       break;
1022     case D3DSIO_M3x3:
1023       nComponents = 3;
1024       opcode = D3DSIO_DP3;
1025       break;
1026     case D3DSIO_M3x2:
1027       nComponents = 2;
1028       opcode = D3DSIO_DP3;
1029       break;
1030     default:
1031       break;
1032   }
1033   for (i = 0; i < nComponents; i++) {
1034     MacroExpansion[i*4+0] = opcode;
1035     MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1036     MacroExpansion[i*4+2] = *(args+1);
1037     MacroExpansion[i*4+3] = (*(args+2))+i;
1038   }
1039   return nComponents;
1040 }
1041
1042 /**
1043  * Function parser ...
1044  */
1045
1046 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1047     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1048     const DWORD* pToken = pFunction;
1049     const DWORD* pSavedToken = NULL;
1050     const SHADER_OPCODE* curOpcode = NULL;
1051     int nRemInstr = -1;
1052     DWORD i;
1053     unsigned lineNum = 0;
1054     char *pgmStr = NULL;
1055     char  tmpLine[255];
1056     DWORD nUseAddressRegister = 0;
1057     DWORD nUseTempRegister = 0;
1058     DWORD regtype;
1059     DWORD reg;
1060     BOOL tmpsUsed[32];
1061 #if 0 /* TODO: loope register (just another address register ) */
1062     BOOL hasLoops = FALSE;
1063 #endif
1064
1065 #define PGMSIZE 65535
1066 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1067     int pgmLength = 0;
1068
1069 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1070         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occure... */
1071     if (This->device->fixupVertexBufferSize < PGMSIZE) {
1072         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1073         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1074         This->fixupVertexBufferSize = PGMSIZE;
1075         This->fixupVertexBuffer[0] = 0;
1076     }
1077     pgmStr = This->device->fixupVertexBuffer;
1078 #endif
1079 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1080         int _tmpLineLen = strlen(_tmpLine); \
1081         if(_tmpLineLen + pgmLength > PGMSIZE) { \
1082             ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1083         } else { \
1084            memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1085         } \
1086         pgmLength += _tmpLineLen; \
1087         }
1088
1089     pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1090     /* Initilise the shader */
1091     This->namedArrays = FALSE;
1092     This->declaredArrays = FALSE;
1093     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1094         This->arrayUsageMap[i] = -1;
1095     }
1096     /* set all the tmpsUsed to not used */
1097     memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1098
1099     /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1100     This->highestConstant = -1;
1101
1102
1103   /**
1104    * First pass to determine what we need to declare:
1105    *  - Temporary variables
1106    *  - Address variables
1107    */ 
1108     if (NULL != pToken) {
1109         while (D3DVS_END() != *pToken) {
1110             if (vshader_is_version_token(*pToken)) {
1111             /** skip version */
1112             ++pToken;
1113             continue;
1114             }
1115             if (vshader_is_comment_token(*pToken)) { /** comment */
1116                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1117                 ++pToken;
1118                 pToken += comment_len;
1119                 continue;
1120             }
1121             curOpcode = vshader_program_get_opcode(*pToken);
1122             ++pToken;
1123             /* TODO: dcl's */
1124             /* TODO: Consts */
1125
1126             if (NULL == curOpcode) {
1127                 while (*pToken & 0x80000000) {
1128                     FIXME("unrecognized opcode: %08lx\n", *pToken);
1129                     /* skip unrecognized opcode */
1130                     ++pToken;
1131                 }
1132             } else {
1133                 if (curOpcode->opcode == D3DSIO_DCL){
1134                     INT usage = *pToken++;
1135                     INT arrayNo = (*pToken++ & 0x00001FFF);
1136                     switch(usage & 0xFFFF) {
1137                     case D3DDECLUSAGE_POSITION:
1138                         if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1139                             TRACE("Setting position to %d\n", arrayNo);
1140                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
1141                             This->namedArrays = TRUE;
1142                         } else {
1143                             /* TODO: position indexes go fro 0-8!!*/
1144                             TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1145                             /* robots uses positions upto 8, the position arrays are just packed.*/
1146                             if ((usage & 0xF0000) >> 16 > 1) {
1147                                 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1148                             }
1149                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1150                             This->declaredArrays = TRUE;
1151                         }
1152                     break;
1153                     case D3DDECLUSAGE_BLENDINDICES:
1154                         /* not supported by openGL */
1155                         TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1156                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1157                         This->declaredArrays = TRUE;
1158                         if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1159                     break;
1160                     case D3DDECLUSAGE_BLENDWEIGHT:
1161                          TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1162                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
1163                         This->namedArrays = TRUE;
1164                         if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1165                     break;
1166                     case D3DDECLUSAGE_NORMAL:
1167                         if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1168                             TRACE("Setting normal to %d\n", arrayNo);
1169                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
1170                             This->namedArrays = TRUE;
1171                         } else {
1172                             TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1173                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
1174                             This->declaredArrays = TRUE;
1175                         }
1176                     break;
1177                     case D3DDECLUSAGE_PSIZE:
1178                         TRACE("Setting PSIZE to %d\n", arrayNo);
1179                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
1180                         This->namedArrays = TRUE;
1181                         if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1182                     break;
1183                     case D3DDECLUSAGE_COLOR:
1184                         if((usage & 0xF0000) >> 16 == 0)  {
1185                             TRACE("Setting DIFFUSE to %d\n", arrayNo);
1186                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
1187                             This->namedArrays = TRUE;
1188                         } else {
1189                             TRACE("Setting SPECULAR to %d\n", arrayNo);
1190                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1191                             This->namedArrays = TRUE;
1192                         }
1193                     break;
1194                     case D3DDECLUSAGE_TEXCOORD:
1195                         This->namedArrays = TRUE;
1196                         /* only 7 texture coords have been designed for, so run a quick sanity check */
1197                         if ((usage & 0xF0000) >> 16 > 7) {
1198                             FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1199                         } else {
1200                             TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1201                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1202                         }
1203                     break;
1204                     /* The following aren't supported by openGL,
1205                         if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1206                         this should be caught in the first pass */
1207                     case D3DDECLUSAGE_TANGENT:
1208                         TRACE("Setting TANGENT to %d\n", arrayNo);
1209                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
1210                         This->declaredArrays = TRUE;
1211                     break;
1212                     case D3DDECLUSAGE_BINORMAL:
1213                         TRACE("Setting BINORMAL to %d\n", arrayNo);
1214                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
1215                         This->declaredArrays = TRUE;
1216                     break;
1217                     case D3DDECLUSAGE_TESSFACTOR:
1218                         TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1219                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
1220                         This->declaredArrays = TRUE;
1221                     break;
1222                     case D3DDECLUSAGE_POSITIONT:
1223                         if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1224                             FIXME("Setting positiont to %d\n", arrayNo);
1225                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1226                             This->namedArrays = TRUE;
1227                         } else {
1228                             FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1229                             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1230                             This->declaredArrays = TRUE;
1231                         if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1232                         }
1233                     break;
1234                     case D3DDECLUSAGE_FOG:
1235                         /* supported by OpenGL */
1236                         TRACE("Setting FOG to %d\n", arrayNo);
1237                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
1238                         This->namedArrays = TRUE;
1239                     break;
1240                     case D3DDECLUSAGE_DEPTH:
1241                         TRACE("Setting DEPTH to %d\n", arrayNo);
1242                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
1243                         This->declaredArrays = TRUE;
1244                     break;
1245                     case D3DDECLUSAGE_SAMPLE:
1246                         TRACE("Setting SAMPLE to %d\n", arrayNo);
1247                         This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
1248                         This->declaredArrays = TRUE;
1249                     break;
1250                     default:
1251                     FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1252                     }
1253                 } else if(curOpcode->opcode == D3DSIO_DEF) {
1254                             This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1255                             FIXME("Constant %ld\n", *pToken & 0xFF);
1256                             ++pToken;
1257                             ++pToken;
1258                             ++pToken;
1259                             ++pToken;
1260                             ++pToken;
1261
1262                 } else {
1263                     /* Check to see if and tmp or addressing redisters are used */
1264                     if (curOpcode->num_params > 0) {
1265                         regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1266                         reg = ((*pToken)  & 0x00001FFF);
1267                         if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1268                         if (D3DSPR_TEMP == regtype){
1269                             tmpsUsed[reg] = TRUE;
1270                             if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
1271                         }
1272                         ++pToken;
1273                         for (i = 1; i < curOpcode->num_params; ++i) {
1274                             regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1275                             reg = ((*pToken)  & 0x00001FFF);
1276                             if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1277                             if (D3DSPR_TEMP == regtype){
1278                                 tmpsUsed[reg] = TRUE;
1279                                 if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
1280                             }
1281                             ++pToken;
1282                         }
1283                     }
1284                 }
1285 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1286                 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1287                     FIXME("This shader requires gl shader language support\n");
1288 #if 0
1289                     This->shaderLanguage = GLSHADER_GLSL;
1290 #endif
1291                 }
1292 #endif
1293             }
1294         }
1295     }
1296 #if 1
1297 #define VSHADER_ALWAYS_NUMBERED
1298 #endif
1299
1300 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1301     /* TODO: using numbered arrays for software shaders makes things easier */
1302     This->declaredArrays = TRUE;
1303 #endif
1304
1305     /* named arrays and declared arrays are mutually exclusive */
1306     if (This->declaredArrays) {
1307         This->namedArrays = FALSE;
1308     }
1309     /* TODO: validate
1310         nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1311         nUseTempRegister    <=  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1312     */
1313
1314   /** second pass, now generate */
1315   pToken = pFunction;
1316
1317   if (NULL != pToken) {
1318     while (1) {
1319       tmpLine[0] = 0;
1320       if ((nRemInstr >= 0) && (--nRemInstr == -1))
1321             /* Macro is finished, continue normal path */ 
1322             pToken = pSavedToken;
1323       if (D3DVS_END() == *pToken)
1324             break;
1325
1326       if (vshader_is_version_token(*pToken)) { /** version */
1327         /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1328         int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1329         int numTemps;
1330         int numConstants;
1331
1332         TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1333
1334         /* Each release of vertex shaders has had different numbers of temp registers */
1335         switch (version) {
1336         case 10:
1337         case 11: numTemps=12;
1338                  numConstants=96;/* min(GL_LIMITS(constants),96) */
1339                  strcpy(tmpLine, "!!ARBvp1.0\n");
1340                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1341                  break;
1342         /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1343            TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1344             TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1345         case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1346                  numConstants=96; /* min(GL_LIMITS(constants),256) */
1347                  strcpy(tmpLine, "!!ARBvp1.0\n");
1348                  FIXME("No work done yet to support vs2.0 in hw\n");
1349                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1350                  break;
1351         case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1352                  numConstants=96; /* min(GL_LIMITS(constants),256) */
1353                  strcpy(tmpLine, "!!ARBvp1.0\n");
1354                  FIXME("No work done yet to support vs2.1 in hw\n");
1355                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1356                  break;
1357         case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1358                  numConstants=96;/* min(GL_LIMITS(constants),256) */
1359                  strcpy(tmpLine, "!!ARBvp3.0\n");
1360                  FIXME("No work done yet to support vs3.0 in hw\n");
1361                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1362                  break;
1363         default:
1364                  numTemps=12;/* min(GL_LIMITS(temps),12) */
1365                  numConstants=96;/* min(GL_LIMITS(constants),96) */
1366                  strcpy(tmpLine, "!!ARBvp1.0\n");
1367                  FIXME("Unrecognized vertex shader version %d!\n", version);
1368         }
1369         PNSTRCAT(pgmStr, tmpLine);
1370
1371         ++lineNum;
1372
1373         /* This should be a bitmap so that only temp registers that are used are declared. */
1374         for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1375             if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1376                 sprintf(tmpLine, "TEMP T%ld;\n", i);
1377                 ++lineNum;
1378                 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1379                 PNSTRCAT(pgmStr, tmpLine);
1380
1381             }
1382         }
1383         /* TODO: loop register counts as an address register */
1384         for (i = 0; i < nUseAddressRegister; i++) {
1385             sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1386             ++lineNum;
1387             TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1388                 PNSTRCAT(pgmStr, tmpLine);
1389
1390         }
1391         /* Due to the dynamic constants binding mechanism, we need to declare
1392         * all the constants for relative addressing. */
1393         /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1394         if (GL_VEND(MESA) || GL_VEND(WINE)) {
1395             numConstants = 95;
1396         }
1397         /* FIXME: We should  be counting the number of constants in the first pass and then validating that many are supported
1398                 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1399         */
1400         sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1401         TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1402         PNSTRCAT(pgmStr, tmpLine);
1403
1404         ++lineNum;
1405
1406         ++pToken;
1407         continue;
1408         }
1409         if (vshader_is_comment_token(*pToken)) { /** comment */
1410             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1411             ++pToken;
1412             FIXME("#%s\n", (char*)pToken);
1413             pToken += comment_len;
1414             continue;
1415       }
1416
1417       curOpcode = vshader_program_get_opcode(*pToken);
1418       ++pToken;
1419       if (NULL == curOpcode) {
1420         /* unkown current opcode ... (shouldn't be any!) */
1421         while (*pToken & 0x80000000) {
1422             FIXME("unrecognized opcode: %08lx\n", *pToken);
1423             ++pToken;
1424         }
1425       } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1426             /* if the token isn't supported by this cross compiler then skip it and it's parameters */
1427           
1428             FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1429             pToken += curOpcode->num_params;
1430       } else {
1431         /* Build opcode for GL vertex_program */
1432         switch (curOpcode->opcode) {
1433         case D3DSIO_NOP:
1434             continue;
1435         case D3DSIO_MOV:
1436             /* Address registers must be loaded with the ARL instruction */
1437             if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1438                 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1439                     strcpy(tmpLine, "ARL");
1440                     break;
1441                 } else
1442                 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1443             }
1444             /* fall through */
1445         case D3DSIO_ADD:
1446         case D3DSIO_SUB:
1447         case D3DSIO_MAD:
1448         case D3DSIO_MUL:
1449         case D3DSIO_RCP:
1450         case D3DSIO_RSQ:
1451         case D3DSIO_DP3:
1452         case D3DSIO_DP4:
1453         case D3DSIO_MIN:
1454         case D3DSIO_MAX:
1455         case D3DSIO_SLT:
1456         case D3DSIO_SGE:
1457         case D3DSIO_LIT:
1458         case D3DSIO_DST:
1459         case D3DSIO_FRC:
1460         case D3DSIO_EXPP:
1461         case D3DSIO_LOGP:
1462         case D3DSIO_EXP:
1463         case D3DSIO_LOG:
1464             strcpy(tmpLine, curOpcode->glname);
1465             break;
1466         case D3DSIO_M4x4:
1467         case D3DSIO_M4x3:
1468         case D3DSIO_M3x4:
1469         case D3DSIO_M3x3:
1470         case D3DSIO_M3x2:
1471             /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1472             nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1473             /* Save point to next instruction */
1474             pSavedToken = pToken + 3;
1475             /* Execute expanded macro */
1476             pToken = MacroExpansion;
1477             continue;
1478         /* dcl and def are handeled in the first pass */
1479         case D3DSIO_DCL:
1480             if (This->namedArrays) {
1481                 const char* attribName = "undefined";
1482                 switch(*pToken & 0xFFFF) {
1483                     case D3DDECLUSAGE_POSITION:
1484                     attribName = "vertex.position";
1485                     break;
1486                     case D3DDECLUSAGE_BLENDINDICES:
1487                     /* not supported by openGL */
1488                     attribName = "vertex.blend";
1489                     break;
1490                     case D3DDECLUSAGE_BLENDWEIGHT:
1491                     attribName = "vertex.weight";
1492                     break;
1493                     case D3DDECLUSAGE_NORMAL:
1494                     attribName = "vertex.normal";
1495                     break;
1496                     case D3DDECLUSAGE_PSIZE:
1497                     attribName = "vertex.psize";
1498                     break;
1499                     case D3DDECLUSAGE_COLOR:
1500                     if((*pToken & 0xF0000) >> 16 == 0)  {
1501                         attribName = "vertex.color";
1502                     } else {
1503                         attribName = "vertex.color.secondary";
1504                     }
1505                     break;
1506                     case D3DDECLUSAGE_TEXCOORD:
1507                     {
1508                         char tmpChar[100];
1509                         tmpChar[0] = 0;
1510                         sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1511                         attribName = tmpChar;
1512                         break;
1513                     }
1514                     /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1515                     case D3DDECLUSAGE_TANGENT:
1516                     attribName = "vertex.tangent";
1517                     break;
1518                     case D3DDECLUSAGE_BINORMAL:
1519                     attribName = "vertex.binormal";
1520                     break;
1521                     case D3DDECLUSAGE_TESSFACTOR:
1522                     attribName = "vertex.tessfactor";
1523                     break;
1524                     case D3DDECLUSAGE_POSITIONT:
1525                     attribName = "vertex.possitionT";
1526                     break;
1527                     case D3DDECLUSAGE_FOG:
1528                     attribName = "vertex.fogcoord";
1529                     break;
1530                     case D3DDECLUSAGE_DEPTH:
1531                     attribName = "vertex.depth";
1532                     break;
1533                     case D3DDECLUSAGE_SAMPLE:
1534                     attribName = "vertex.sample";
1535                     break;
1536                     default:
1537                     FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1538                 }
1539                 {
1540                     char tmpChar[80];
1541                     ++pToken;
1542                     sprintf(tmpLine, "ATTRIB ");
1543                     vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1544                     sprintf(tmpChar," = %s", attribName);
1545                     strcat(tmpLine, tmpChar);
1546                     strcat(tmpLine,";\n");
1547                     ++lineNum;
1548                     if (This->namedArrays) {
1549                         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1550                         PNSTRCAT(pgmStr, tmpLine);
1551
1552                     } else {
1553                         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1554                     }
1555                 }
1556             } else {
1557                 /* eat the token so it doesn't generate a warning */
1558                 ++pToken;
1559             }
1560             ++pToken;
1561             continue;
1562         case D3DSIO_DEF:
1563             {
1564             char tmpChar[80];
1565             sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1566             ++pToken;
1567             sprintf(tmpChar,"%f ,", *(float *)pToken);
1568             strcat(tmpLine, tmpChar);
1569             ++pToken;
1570             sprintf(tmpChar,"%f ,", *(float *)pToken);
1571             strcat(tmpLine, tmpChar);
1572             ++pToken;
1573             sprintf(tmpChar,"%f ,", *(float *)pToken);
1574             strcat(tmpLine, tmpChar);
1575             ++pToken;
1576             sprintf(tmpChar,"%f}", *(float *)pToken);
1577             strcat(tmpLine, tmpChar);
1578
1579             strcat(tmpLine,";\n");
1580             ++lineNum;
1581             TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1582             PNSTRCAT(pgmStr, tmpLine);
1583
1584             ++pToken;
1585             continue;
1586             }
1587         default:
1588             if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1589                 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1590             } else {
1591                 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1592             }
1593         }
1594         if (curOpcode->num_params > 0) {
1595             vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1596
1597             ++pToken;
1598             for (i = 1; i < curOpcode->num_params; ++i) {
1599                 strcat(tmpLine, ",");
1600                 vshader_program_add_param(*pToken, 1, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1601                 ++pToken;
1602             }
1603         }
1604         strcat(tmpLine,";\n");
1605         ++lineNum;
1606         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1607         PNSTRCAT(pgmStr, tmpLine);
1608
1609       }
1610     }
1611     strcpy(tmpLine, "END\n"); 
1612     ++lineNum;
1613     TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1614     PNSTRCAT(pgmStr, tmpLine);
1615
1616   }
1617   /* finally null terminate the pgmStr*/
1618   pgmStr[pgmLength] = 0;
1619
1620   /* Check that Vertex Shaders are supported */
1621   if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1622       /*  Create the hw shader */
1623       /* TODO: change to resource.glObjectHandel or something like that */
1624       GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1625       TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1626       GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1627
1628       /* Create the program and check for errors */
1629       GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1630       if (glGetError() == GL_INVALID_OPERATION) {
1631           GLint errPos;
1632           glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1633           FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1634           This->prgId = -1;
1635       }
1636   }
1637 #if 1 /* if were using the data buffer of device then we don't need to free it */
1638   HeapFree(GetProcessHeap(), 0, pgmStr);
1639 #endif
1640 #undef PNSTRCAT
1641 }
1642
1643 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1644   /**
1645    * TODO: use the NV_vertex_program (or 1_1) extension
1646    *  and specifics vendors (ARB_vertex_program??) variants for it
1647    */
1648   return TRUE;
1649 }
1650
1651 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1652     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1653         
1654     /** Vertex Shader Temporary Registers */
1655     WINED3DSHADERVECTOR R[12];
1656       /*D3DSHADERSCALAR A0;*/
1657     WINED3DSHADERVECTOR A[1];
1658     /** temporary Vector for modifier management */
1659     WINED3DSHADERVECTOR d;
1660     WINED3DSHADERVECTOR s[3];
1661     /** parser datas */
1662     const DWORD* pToken = This->function;
1663     const SHADER_OPCODE* curOpcode = NULL;
1664     /** functions parameters */
1665     WINED3DSHADERVECTOR* p[4];
1666     WINED3DSHADERVECTOR* p_send[4];
1667     DWORD i;
1668
1669     /** init temporary register */
1670     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1671
1672     /* vshader_program_parse(vshader); */
1673 #if 0 /* Must not be 1 in cvs */
1674     TRACE("Input:\n");
1675     TRACE_VSVECTOR(This->data->C[0]);
1676     TRACE_VSVECTOR(This->data->C[1]);
1677     TRACE_VSVECTOR(This->data->C[2]);
1678     TRACE_VSVECTOR(This->data->C[3]);
1679     TRACE_VSVECTOR(This->data->C[4]);
1680     TRACE_VSVECTOR(This->data->C[5]);
1681     TRACE_VSVECTOR(This->data->C[6]);
1682     TRACE_VSVECTOR(This->data->C[7]);
1683     TRACE_VSVECTOR(This->data->C[8]);
1684     TRACE_VSVECTOR(This->data->C[64]);
1685     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1686     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1687     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1688     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1689     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1690     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1691     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1692     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1693     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1694 #endif
1695
1696     TRACE_VSVECTOR(vshader->data->C[64]);
1697     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1698
1699     /* the first dword is the version tag */
1700     /* TODO: parse it */
1701
1702     if (vshader_is_version_token(*pToken)) { /** version */
1703         ++pToken;
1704     }
1705     while (D3DVS_END() != *pToken) {
1706         if (vshader_is_comment_token(*pToken)) { /** comment */
1707             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1708             ++pToken;
1709             pToken += comment_len;
1710             continue ;
1711         }
1712         curOpcode = vshader_program_get_opcode(*pToken);
1713         ++pToken;
1714         if (NULL == curOpcode) {
1715             i = 0;
1716             /* unkown current opcode ... */
1717             /* TODO: Think of a name for 0x80000000 and repalce it's use with a constant */
1718             while (*pToken & 0x80000000) {
1719                 if (i == 0) {
1720                     FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1721                 }
1722                 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1723                 vshader_program_dump_param(*pToken, i);
1724                 TRACE("\n");
1725                 ++i;
1726                 ++pToken;
1727             }
1728             /* return FALSE; */
1729         } else {
1730             if (curOpcode->num_params > 0) {
1731                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1732                 for (i = 0; i < curOpcode->num_params; ++i) {
1733                     DWORD reg = pToken[i] & 0x00001FFF;
1734                     DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1735     
1736                     switch (regtype << D3DSP_REGTYPE_SHIFT) {
1737                     case D3DSPR_TEMP:
1738                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1739                         p[i] = &R[reg];
1740                         break;
1741                     case D3DSPR_INPUT:
1742                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1743                         p[i] = &input->V[reg];
1744                         break;
1745                     case D3DSPR_CONST:
1746                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1747                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1748                         } else {
1749                             p[i] = &This->data->C[reg];
1750                         }
1751                         break;
1752                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1753                         if (0 != reg) {
1754                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1755                             reg = 0;
1756                         }
1757                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1758                         p[i] = &A[reg];
1759                         break;
1760                     case D3DSPR_RASTOUT:
1761                         switch (reg) {
1762                         case D3DSRO_POSITION:
1763                             p[i] = &output->oPos;
1764                             break;
1765                         case D3DSRO_FOG:
1766                             p[i] = &output->oFog;
1767                             break;
1768                         case D3DSRO_POINT_SIZE:
1769                             p[i] = &output->oPts;
1770                             break;
1771                         }
1772                         break;
1773                     case D3DSPR_ATTROUT:
1774                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1775                         p[i] = &output->oD[reg];
1776                         break;
1777                     case D3DSPR_TEXCRDOUT:
1778                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1779                         p[i] = &output->oT[reg];
1780                         break;
1781                     /* TODO Decls and defs */
1782 #if 0
1783                     case D3DSPR_DCL:
1784                     case D3DSPR_DEF:
1785 #endif
1786                     default:
1787                         break;
1788                     }
1789
1790                     if (i > 0) { /* input reg */
1791                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1792                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1793
1794                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1795                             /* TRACE("p[%d] not swizzled\n", i); */
1796                             p_send[i] = p[i];
1797                         } else {
1798                             DWORD swizzle_x = swizzle & 0x03;
1799                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1800                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1801                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1802                             /* TRACE("p[%d] swizzled\n", i); */
1803                             float* tt = (float*) p[i];
1804                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1805                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1806                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1807                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1808                             p_send[i] = &s[i];
1809                         }
1810                     } else { /* output reg */
1811                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1812                             p_send[i] = p[i];
1813                         } else {
1814                             p_send[i] = &d; /* to be post-processed for modifiers management */
1815                         }
1816                     }
1817                 }
1818             }
1819
1820             switch (curOpcode->num_params) {
1821             case 0:
1822                 curOpcode->soft_fct();
1823                 break;
1824             case 1:
1825                 curOpcode->soft_fct(p_send[0]);
1826             break;
1827             case 2:
1828                 curOpcode->soft_fct(p_send[0], p_send[1]);
1829                 break;
1830             case 3:
1831                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1832                 break;
1833             case 4:
1834                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1835                 break;
1836             case 5:
1837                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1838                 break;
1839             case 6:
1840                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1841                 break;
1842             default:
1843                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1844             }
1845
1846             /* check if output reg modifier post-process */
1847             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1848                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1849                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1850                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1851                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1852             }
1853 #if 0
1854             TRACE_VSVECTOR(output->oPos);
1855             TRACE_VSVECTOR(output->oD[0]);
1856             TRACE_VSVECTOR(output->oD[1]);
1857             TRACE_VSVECTOR(output->oT[0]);
1858             TRACE_VSVECTOR(output->oT[1]);
1859             TRACE_VSVECTOR(R[0]);
1860             TRACE_VSVECTOR(R[1]);
1861             TRACE_VSVECTOR(R[2]);
1862             TRACE_VSVECTOR(R[3]);
1863             TRACE_VSVECTOR(R[4]);
1864             TRACE_VSVECTOR(R[5]);
1865 #endif
1866
1867             /* to next opcode token */
1868             pToken += curOpcode->num_params;
1869         }
1870 #if 0
1871         TRACE("End of current instruction:\n");
1872         TRACE_VSVECTOR(output->oPos);
1873         TRACE_VSVECTOR(output->oD[0]);
1874         TRACE_VSVECTOR(output->oD[1]);
1875         TRACE_VSVECTOR(output->oT[0]);
1876         TRACE_VSVECTOR(output->oT[1]);
1877         TRACE_VSVECTOR(R[0]);
1878         TRACE_VSVECTOR(R[1]);
1879         TRACE_VSVECTOR(R[2]);
1880         TRACE_VSVECTOR(R[3]);
1881         TRACE_VSVECTOR(R[4]);
1882         TRACE_VSVECTOR(R[5]);
1883 #endif
1884     }
1885 #if 0 /* Must not be 1 in cvs */
1886     TRACE("Output:\n");
1887     TRACE_VSVECTOR(output->oPos);
1888     TRACE_VSVECTOR(output->oD[0]);
1889     TRACE_VSVECTOR(output->oD[1]);
1890     TRACE_VSVECTOR(output->oT[0]);
1891     TRACE_VSVECTOR(output->oT[1]);
1892 #endif
1893     return D3D_OK;
1894 }
1895
1896 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1897     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1898     FIXME("(%p) : stub\n", This);
1899     return D3D_OK;
1900 }
1901
1902 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1903     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1904     FIXME("(%p) : stub\n", This);
1905     return D3D_OK;
1906 }
1907
1908 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1909     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1910     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1911         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1912         return D3DERR_INVALIDCALL;
1913     }
1914     if (NULL == pConstantData) {
1915         return D3DERR_INVALIDCALL;
1916     }
1917     FIXME("(%p) : stub\n", This);
1918     return D3D_OK;
1919 }
1920
1921 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1922     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1923     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1924     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1925         return D3DERR_INVALIDCALL;
1926     }
1927     if (NULL == pConstantData) {
1928         return D3DERR_INVALIDCALL;
1929     }
1930     FIXME("(%p) : stub\n", This);
1931     return D3D_OK;
1932 }
1933
1934 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1935     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1936     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1937         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1938         return D3DERR_INVALIDCALL;
1939     }
1940     if (NULL == pConstantData) {
1941         return D3DERR_INVALIDCALL;
1942     }
1943     FIXME("(%p) : stub\n", This);
1944     return D3D_OK;
1945 }
1946
1947 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1948     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1949     FIXME("(%p) : stub\n", This);
1950     return D3D_OK;
1951 }
1952
1953 #endif
1954
1955 /* *******************************************
1956    IWineD3DVertexShader IUnknown parts follow
1957    ******************************************* */
1958 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1959 {
1960     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1961     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1962     if (IsEqualGUID(riid, &IID_IUnknown) 
1963         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1964         IUnknown_AddRef(iface);
1965         *ppobj = This;
1966         return D3D_OK;
1967     }
1968     return E_NOINTERFACE;
1969 }
1970
1971 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1972     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1973     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1974     return InterlockedIncrement(&This->ref);
1975 }
1976
1977 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1978     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1979     ULONG ref;
1980     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1981     ref = InterlockedDecrement(&This->ref);
1982     if (ref == 0) {
1983         HeapFree(GetProcessHeap(), 0, This);
1984     }
1985     return ref;
1986 }
1987
1988 /* *******************************************
1989    IWineD3DVertexShader IWineD3DVertexShader parts follow
1990    ******************************************* */
1991
1992 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1993     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1994     
1995     *parent = (IUnknown*)This->parent;
1996     IUnknown_AddRef(*parent);
1997     TRACE("(%p) : returning %p\n", This, *parent);
1998     return D3D_OK;
1999 }
2000
2001 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2002     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2003     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2004     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2005     TRACE("(%p) returning %p\n", This, *pDevice);
2006     return D3D_OK;
2007 }
2008
2009 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2010     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2011     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2012
2013     if (NULL == pData) {
2014         *pSizeOfData = This->functionLength;
2015         return D3D_OK;
2016     }
2017     if (*pSizeOfData < This->functionLength) {
2018         *pSizeOfData = This->functionLength;
2019         return D3DERR_MOREDATA;
2020     }
2021     if (NULL == This->function) { /* no function defined */
2022         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2023         (*(DWORD **) pData) = NULL;
2024     } else {
2025         if(This->functionLength == 0){
2026
2027         }
2028         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2029         memcpy(pData, This->function, This->functionLength);
2030     }
2031     return D3D_OK;
2032 }
2033
2034 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2035     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2036     const DWORD* pToken = pFunction;
2037     const SHADER_OPCODE* curOpcode = NULL;
2038     DWORD len = 0;
2039     DWORD i;
2040     TRACE("(%p) : Parsing programme\n", This);
2041
2042     if (NULL != pToken) {
2043         while (D3DVS_END() != *pToken) {
2044             if (vshader_is_version_token(*pToken)) { /** version */
2045                 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2046                 ++pToken;
2047                 ++len;
2048                 continue;
2049             }
2050             if (vshader_is_comment_token(*pToken)) { /** comment */
2051                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2052                 ++pToken;
2053                 TRACE("//%s\n", (char*)pToken);
2054                 pToken += comment_len;
2055                 len += comment_len + 1;
2056                 continue;
2057             }
2058             curOpcode = vshader_program_get_opcode(*pToken);
2059             ++pToken;
2060             ++len;
2061             if (NULL == curOpcode) {
2062                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2063                 while (*pToken & 0x80000000) {
2064                     /* unkown current opcode ... */
2065                     FIXME("unrecognized opcode: %08lx", *pToken);
2066                     ++pToken;
2067                     ++len;
2068                     TRACE("\n");
2069                 }
2070
2071             } else {
2072                 if (curOpcode->opcode == D3DSIO_DCL) {
2073                     TRACE("dcl_");
2074                     switch(*pToken & 0xFFFF) {
2075                         case D3DDECLUSAGE_POSITION:
2076                         TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2077                         break;
2078                         case D3DDECLUSAGE_BLENDINDICES:
2079                         TRACE("%s ", "blend");
2080                         break;
2081                         case D3DDECLUSAGE_BLENDWEIGHT:
2082                         TRACE("%s ", "weight");
2083                         break;
2084                         case D3DDECLUSAGE_NORMAL:
2085                         TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2086                         break;
2087                         case D3DDECLUSAGE_PSIZE:
2088                         TRACE("%s ", "psize");
2089                         break;
2090                         case D3DDECLUSAGE_COLOR:
2091                         if((*pToken & 0xF0000) >> 16 == 0)  {
2092                             TRACE("%s ", "color");
2093                         } else {
2094                             TRACE("%s ", "specular");
2095                         }
2096                         break;
2097                         case D3DDECLUSAGE_TEXCOORD:
2098                         TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2099                         break;
2100                         case D3DDECLUSAGE_TANGENT:
2101                         TRACE("%s ", "tangent");
2102                         break;
2103                         case D3DDECLUSAGE_BINORMAL:
2104                         TRACE("%s ", "binormal");
2105                         break;
2106                         case D3DDECLUSAGE_TESSFACTOR:
2107                         TRACE("%s ", "tessfactor");
2108                         break;
2109                         case D3DDECLUSAGE_POSITIONT:
2110                         TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2111                         break;
2112                         case D3DDECLUSAGE_FOG:
2113                         TRACE("%s ", "fog");
2114                         break;
2115                         case D3DDECLUSAGE_DEPTH:
2116                         TRACE("%s ", "depth");
2117                         break;
2118                         case D3DDECLUSAGE_SAMPLE:
2119                         TRACE("%s ", "sample");
2120                         break;
2121                         default:
2122                         FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2123                     }
2124                     ++pToken;
2125                     ++len;
2126                     vshader_program_dump_vs_param(*pToken, 0);
2127                     ++pToken;
2128                     ++len;
2129                 } else 
2130                     if (curOpcode->opcode == D3DSIO_DEF) {
2131                         TRACE("def c%lu = ", *pToken & 0xFF);
2132                         ++pToken;
2133                         ++len;
2134                         TRACE("%f ,", *(float *)pToken);
2135                         ++pToken;
2136                         ++len;
2137                         TRACE("%f ,", *(float *)pToken);
2138                         ++pToken;
2139                         ++len;
2140                         TRACE("%f ,", *(float *)pToken);
2141                         ++pToken;
2142                         ++len;
2143                         TRACE("%f", *(float *)pToken);
2144                         ++pToken;
2145                         ++len;
2146                 } else {
2147                     TRACE("%s ", curOpcode->name);
2148                     if (curOpcode->num_params > 0) {
2149                         vshader_program_dump_vs_param(*pToken, 0);
2150                         ++pToken;
2151                         ++len;
2152                         for (i = 1; i < curOpcode->num_params; ++i) {
2153                             TRACE(", ");
2154                             vshader_program_dump_vs_param(*pToken, 1);
2155                             ++pToken;
2156                             ++len;
2157                         }
2158                     }
2159                 }
2160                 TRACE("\n");
2161             }
2162         }
2163         This->functionLength = (len + 1) * sizeof(DWORD);
2164     } else {
2165         This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2166     }
2167
2168     /* Generate HW shader in needed */
2169     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
2170 #if 1
2171         IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2172 #endif
2173     }
2174
2175     /* copy the function ... because it will certainly be released by application */
2176     if (NULL != pFunction) {
2177         This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2178         memcpy((void *)This->function, pFunction, This->functionLength);
2179     } else {
2180         This->function = NULL;
2181     }
2182     return D3D_OK;
2183 }
2184
2185 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2186 {
2187     /*** IUnknown methods ***/
2188     IWineD3DVertexShaderImpl_QueryInterface,
2189     IWineD3DVertexShaderImpl_AddRef,
2190     IWineD3DVertexShaderImpl_Release,
2191     /*** IWineD3DVertexShader methods ***/
2192     IWineD3DVertexShaderImpl_GetParent,
2193     IWineD3DVertexShaderImpl_GetDevice,
2194     IWineD3DVertexShaderImpl_GetFunction,
2195     IWineD3DVertexShaderImpl_SetFunction
2196 };