Integrate hardware vertex shaders into the drawing pipeline.
[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", 5, 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                     TRACE("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 addres 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 inuse 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             TRACE("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   /*  Create the hw shader */
1620     /* TODO: change to resource.glObjectHandel or something like that */
1621   GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1622   TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1623
1624   GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1625
1626
1627   /* Create the program and check for errors */
1628   GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1629   if (glGetError() == GL_INVALID_OPERATION) {
1630     GLint errPos;
1631     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1632     FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1633     This->prgId = -1;
1634   }
1635 #if 1 /* if were using the data buffer of device then we don't need to free it */
1636   HeapFree(GetProcessHeap(), 0, pgmStr);
1637 #endif
1638 #undef PNSTRCAT
1639 }
1640
1641 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1642   /**
1643    * TODO: use the NV_vertex_program (or 1_1) extension
1644    *  and specifics vendors (ARB_vertex_program??) variants for it
1645    */
1646   return TRUE;
1647 }
1648
1649 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1650     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1651         
1652     /** Vertex Shader Temporary Registers */
1653     WINED3DSHADERVECTOR R[12];
1654       /*D3DSHADERSCALAR A0;*/
1655     WINED3DSHADERVECTOR A[1];
1656     /** temporary Vector for modifier management */
1657     WINED3DSHADERVECTOR d;
1658     WINED3DSHADERVECTOR s[3];
1659     /** parser datas */
1660     const DWORD* pToken = This->function;
1661     const SHADER_OPCODE* curOpcode = NULL;
1662     /** functions parameters */
1663     WINED3DSHADERVECTOR* p[4];
1664     WINED3DSHADERVECTOR* p_send[4];
1665     DWORD i;
1666
1667     /** init temporary register */
1668     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1669
1670     /* vshader_program_parse(vshader); */
1671 #if 0 /* Must not be 1 in cvs */
1672     TRACE("Input:\n");
1673     TRACE_VSVECTOR(This->data->C[0]);
1674     TRACE_VSVECTOR(This->data->C[1]);
1675     TRACE_VSVECTOR(This->data->C[2]);
1676     TRACE_VSVECTOR(This->data->C[3]);
1677     TRACE_VSVECTOR(This->data->C[4]);
1678     TRACE_VSVECTOR(This->data->C[5]);
1679     TRACE_VSVECTOR(This->data->C[6]);
1680     TRACE_VSVECTOR(This->data->C[7]);
1681     TRACE_VSVECTOR(This->data->C[8]);
1682     TRACE_VSVECTOR(This->data->C[64]);
1683     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1684     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1685     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1686     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1687     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1688     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1689     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1690     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1691     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1692 #endif
1693
1694     TRACE_VSVECTOR(vshader->data->C[64]);
1695     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1696
1697     /* the first dword is the version tag */
1698     /* TODO: parse it */
1699
1700     if (vshader_is_version_token(*pToken)) { /** version */
1701         ++pToken;
1702     }
1703     while (D3DVS_END() != *pToken) {
1704         if (vshader_is_comment_token(*pToken)) { /** comment */
1705             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1706             ++pToken;
1707             pToken += comment_len;
1708             continue ;
1709         }
1710         curOpcode = vshader_program_get_opcode(*pToken);
1711         ++pToken;
1712         if (NULL == curOpcode) {
1713             i = 0;
1714             /* unkown current opcode ... */
1715             /* TODO: Think of a name for 0x80000000 and repalce it's use with a constant */
1716             while (*pToken & 0x80000000) {
1717                 if (i == 0) {
1718                     TRACE("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1719                 }
1720                 TRACE("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1721                 vshader_program_dump_param(*pToken, i);
1722                 TRACE("\n");
1723                 ++i;
1724                 ++pToken;
1725             }
1726             /* return FALSE; */
1727         } else {
1728             if (curOpcode->num_params > 0) {
1729                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1730                 for (i = 0; i < curOpcode->num_params; ++i) {
1731                     DWORD reg = pToken[i] & 0x00001FFF;
1732                     DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1733     
1734                     switch (regtype << D3DSP_REGTYPE_SHIFT) {
1735                     case D3DSPR_TEMP:
1736                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1737                         p[i] = &R[reg];
1738                         break;
1739                     case D3DSPR_INPUT:
1740                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1741                         p[i] = &input->V[reg];
1742                         break;
1743                     case D3DSPR_CONST:
1744                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1745                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1746                         } else {
1747                             p[i] = &This->data->C[reg];
1748                         }
1749                         break;
1750                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1751                         if (0 != reg) {
1752                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1753                             reg = 0;
1754                         }
1755                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1756                         p[i] = &A[reg];
1757                         break;
1758                     case D3DSPR_RASTOUT:
1759                         switch (reg) {
1760                         case D3DSRO_POSITION:
1761                             p[i] = &output->oPos;
1762                             break;
1763                         case D3DSRO_FOG:
1764                             p[i] = &output->oFog;
1765                             break;
1766                         case D3DSRO_POINT_SIZE:
1767                             p[i] = &output->oPts;
1768                             break;
1769                         }
1770                         break;
1771                     case D3DSPR_ATTROUT:
1772                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1773                         p[i] = &output->oD[reg];
1774                         break;
1775                     case D3DSPR_TEXCRDOUT:
1776                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1777                         p[i] = &output->oT[reg];
1778                         break;
1779                     /* TODO Decls and defs */
1780 #if 0
1781                     case D3DSPR_DCL:
1782                     case D3DSPR_DEF:
1783 #endif
1784                     default:
1785                         break;
1786                     }
1787
1788                     if (i > 0) { /* input reg */
1789                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1790                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1791
1792                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1793                             /* TRACE("p[%d] not swizzled\n", i); */
1794                             p_send[i] = p[i];
1795                         } else {
1796                             DWORD swizzle_x = swizzle & 0x03;
1797                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1798                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1799                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1800                             /* TRACE("p[%d] swizzled\n", i); */
1801                             float* tt = (float*) p[i];
1802                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1803                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1804                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1805                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1806                             p_send[i] = &s[i];
1807                         }
1808                     } else { /* output reg */
1809                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1810                             p_send[i] = p[i];
1811                         } else {
1812                             p_send[i] = &d; /* to be post-processed for modifiers management */
1813                         }
1814                     }
1815                 }
1816             }
1817
1818             switch (curOpcode->num_params) {
1819             case 0:
1820                 curOpcode->soft_fct();
1821                 break;
1822             case 1:
1823                 curOpcode->soft_fct(p_send[0]);
1824             break;
1825             case 2:
1826                 curOpcode->soft_fct(p_send[0], p_send[1]);
1827                 break;
1828             case 3:
1829                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1830                 break;
1831             case 4:
1832                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1833                 break;
1834             case 5:
1835                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1836                 break;
1837             case 6:
1838                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1839                 break;
1840             default:
1841                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1842             }
1843
1844             /* check if output reg modifier post-process */
1845             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1846                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1847                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1848                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1849                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1850             }
1851 #if 0
1852             TRACE_VSVECTOR(output->oPos);
1853             TRACE_VSVECTOR(output->oD[0]);
1854             TRACE_VSVECTOR(output->oD[1]);
1855             TRACE_VSVECTOR(output->oT[0]);
1856             TRACE_VSVECTOR(output->oT[1]);
1857             TRACE_VSVECTOR(R[0]);
1858             TRACE_VSVECTOR(R[1]);
1859             TRACE_VSVECTOR(R[2]);
1860             TRACE_VSVECTOR(R[3]);
1861             TRACE_VSVECTOR(R[4]);
1862             TRACE_VSVECTOR(R[5]);
1863 #endif
1864
1865             /* to next opcode token */
1866             pToken += curOpcode->num_params;
1867         }
1868 #if 0
1869         TRACE("End of current instruction:\n");
1870         TRACE_VSVECTOR(output->oPos);
1871         TRACE_VSVECTOR(output->oD[0]);
1872         TRACE_VSVECTOR(output->oD[1]);
1873         TRACE_VSVECTOR(output->oT[0]);
1874         TRACE_VSVECTOR(output->oT[1]);
1875         TRACE_VSVECTOR(R[0]);
1876         TRACE_VSVECTOR(R[1]);
1877         TRACE_VSVECTOR(R[2]);
1878         TRACE_VSVECTOR(R[3]);
1879         TRACE_VSVECTOR(R[4]);
1880         TRACE_VSVECTOR(R[5]);
1881 #endif
1882     }
1883 #if 0 /* Must not be 1 in cvs */
1884     TRACE("Output:\n");
1885     TRACE_VSVECTOR(output->oPos);
1886     TRACE_VSVECTOR(output->oD[0]);
1887     TRACE_VSVECTOR(output->oD[1]);
1888     TRACE_VSVECTOR(output->oT[0]);
1889     TRACE_VSVECTOR(output->oT[1]);
1890 #endif
1891     return D3D_OK;
1892 }
1893
1894 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1895     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1896     FIXME("(%p) : stub\n", This);
1897     return D3D_OK;
1898 }
1899
1900 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1901     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1902     FIXME("(%p) : stub\n", This);
1903     return D3D_OK;
1904 }
1905
1906 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1907     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1908     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1909         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1910         return D3DERR_INVALIDCALL;
1911     }
1912     if (NULL == pConstantData) {
1913         return D3DERR_INVALIDCALL;
1914     }
1915     FIXME("(%p) : stub\n", This);
1916     return D3D_OK;
1917 }
1918
1919 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1920     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1921     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1922     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1923         return D3DERR_INVALIDCALL;
1924     }
1925     if (NULL == pConstantData) {
1926         return D3DERR_INVALIDCALL;
1927     }
1928     FIXME("(%p) : stub\n", This);
1929     return D3D_OK;
1930 }
1931
1932 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1933     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1934     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1935         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1936         return D3DERR_INVALIDCALL;
1937     }
1938     if (NULL == pConstantData) {
1939         return D3DERR_INVALIDCALL;
1940     }
1941     FIXME("(%p) : stub\n", This);
1942     return D3D_OK;
1943 }
1944
1945 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1946     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1947     FIXME("(%p) : stub\n", This);
1948     return D3D_OK;
1949 }
1950
1951 #endif
1952
1953 /* *******************************************
1954    IWineD3DVertexShader IUnknown parts follow
1955    ******************************************* */
1956 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1957 {
1958     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1959     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1960     if (IsEqualGUID(riid, &IID_IUnknown) 
1961         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1962         IUnknown_AddRef(iface);
1963         *ppobj = This;
1964         return D3D_OK;
1965     }
1966     return E_NOINTERFACE;
1967 }
1968
1969 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1970     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1971     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1972     return InterlockedIncrement(&This->ref);
1973 }
1974
1975 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1976     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1977     ULONG ref;
1978     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1979     ref = InterlockedDecrement(&This->ref);
1980     if (ref == 0) {
1981         HeapFree(GetProcessHeap(), 0, This);
1982     }
1983     return ref;
1984 }
1985
1986 /* *******************************************
1987    IWineD3DVertexShader IWineD3DVertexShader parts follow
1988    ******************************************* */
1989
1990 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1991     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1992     
1993     *parent = (IUnknown*)This->parent;
1994     IUnknown_AddRef(*parent);
1995     TRACE("(%p) : returning %p\n", This, *parent);
1996     return D3D_OK;
1997 }
1998
1999 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2000     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2001     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2002     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2003     TRACE("(%p) returning %p\n", This, *pDevice);
2004     return D3D_OK;
2005 }
2006
2007 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2008     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2009     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2010
2011     if (NULL == pData) {
2012         *pSizeOfData = This->functionLength;
2013         return D3D_OK;
2014     }
2015     if (*pSizeOfData < This->functionLength) {
2016         *pSizeOfData = This->functionLength;
2017         return D3DERR_MOREDATA;
2018     }
2019     if (NULL == This->function) { /* no function defined */
2020         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2021         (*(DWORD **) pData) = NULL;
2022     } else {
2023         if(This->functionLength == 0){
2024
2025         }
2026         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2027         memcpy(pData, This->function, This->functionLength);
2028     }
2029     return D3D_OK;
2030 }
2031
2032 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2033     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2034     const DWORD* pToken = pFunction;
2035     const SHADER_OPCODE* curOpcode = NULL;
2036     DWORD len = 0;
2037     DWORD i;
2038     TRACE("(%p) : Parsing programme\n", This);
2039
2040     if (NULL != pToken) {
2041         while (D3DVS_END() != *pToken) {
2042             if (vshader_is_version_token(*pToken)) { /** version */
2043                 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2044                 ++pToken;
2045                 ++len;
2046                 continue;
2047             }
2048             if (vshader_is_comment_token(*pToken)) { /** comment */
2049                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2050                 ++pToken;
2051                 TRACE("//%s\n", (char*)pToken);
2052                 pToken += comment_len;
2053                 len += comment_len + 1;
2054                 continue;
2055             }
2056             curOpcode = vshader_program_get_opcode(*pToken);
2057             ++pToken;
2058             ++len;
2059             if (NULL == curOpcode) {
2060                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2061                 while (*pToken & 0x80000000) {
2062                     /* unkown current opcode ... */
2063                         TRACE("unrecognized opcode: %08lx", *pToken);
2064                     ++pToken;
2065                     ++len;
2066                     TRACE("\n");
2067                 }
2068
2069             } else {
2070                 if (curOpcode->opcode == D3DSIO_DCL) {
2071                     TRACE("dcl_");
2072                     switch(*pToken & 0xFFFF) {
2073                         case D3DDECLUSAGE_POSITION:
2074                         TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2075                         break;
2076                         case D3DDECLUSAGE_BLENDINDICES:
2077                         TRACE("%s ", "blend");
2078                         break;
2079                         case D3DDECLUSAGE_BLENDWEIGHT:
2080                         TRACE("%s ", "weight");
2081                         break;
2082                         case D3DDECLUSAGE_NORMAL:
2083                         TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2084                         break;
2085                         case D3DDECLUSAGE_PSIZE:
2086                         TRACE("%s ", "psize");
2087                         break;
2088                         case D3DDECLUSAGE_COLOR:
2089                         if((*pToken & 0xF0000) >> 16 == 0)  {
2090                             TRACE("%s ", "color");
2091                         } else {
2092                             TRACE("%s ", "specular");
2093                         }
2094                         break;
2095                         case D3DDECLUSAGE_TEXCOORD:
2096                         TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2097                         break;
2098                         case D3DDECLUSAGE_TANGENT:
2099                         TRACE("%s ", "tangent");
2100                         break;
2101                         case D3DDECLUSAGE_BINORMAL:
2102                         TRACE("%s ", "binormal");
2103                         break;
2104                         case D3DDECLUSAGE_TESSFACTOR:
2105                         TRACE("%s ", "tessfactor");
2106                         break;
2107                         case D3DDECLUSAGE_POSITIONT:
2108                         TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2109                         break;
2110                         case D3DDECLUSAGE_FOG:
2111                         TRACE("%s ", "fog");
2112                         break;
2113                         case D3DDECLUSAGE_DEPTH:
2114                         TRACE("%s ", "depth");
2115                         break;
2116                         case D3DDECLUSAGE_SAMPLE:
2117                         TRACE("%s ", "sample");
2118                         break;
2119                         default:
2120                         FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2121                     }
2122                     ++pToken;
2123                     ++len;
2124                     vshader_program_dump_vs_param(*pToken, 0);
2125                     ++pToken;
2126                     ++len;
2127                 } else 
2128                     if (curOpcode->opcode == D3DSIO_DEF) {
2129                         TRACE("def c%lu = ", *pToken & 0xFF);
2130                         ++pToken;
2131                         ++len;
2132                         TRACE("%f ,", *(float *)pToken);
2133                         ++pToken;
2134                         ++len;
2135                         TRACE("%f ,", *(float *)pToken);
2136                         ++pToken;
2137                         ++len;
2138                         TRACE("%f ,", *(float *)pToken);
2139                         ++pToken;
2140                         ++len;
2141                         TRACE("%f", *(float *)pToken);
2142                         ++pToken;
2143                         ++len;
2144                 } else {
2145                     TRACE("%s ", curOpcode->name);
2146                     if (curOpcode->num_params > 0) {
2147                         vshader_program_dump_vs_param(*pToken, 0);
2148                         ++pToken;
2149                         ++len;
2150                         for (i = 1; i < curOpcode->num_params; ++i) {
2151                             TRACE(", ");
2152                             vshader_program_dump_vs_param(*pToken, 1);
2153                             ++pToken;
2154                             ++len;
2155                         }
2156                     }
2157                 }
2158                 TRACE("\n");
2159             }
2160         }
2161         This->functionLength = (len + 1) * sizeof(DWORD);
2162     } else {
2163         This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2164     }
2165
2166     /* Generate HW shader in needed */
2167     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
2168 #if 1
2169         IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2170 #endif
2171     }
2172
2173     /* copy the function ... because it will certainly be released by application */
2174     if (NULL != pFunction) {
2175         This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2176         memcpy((void *)This->function, pFunction, This->functionLength);
2177     } else {
2178         This->function = NULL;
2179     }
2180     return D3D_OK;
2181 }
2182
2183 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2184 {
2185     /*** IUnknown methods ***/
2186     IWineD3DVertexShaderImpl_QueryInterface,
2187     IWineD3DVertexShaderImpl_AddRef,
2188     IWineD3DVertexShaderImpl_Release,
2189     /*** IWineD3DVertexShader methods ***/
2190     IWineD3DVertexShaderImpl_GetParent,
2191     IWineD3DVertexShaderImpl_GetDevice,
2192     IWineD3DVertexShaderImpl_GetFunction,
2193     IWineD3DVertexShaderImpl_SetFunction
2194 };