wined3d: LRP is not a valid ARBvp code.
[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  * Copyright 2006 Ivan Gyurdiev
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25
26 #include <math.h>
27 #include <stdio.h>
28
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
32
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34
35 /* Shader debugging - Change the following line to enable debugging of software
36       vertex shaders                                                             */
37 #if 0 /* Musxt not be 1 in cvs version */
38 # define VSTRACE(A) TRACE A
39 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
40 #else
41 # define VSTRACE(A)
42 # define TRACE_VSVECTOR(name)
43 #endif
44
45 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
46
47 /**
48  * DirectX9 SDK download
49  *  http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
50  *
51  * Exploring D3DX
52  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
53  *
54  * Using Vertex Shaders
55  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
56  *
57  * Dx9 New
58  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
59  *
60  * Dx9 Shaders
61  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
62  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
63  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
64  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
65  *
66  * Dx9 D3DX
67  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
68  *
69  * FVF
70  *  http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
71  *
72  * NVIDIA: DX8 Vertex Shader to NV Vertex Program
73  *  http://developer.nvidia.com/view.asp?IO=vstovp
74  *
75  * NVIDIA: Memory Management with VAR
76  *  http://developer.nvidia.com/view.asp?IO=var_memory_management
77  */
78
79 /* 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
80 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 */
81
82 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
83
84 /*******************************
85  * vshader functions software VM
86  */
87
88 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
89   d->x = s0->x + s1->x;
90   d->y = s0->y + s1->y;
91   d->z = s0->z + s1->z;
92   d->w = s0->w + s1->w;
93   VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
94                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
95 }
96
97 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
98   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
99   VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
100                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
101 }
102
103 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
104   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
105   VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
106           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
107 }
108
109 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
110   d->x = 1.0f;
111   d->y = s0->y * s1->y;
112   d->z = s0->z;
113   d->w = s1->w;
114   VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
115           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
116 }
117
118 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
119   union {
120     float f;
121     DWORD d;
122   } tmp;
123
124   tmp.f = floorf(s0->w);
125   d->x  = powf(2.0f, tmp.f);
126   d->y  = s0->w - tmp.f;
127   tmp.f = powf(2.0f, s0->w);
128   tmp.d &= 0xFFFFFF00U;
129   d->z  = tmp.f;
130   d->w  = 1.0f;
131   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
132                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
133 }
134
135 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
136   d->x = 1.0f;
137   d->y = (0.0f < s0->x) ? s0->x : 0.0f;
138   d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
139   d->w = 1.0f;
140   VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
141                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
142 }
143
144 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
145   float tmp_f = fabsf(s0->w);
146   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
147   VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
148                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
149 }
150
151 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
152   d->x = s0->x * s1->x + s2->x;
153   d->y = s0->y * s1->y + s2->y;
154   d->z = s0->z * s1->z + s2->z;
155   d->w = s0->w * s1->w + s2->w;
156   VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
157           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));
158 }
159
160 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
161   d->x = (s0->x >= s1->x) ? s0->x : s1->x;
162   d->y = (s0->y >= s1->y) ? s0->y : s1->y;
163   d->z = (s0->z >= s1->z) ? s0->z : s1->z;
164   d->w = (s0->w >= s1->w) ? s0->w : s1->w;
165   VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
166           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
167 }
168
169 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
170   d->x = (s0->x < s1->x) ? s0->x : s1->x;
171   d->y = (s0->y < s1->y) ? s0->y : s1->y;
172   d->z = (s0->z < s1->z) ? s0->z : s1->z;
173   d->w = (s0->w < s1->w) ? s0->w : s1->w;
174   VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
175           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
176 }
177
178 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
179   d->x = s0->x;
180   d->y = s0->y;
181   d->z = s0->z;
182   d->w = s0->w;
183   VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
184           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
185 }
186
187 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
188   d->x = s0->x * s1->x;
189   d->y = s0->y * s1->y;
190   d->z = s0->z * s1->z;
191   d->w = s0->w * s1->w;
192   VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
193           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
194 }
195
196 void vshader_nop(void) {
197     /* NOPPPP ahhh too easy ;) */
198     VSTRACE(("executing nop\n"));
199 }
200
201 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
202   d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
203   VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
205 }
206
207 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
208   float tmp_f = fabsf(s0->w);
209   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);
210   VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
211           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
212 }
213
214 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
215   d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
216   d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
217   d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
218   d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
219   VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
220           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
221 }
222
223 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
224   d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
225   d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
226   d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
227   d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
228   VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
229           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
230 }
231
232 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
233   d->x = s0->x - s1->x;
234   d->y = s0->y - s1->y;
235   d->z = s0->z - s1->z;
236   d->w = s0->w - s1->w;
237   VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
238           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
239 }
240
241 /**
242  * Version 1.1 specific
243  */
244
245 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
246   d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
247   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
248           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
249 }
250
251 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
252   float tmp_f = fabsf(s0->w);
253   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
254   VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
255           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
256 }
257
258 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
259   d->x = s0->x - floorf(s0->x);
260   d->y = s0->y - floorf(s0->y);
261   d->z = 0.0f;
262   d->w = 1.0f;
263   VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
264           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
265 }
266
267 typedef FLOAT D3DMATRIX44[4][4];
268 typedef FLOAT D3DMATRIX43[4][3];
269 typedef FLOAT D3DMATRIX34[3][4];
270 typedef FLOAT D3DMATRIX33[3][3];
271 typedef FLOAT D3DMATRIX23[2][3];
272
273 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
274   /*
275    * Buggy CODE: here only if cast not work for copy/paste
276   WINED3DSHADERVECTOR* mat2 = mat1 + 1;
277   WINED3DSHADERVECTOR* mat3 = mat1 + 2;
278   WINED3DSHADERVECTOR* mat4 = mat1 + 3;
279   d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
280   d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
281   d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
282   d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
283   */
284   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
285   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
286   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
287   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
288   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));
289   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));
290   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));
291   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));
292 }
293
294 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
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 = 1.0f;
299   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));
300   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));
301   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));
302   VSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
303 }
304
305 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
307   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
308   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
309   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
310   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));
311   VSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
312   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));
313   VSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
314 }
315
316 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
317   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318   d->y = mat[1][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 = 1.0f;
321   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));
322   VSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323   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));
324   VSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
325 }
326
327 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
328   FIXME("check\n");
329   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
330   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
331   d->z = 0.0f;
332   d->w = 1.0f;
333 }
334
335 /**
336  * Version 2.0 specific
337  */
338 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
339   d->x = s0->x * (s1->x - s2->x) + s2->x;
340   d->y = s0->y * (s1->y - s2->y) + s2->y;
341   d->z = s0->z * (s1->z - s2->z) + s2->z;
342   d->w = s0->w * (s1->w - s2->w) + s2->w;
343 }
344
345 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
346   d->x = s0->y * s1->z - s0->z * s1->y;
347   d->y = s0->z * s1->x - s0->x * s1->z;
348   d->z = s0->x * s1->y - s0->y * s1->x;
349   d->w = 0.9f; /* w is undefined, so set it to something safeish */
350
351   VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
352              s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
353 }
354
355 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
356
357   d->x = fabsf(s0->x);
358   d->y = fabsf(s0->y);
359   d->z = fabsf(s0->z);
360   d->w = fabsf(s0->w);
361   VSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
362              s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
363 }
364
365     /* Stubs */
366
367 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
368 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
369     FIXME(" : Stub\n");
370 }
371
372 void vshader_call(WINED3DSHADERVECTOR* d) {
373     FIXME(" : Stub\n");
374 }
375
376 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
377     FIXME(" : Stub\n");
378 }
379
380 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
381     FIXME(" : Stub\n");
382 }
383
384 void vshader_ret(void) {
385     FIXME(" : Stub\n");
386 }
387
388 void vshader_endloop(void) {
389     FIXME(" : Stub\n");
390 }
391
392 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393     FIXME(" : Stub\n");
394 }
395
396 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
397     FIXME(" : Stub\n");
398 }
399
400 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401     FIXME(" : Stub\n");
402 }
403
404 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405     FIXME(" : Stub\n");
406 }
407
408 void vshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409     FIXME(" : Stub\n");
410 }
411
412 void vshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
413      FIXME(" : Stub\n");
414 }
415
416 void vshader_rep(WINED3DSHADERVECTOR* d) {
417     FIXME(" : Stub\n");
418 }
419
420 void vshader_endrep(void) {
421     FIXME(" : Stub\n");
422 }
423
424 void vshader_if(WINED3DSHADERVECTOR* d) {
425     FIXME(" : Stub\n");
426 }
427
428 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
429     FIXME(" : Stub\n");
430 }
431
432 void vshader_else(void) {
433     FIXME(" : Stub\n");
434 }
435
436 void vshader_label(WINED3DSHADERVECTOR* d) {
437     FIXME(" : Stub\n");
438 }
439
440 void vshader_endif(void) {
441     FIXME(" : Stub\n");
442 }
443
444 void vshader_break(void) {
445     FIXME(" : Stub\n");
446 }
447
448 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449     FIXME(" : Stub\n");
450 }
451
452 void vshader_breakp(WINED3DSHADERVECTOR* d) {
453     FIXME(" : Stub\n");
454 }
455
456 void vshader_mova(WINED3DSHADERVECTOR* d) {
457     FIXME(" : Stub\n");
458 }
459
460 void vshader_defb(WINED3DSHADERVECTOR* d) {
461     FIXME(" : Stub\n");
462 }
463
464 void vshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
465     FIXME(" : Stub\n");
466 }
467
468 void vshader_texldd(WINED3DSHADERVECTOR* d) {
469     FIXME(" : Stub\n");
470 }
471
472 void vshader_setp(WINED3DSHADERVECTOR* d) {
473     FIXME(" : Stub\n");
474 }
475
476 void vshader_texldl(WINED3DSHADERVECTOR* d) {
477     FIXME(" : Stub\n");
478 }
479
480 /* Prototype */
481 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
482 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
483 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
484 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
485
486 /**
487  * log, exp, frc, m*x* seems to be macros ins ... to see
488  */
489 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
490
491     /* Arithmetic */ 
492     {D3DSIO_NOP,  "nop",  "NOP", 0, vshader_nop,  vshader_hw_map2gl, NULL, 0, 0},
493     {D3DSIO_MOV,  "mov",  "MOV", 2, vshader_mov,  vshader_hw_map2gl, NULL, 0, 0},
494     {D3DSIO_ADD,  "add",  "ADD", 3, vshader_add,  vshader_hw_map2gl, NULL, 0, 0},
495     {D3DSIO_SUB,  "sub",  "SUB", 3, vshader_sub,  vshader_hw_map2gl, NULL, 0, 0},
496     {D3DSIO_MAD,  "mad",  "MAD", 4, vshader_mad,  vshader_hw_map2gl, NULL, 0, 0},
497     {D3DSIO_MUL,  "mul",  "MUL", 3, vshader_mul,  vshader_hw_map2gl, NULL, 0, 0},
498     {D3DSIO_RCP,  "rcp",  "RCP", 2, vshader_rcp,  vshader_hw_map2gl, NULL, 0, 0},
499     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, vshader_rsq,  vshader_hw_map2gl, NULL, 0, 0},
500     {D3DSIO_DP3,  "dp3",  "DP3", 3, vshader_dp3,  vshader_hw_map2gl, NULL, 0, 0},
501     {D3DSIO_DP4,  "dp4",  "DP4", 3, vshader_dp4,  vshader_hw_map2gl, NULL, 0, 0},
502     {D3DSIO_MIN,  "min",  "MIN", 3, vshader_min,  vshader_hw_map2gl, NULL, 0, 0},
503     {D3DSIO_MAX,  "max",  "MAX", 3, vshader_max,  vshader_hw_map2gl, NULL, 0, 0},
504     {D3DSIO_SLT,  "slt",  "SLT", 3, vshader_slt,  vshader_hw_map2gl, NULL, 0, 0},
505     {D3DSIO_SGE,  "sge",  "SGE", 3, vshader_sge,  vshader_hw_map2gl, NULL, 0, 0},
506     {D3DSIO_ABS,  "abs",  "ABS", 2, vshader_abs,  vshader_hw_map2gl, NULL, 0, 0},
507     {D3DSIO_EXP,  "exp",  "EX2", 2, vshader_exp,  vshader_hw_map2gl, NULL, 0, 0},
508     {D3DSIO_LOG,  "log",  "LG2", 2, vshader_log,  vshader_hw_map2gl, NULL, 0, 0},
509     {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
510     {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
511     {D3DSIO_LIT,  "lit",  "LIT", 2, vshader_lit,  vshader_hw_map2gl, NULL, 0, 0},
512     {D3DSIO_DST,  "dst",  "DST", 3, vshader_dst,  vshader_hw_map2gl, NULL, 0, 0},
513     {D3DSIO_LRP,  "lrp",  "LRP", 4, vshader_lrp,  NULL,              NULL, 0, 0},
514     {D3DSIO_FRC,  "frc",  "FRC", 2, vshader_frc,  vshader_hw_map2gl, NULL, 0, 0},
515     {D3DSIO_POW,  "pow",  "POW", 3, vshader_pow,  NULL, NULL, 0, 0},
516     {D3DSIO_CRS,  "crs",  "XPS", 3, vshader_crs,  NULL, NULL, 0, 0},
517     /* TODO: sng can possibly be performed a  s
518         RCP tmp, vec
519         MUL out, tmp, vec*/
520     {D3DSIO_SGN,  "sng",  NULL,  2, vshader_sng,  NULL,   NULL, 0, 0},
521     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
522         DP3 tmp , vec, vec;
523         RSQ tmp, tmp.x;
524         MUL vec.xyz, vec, tmp;
525     but I think this is better because it accounts for w properly.
526         DP3 tmp , vec, vec;
527         RSQ tmp, tmp.x;
528         MUL vec, vec, tmp;
529
530     */
531     {D3DSIO_NRM,      "nrm",      NULL,   2, vshader_nrm,    NULL, NULL, 0, 0},
532     {D3DSIO_SINCOS,   "sincos",   NULL,   4, vshader_sincos2, NULL, NULL, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
533     {D3DSIO_SINCOS,   "sincos",   NULL,   2, vshader_sincos3, NULL, NULL, D3DVS_VERSION(3,0), -1},
534
535     /* Matrix */
536     {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
537     {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
538     {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
539     {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
540     {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
541
542     /* Declare registers */
543     {D3DSIO_DCL,      "dcl",      NULL,                  2, vshader_dcl,     vshader_hw_dcl, NULL, 0, 0},
544
545     /* Constant definitions */
546     {D3DSIO_DEF,      "def",      NULL,                  5, vshader_def,     vshader_hw_def, NULL, 0, 0},
547     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, vshader_defb,    NULL, NULL, 0, 0},
548     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   5, vshader_defi,    NULL, NULL, 0, 0},
549
550     /* Flow control - requires GLSL or software shaders */
551     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   1, vshader_rep,     NULL, NULL, 0, 0},
552     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, vshader_endrep,  NULL, NULL, 0, 0},
553     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   1, vshader_if,      NULL, NULL, 0, 0},
554     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, vshader_ifc,     NULL, NULL, 0, 0},
555     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   0, vshader_else,    NULL, NULL, 0, 0},
556     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   0, vshader_endif,   NULL, NULL, 0, 0},
557     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   0, vshader_break,   NULL, NULL, 0, 0},
558     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, vshader_breakc,  NULL, NULL, 0, 0},
559     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   1, vshader_breakp,  NULL, NULL, 0, 0},
560     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, vshader_call,    NULL, NULL, 0, 0},
561     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, vshader_callnz,  NULL, NULL, 0, 0},
562     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, vshader_loop,    NULL, NULL, 0, 0},
563     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, vshader_ret,     NULL, NULL, 0, 0},
564     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, vshader_endloop, NULL, NULL, 0, 0},
565     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, vshader_label,   NULL, NULL, 0, 0},
566
567     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, vshader_mova,    NULL, NULL, 0, 0},
568     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, vshader_setp,    NULL, NULL, 0, 0},
569     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, vshader_texldl,  NULL, NULL, 0, 0},
570     {0,               NULL,       NULL,   0, NULL,            NULL, 0, 0}
571 };
572
573 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
574     /** operand output */
575     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
576       strcat(hwLine, ".");
577       if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
578       if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
579       if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
580       if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
581     }  
582 }
583
584 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
585     static const char swizzle_reg_chars_color_fix[] = "zyxw";
586     static const char swizzle_reg_chars[] = "xyzw";
587     const char* swizzle_regs = NULL;
588     char  tmpReg[255];
589
590     /** operand input */
591     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
592     DWORD swizzle_x = swizzle & 0x03;
593     DWORD swizzle_y = (swizzle >> 2) & 0x03;
594     DWORD swizzle_z = (swizzle >> 4) & 0x03;
595     DWORD swizzle_w = (swizzle >> 6) & 0x03;
596
597     if (is_color) {
598       swizzle_regs = swizzle_reg_chars_color_fix;
599     } else {
600       swizzle_regs = swizzle_reg_chars;
601     }
602
603     /**
604      * swizzle bits fields:
605      *  WWZZYYXX
606      */
607     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
608       if (is_color) {
609         sprintf(tmpReg, ".%c%c%c%c",
610                 swizzle_regs[swizzle_x],
611                 swizzle_regs[swizzle_y],
612                 swizzle_regs[swizzle_z],
613                 swizzle_regs[swizzle_w]);
614         strcat(hwLine, tmpReg);
615       }
616       return ;
617     }
618     if (swizzle_x == swizzle_y &&
619         swizzle_x == swizzle_z &&
620         swizzle_x == swizzle_w)
621     {
622       sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
623       strcat(hwLine, tmpReg);
624     } else {
625       sprintf(tmpReg, ".%c%c%c%c",
626               swizzle_regs[swizzle_x],
627               swizzle_regs[swizzle_y],
628               swizzle_regs[swizzle_z],
629               swizzle_regs[swizzle_w]);
630       strcat(hwLine, tmpReg);
631     }
632 }
633
634 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
635   /* oPos, oFog and oPts in D3D */
636   static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
637
638   DWORD reg = param & D3DSP_REGNUM_MASK;
639   DWORD regtype = shader_get_regtype(param);
640   char  tmpReg[255];
641   BOOL is_color = FALSE;
642
643   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
644       strcat(hwLine, " -");
645   } else {
646       strcat(hwLine, " ");
647   }
648
649   switch (regtype) {
650   case D3DSPR_TEMP:
651     sprintf(tmpReg, "R%lu", reg);
652     strcat(hwLine, tmpReg);
653     break;
654   case D3DSPR_INPUT:
655     if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
656         || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
657         is_color = TRUE;
658     }
659     /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
660     if (This->namedArrays) {
661         sprintf(tmpReg, "namedVertex%lu", reg);
662     } else {
663     /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
664         sprintf(tmpReg, "vertex.attrib[%lu]", reg);
665     }
666     strcat(hwLine, tmpReg);
667     break;
668   case D3DSPR_CONST:
669     /* FIXME: some constants are named so we need a constants map*/
670     if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
671         if (param & D3DVS_ADDRMODE_RELATIVE) {
672             FIXME("Relative addressing not expected for a named constant %lu\n", reg);
673         }
674         sprintf(tmpReg, "const%lu", reg);
675     } else {
676         sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
677     }
678     strcat(hwLine, tmpReg);
679     break;
680   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
681     sprintf(tmpReg, "A%lu", reg);
682     strcat(hwLine, tmpReg);
683     break;
684   case D3DSPR_RASTOUT:
685     sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
686     strcat(hwLine, tmpReg);
687     break;
688   case D3DSPR_ATTROUT:
689     if (reg==0) {
690        strcat(hwLine, "result.color.primary");
691     } else {
692        strcat(hwLine, "result.color.secondary");
693     }
694     break;
695   case D3DSPR_TEXCRDOUT:
696     sprintf(tmpReg, "result.texcoord[%lu]", reg);
697     strcat(hwLine, tmpReg);
698     break;
699   default:
700     FIXME("Unknown reg type %ld %ld\n", regtype, reg);
701     strcat(hwLine, "unrecognized_register");
702     break;
703   }
704
705   if (!is_input) {
706     vshader_program_add_output_param_swizzle(param, is_color, hwLine);
707   } else {
708     vshader_program_add_input_param_swizzle(param, is_color, hwLine);
709   }
710 }
711
712 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
713 {
714     switch(usage & 0xFFFF) {
715         case D3DDECLUSAGE_POSITION:
716             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
717                 TRACE("Setting position to %d\n", arrayNo);
718                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
719                 This->namedArrays = TRUE;
720             } else {
721                 /* TODO: position indexes go from 0-8!!*/
722                 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
723                 /* robots uses positions up to 8, the position arrays are just packed.*/
724                 if ((usage & 0xF0000) >> 16 > 1) {
725                     TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
726                 }
727                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
728                 This->declaredArrays = TRUE;
729             }
730         break;
731         case D3DDECLUSAGE_BLENDINDICES:
732             /* not supported by openGL */
733             TRACE("Setting BLENDINDICES to %d\n", arrayNo);
734             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
735             This->declaredArrays = TRUE;
736             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
737         break;
738         case D3DDECLUSAGE_BLENDWEIGHT:
739             TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
740             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
741             This->namedArrays = TRUE;
742             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
743         break;
744         case D3DDECLUSAGE_NORMAL:
745             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
746                 TRACE("Setting normal to %d\n", arrayNo);
747                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
748                 This->namedArrays = TRUE;
749             } else {
750                 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
751                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
752                 This->declaredArrays = TRUE;
753             }
754         break;
755         case D3DDECLUSAGE_PSIZE:
756             TRACE("Setting PSIZE to %d\n", arrayNo);
757             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
758             This->namedArrays = TRUE;
759             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
760         break;
761         case D3DDECLUSAGE_COLOR:
762             if((usage & 0xF0000) >> 16 == 0)  {
763                 TRACE("Setting DIFFUSE to %d\n", arrayNo);
764                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
765                 This->namedArrays = TRUE;
766             } else {
767                 TRACE("Setting SPECULAR to %d\n", arrayNo);
768                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
769                 This->namedArrays = TRUE;
770             }
771         break;
772         case D3DDECLUSAGE_TEXCOORD:
773             This->namedArrays = TRUE;
774             /* only 7 texture coords have been designed for, so run a quick sanity check */
775             if ((usage & 0xF0000) >> 16 > 7) {
776                 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
777             } else {
778                 TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
779                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
780             }
781         break;
782         /* The following aren't supported by openGL,
783             if we get them then everything needs to be mapped to numbered attributes instead of named ones.
784             this should be caught in the first pass */
785         case D3DDECLUSAGE_TANGENT:
786             TRACE("Setting TANGENT to %d\n", arrayNo);
787             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
788             This->declaredArrays = TRUE;
789         break;
790         case D3DDECLUSAGE_BINORMAL:
791             TRACE("Setting BINORMAL to %d\n", arrayNo);
792             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
793             This->declaredArrays = TRUE;
794         break;
795         case D3DDECLUSAGE_TESSFACTOR:
796             TRACE("Setting TESSFACTOR to %d\n", arrayNo);
797             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
798             This->declaredArrays = TRUE;
799         break;
800         case D3DDECLUSAGE_POSITIONT:
801             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
802                 FIXME("Setting positiont to %d\n", arrayNo);
803                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
804                 This->namedArrays = TRUE;
805             } else {
806                 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
807                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
808                 This->declaredArrays = TRUE;
809             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
810             }
811         break;
812         case D3DDECLUSAGE_FOG:
813             /* supported by OpenGL */
814             TRACE("Setting FOG to %d\n", arrayNo);
815             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
816             This->namedArrays = TRUE;
817         break;
818         case D3DDECLUSAGE_DEPTH:
819             TRACE("Setting DEPTH to %d\n", arrayNo);
820             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
821             This->declaredArrays = TRUE;
822         break;
823         case D3DDECLUSAGE_SAMPLE:
824             TRACE("Setting SAMPLE to %d\n", arrayNo);
825             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
826             This->declaredArrays = TRUE;
827         break;
828         default:
829         FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
830     }
831 }
832
833 void vshader_set_version(
834       IWineD3DVertexShaderImpl *This,
835       DWORD version) {
836
837       DWORD major = (version >> 8) & 0x0F;
838       DWORD minor = version & 0x0F;
839
840       This->baseShader.hex_version = version;
841       This->baseShader.version = major * 10 + minor;
842       TRACE("vs_%lu_%lu\n", major, minor);
843
844       This->baseShader.limits.texture = 0;
845
846       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
847       This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
848
849       switch (This->baseShader.version) {
850           case 10:
851           case 11: This->baseShader.limits.temporary = 12;
852                    This->baseShader.limits.constant_bool = 0;
853                    This->baseShader.limits.constant_int = 0;
854                    This->baseShader.limits.address = 1;
855                    break;
856       
857           case 20:
858           case 21: This->baseShader.limits.temporary = 12;
859                    This->baseShader.limits.constant_bool = 16;
860                    This->baseShader.limits.constant_int = 16;
861                    This->baseShader.limits.address = 1;
862                    break;
863
864           case 30: This->baseShader.limits.temporary = 32;
865                    This->baseShader.limits.constant_bool = 32;
866                    This->baseShader.limits.constant_int = 32;
867                    This->baseShader.limits.address = 1;
868                    break;
869
870           default: This->baseShader.limits.temporary = 12;
871                    This->baseShader.limits.constant_bool = 0;
872                    This->baseShader.limits.constant_int = 0;
873                    This->baseShader.limits.address = 1;
874                    FIXME("Unrecognized vertex shader version %lx!\n", version);
875       }
876 }
877
878 /* Map the opcode 1-to-1 to the GL code */
879 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
880
881     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
882     CONST SHADER_OPCODE* curOpcode = arg->opcode;
883     SHADER_BUFFER* buffer = arg->buffer;
884     DWORD dst = arg->dst;
885     DWORD* src = arg->src;
886
887     DWORD dst_regtype = shader_get_regtype(dst);
888     char tmpLine[256];
889     unsigned int i;
890
891     if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
892         strcpy(tmpLine, "ARL");
893     else
894         strcpy(tmpLine, curOpcode->glname);
895
896     if (curOpcode->num_params > 0) {
897         vshader_program_add_param(This, dst, FALSE, tmpLine);
898         for (i = 1; i < curOpcode->num_params; ++i) {
899            strcat(tmpLine, ",");
900            vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
901         }
902     }
903    shader_addline(buffer, "%s;\n", tmpLine);
904 }
905
906 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
907     
908     DWORD dst = arg->dst;
909     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
910     char tmpLine[256];
911     SHADER_BUFFER* buffer = arg->buffer;
912     
913     if (This->namedArrays) {
914         const char* attribName = "undefined";
915         switch(dst & 0xFFFF) {
916             case D3DDECLUSAGE_POSITION:
917             attribName = "vertex.position";
918             break;
919             case D3DDECLUSAGE_BLENDINDICES:
920             /* not supported by openGL */
921             attribName = "vertex.blend";
922             break;
923             case D3DDECLUSAGE_BLENDWEIGHT:
924             attribName = "vertex.weight";
925             break;
926             case D3DDECLUSAGE_NORMAL:
927             attribName = "vertex.normal";
928             break;
929             case D3DDECLUSAGE_PSIZE:
930             attribName = "vertex.psize";
931             break;
932             case D3DDECLUSAGE_COLOR:
933             if((dst & 0xF0000) >> 16 == 0)  {
934                 attribName = "vertex.color";
935             } else {
936                 attribName = "vertex.color.secondary";
937             }
938             break;
939             case D3DDECLUSAGE_TEXCOORD:
940             {
941                 char tmpChar[100];
942                 tmpChar[0] = 0;
943                 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
944                 attribName = tmpChar;
945                 break;
946             }
947             /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
948             case D3DDECLUSAGE_TANGENT:
949             attribName = "vertex.tangent";
950             break;
951             case D3DDECLUSAGE_BINORMAL:
952             attribName = "vertex.binormal";
953             break;
954             case D3DDECLUSAGE_TESSFACTOR:
955             attribName = "vertex.tessfactor";
956             break;
957             case D3DDECLUSAGE_POSITIONT:
958             attribName = "vertex.possitionT";
959             break;
960             case D3DDECLUSAGE_FOG:
961             attribName = "vertex.fogcoord";
962             break;
963             case D3DDECLUSAGE_DEPTH:
964             attribName = "vertex.depth";
965             break;
966             case D3DDECLUSAGE_SAMPLE:
967             attribName = "vertex.sample";
968             break;
969             default:
970             FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
971         }
972         {
973             sprintf(tmpLine, "ATTRIB ");
974             vshader_program_add_param(This, dst, FALSE, tmpLine);
975             if (This->namedArrays) 
976                 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
977         }
978     }
979 }
980
981 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
982     
983     IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
984     SHADER_BUFFER* buffer = arg->buffer;
985     DWORD reg = arg->dst;
986
987     shader_addline(buffer, 
988         "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF, 
989           *((const float *)(arg->src + 0)), 
990           *((const float *)(arg->src + 1)), 
991           *((const float *)(arg->src + 2)), 
992           *((const float *)(arg->src + 3)) );
993
994     shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
995 }
996
997 /** Handles transforming all D3DSIO_M?x? opcodes for 
998     Vertex shaders to ARB_vertex_program codes */
999 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1000
1001     int i;
1002     int nComponents = 0;
1003     SHADER_OPCODE_ARG tmpArg;
1004     
1005     /* Set constants for the temporary argument */
1006     tmpArg.shader = arg->shader;
1007     tmpArg.buffer = arg->buffer;
1008     tmpArg.src[0] = arg->src[0];
1009    
1010     switch(arg->opcode->opcode) {
1011     case D3DSIO_M4x4:
1012         nComponents = 4;
1013         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1014         break;
1015     case D3DSIO_M4x3:
1016         nComponents = 3;
1017         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1018         break;
1019     case D3DSIO_M3x4:
1020         nComponents = 4;
1021         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1022         break;
1023     case D3DSIO_M3x3:
1024         nComponents = 3;
1025         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1026         break;
1027     case D3DSIO_M3x2:
1028         nComponents = 2;
1029         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1030         break;
1031     default:
1032         break;
1033     }
1034     
1035     for (i = 0; i < nComponents; i++) {
1036         tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1037         tmpArg.src[1] = arg->src[1]+i;
1038         vshader_hw_map2gl(&tmpArg);
1039     }
1040 }
1041
1042 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1043     or GLSL and send it to the card */
1044 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1045     IWineD3DVertexShader *iface,
1046     CONST DWORD *pFunction) {
1047
1048     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1049     SHADER_BUFFER buffer;
1050
1051 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1052         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1053     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1054         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1055         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1056         This->fixupVertexBufferSize = PGMSIZE;
1057         This->fixupVertexBuffer[0] = 0;
1058     }
1059     buffer.buffer = This->device->fixupVertexBuffer;
1060 #else
1061     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
1062 #endif
1063     buffer.bsize = 0;
1064     buffer.lineNo = 0;
1065
1066     /* TODO: Optionally, generate the GLSL shader instead */
1067     if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1068         /*  Create the hw ARB shader */
1069         shader_addline(&buffer, "!!ARBvp1.0\n");
1070
1071         /* Mesa supports only 95 constants */
1072         if (GL_VEND(MESA) || GL_VEND(WINE))
1073             This->baseShader.limits.constant_float = 
1074                 min(95, This->baseShader.limits.constant_float);
1075
1076         shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1077             This->baseShader.limits.constant_float, 
1078             This->baseShader.limits.constant_float - 1);
1079
1080         /** Call the base shader generation routine to generate most 
1081             of the vertex shader string for us */
1082         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1083
1084         shader_addline(&buffer, "END\n\0"); 
1085
1086         /* TODO: change to resource.glObjectHandle or something like that */
1087         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1088
1089         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1090         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1091
1092         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1093         /* Create the program and check for errors */
1094         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1095             buffer.bsize, buffer.buffer));
1096
1097         if (glGetError() == GL_INVALID_OPERATION) {
1098             GLint errPos;
1099             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1100             FIXME("HW VertexShader Error at position %d: %s\n",
1101                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1102             This->baseShader.prgId = -1;
1103         }
1104     }
1105
1106 #if 1 /* if were using the data buffer of device then we don't need to free it */
1107   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1108 #endif
1109 }
1110
1111 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1112   /**
1113    * TODO: use the NV_vertex_program (or 1_1) extension
1114    *  and specifics vendors (ARB_vertex_program??) variants for it
1115    */
1116   return TRUE;
1117 }
1118
1119 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1120     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1121     DWORD opcode_token;   
1122  
1123     /** Vertex Shader Temporary Registers */
1124     WINED3DSHADERVECTOR R[12];
1125       /*D3DSHADERSCALAR A0;*/
1126     WINED3DSHADERVECTOR A[1];
1127     /** temporary Vector for modifier management */
1128     WINED3DSHADERVECTOR d;
1129     WINED3DSHADERVECTOR s[3];
1130     /** parser datas */
1131     const DWORD* pToken = This->baseShader.function;
1132     const SHADER_OPCODE* curOpcode = NULL;
1133     /** functions parameters */
1134     WINED3DSHADERVECTOR* p[6];
1135     WINED3DSHADERVECTOR* p_send[6];
1136     DWORD i;
1137
1138     /** init temporary register */
1139     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1140
1141     /* vshader_program_parse(vshader); */
1142 #if 0 /* Must not be 1 in cvs */
1143     TRACE("Input:\n");
1144     TRACE_VSVECTOR(This->data->C[0]);
1145     TRACE_VSVECTOR(This->data->C[1]);
1146     TRACE_VSVECTOR(This->data->C[2]);
1147     TRACE_VSVECTOR(This->data->C[3]);
1148     TRACE_VSVECTOR(This->data->C[4]);
1149     TRACE_VSVECTOR(This->data->C[5]);
1150     TRACE_VSVECTOR(This->data->C[6]);
1151     TRACE_VSVECTOR(This->data->C[7]);
1152     TRACE_VSVECTOR(This->data->C[8]);
1153     TRACE_VSVECTOR(This->data->C[64]);
1154     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1155     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1156     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1157     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1158     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1159     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1160     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1161     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1162     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1163 #endif
1164
1165     TRACE_VSVECTOR(vshader->data->C[64]);
1166     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1167
1168     /* the first dword is the version tag */
1169     /* TODO: parse it */
1170
1171     if (shader_is_vshader_version(*pToken)) { /** version */
1172         ++pToken;
1173     }
1174     while (D3DVS_END() != *pToken) {
1175         if (shader_is_comment(*pToken)) { /** comment */
1176             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1177             ++pToken;
1178             pToken += comment_len;
1179             continue ;
1180         }
1181
1182         opcode_token = *pToken++;
1183         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1184
1185         if (NULL == curOpcode) {
1186             FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1187             pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1188             /* return FALSE; */
1189
1190         } else {
1191             if (curOpcode->num_params > 0) {
1192                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1193                 for (i = 0; i < curOpcode->num_params; ++i) {
1194                     DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1195                     DWORD regtype = shader_get_regtype(pToken[i]);
1196     
1197                     switch (regtype) {
1198                     case D3DSPR_TEMP:
1199                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1200                         p[i] = &R[reg];
1201                         break;
1202                     case D3DSPR_INPUT:
1203                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1204                         p[i] = &input->V[reg];
1205                         break;
1206                     case D3DSPR_CONST:
1207                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1208                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1209                         } else {
1210                             p[i] = &This->data->C[reg];
1211                         }
1212                         break;
1213                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1214                         if (0 != reg) {
1215                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1216                             reg = 0;
1217                         }
1218                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1219                         p[i] = &A[reg];
1220                         break;
1221                     case D3DSPR_RASTOUT:
1222                         switch (reg) {
1223                         case D3DSRO_POSITION:
1224                             p[i] = &output->oPos;
1225                             break;
1226                         case D3DSRO_FOG:
1227                             p[i] = &output->oFog;
1228                             break;
1229                         case D3DSRO_POINT_SIZE:
1230                             p[i] = &output->oPts;
1231                             break;
1232                         }
1233                         break;
1234                     case D3DSPR_ATTROUT:
1235                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1236                         p[i] = &output->oD[reg];
1237                         break;
1238                     case D3DSPR_TEXCRDOUT:
1239                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1240                         p[i] = &output->oT[reg];
1241                         break;
1242                     /* TODO Decls and defs */
1243 #if 0
1244                     case D3DSPR_DCL:
1245                     case D3DSPR_DEF:
1246 #endif
1247                     default:
1248                         break;
1249                     }
1250
1251                     if (i > 0) { /* input reg */
1252                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1253                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1254
1255                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1256                             /* TRACE("p[%d] not swizzled\n", i); */
1257                             p_send[i] = p[i];
1258                         } else {
1259                             DWORD swizzle_x = swizzle & 0x03;
1260                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1261                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1262                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1263                             /* TRACE("p[%d] swizzled\n", i); */
1264                             float* tt = (float*) p[i];
1265                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1266                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1267                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1268                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1269                             p_send[i] = &s[i];
1270                         }
1271                     } else { /* output reg */
1272                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1273                             p_send[i] = p[i];
1274                         } else {
1275                             p_send[i] = &d; /* to be post-processed for modifiers management */
1276                         }
1277                     }
1278                 }
1279             }
1280
1281             switch (curOpcode->num_params) {
1282             case 0:
1283                 curOpcode->soft_fct();
1284                 break;
1285             case 1:
1286                 curOpcode->soft_fct(p_send[0]);
1287             break;
1288             case 2:
1289                 curOpcode->soft_fct(p_send[0], p_send[1]);
1290                 break;
1291             case 3:
1292                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1293                 break;
1294             case 4:
1295                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1296                 break;
1297             case 5:
1298                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1299                 break;
1300             case 6:
1301                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1302                 break;
1303             default:
1304                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1305             }
1306
1307             /* check if output reg modifier post-process */
1308             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1309                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1310                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1311                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1312                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1313             }
1314 #if 0
1315             TRACE_VSVECTOR(output->oPos);
1316             TRACE_VSVECTOR(output->oD[0]);
1317             TRACE_VSVECTOR(output->oD[1]);
1318             TRACE_VSVECTOR(output->oT[0]);
1319             TRACE_VSVECTOR(output->oT[1]);
1320             TRACE_VSVECTOR(R[0]);
1321             TRACE_VSVECTOR(R[1]);
1322             TRACE_VSVECTOR(R[2]);
1323             TRACE_VSVECTOR(R[3]);
1324             TRACE_VSVECTOR(R[4]);
1325             TRACE_VSVECTOR(R[5]);
1326 #endif
1327
1328             /* to next opcode token */
1329             pToken += curOpcode->num_params;
1330         }
1331 #if 0
1332         TRACE("End of current instruction:\n");
1333         TRACE_VSVECTOR(output->oPos);
1334         TRACE_VSVECTOR(output->oD[0]);
1335         TRACE_VSVECTOR(output->oD[1]);
1336         TRACE_VSVECTOR(output->oT[0]);
1337         TRACE_VSVECTOR(output->oT[1]);
1338         TRACE_VSVECTOR(R[0]);
1339         TRACE_VSVECTOR(R[1]);
1340         TRACE_VSVECTOR(R[2]);
1341         TRACE_VSVECTOR(R[3]);
1342         TRACE_VSVECTOR(R[4]);
1343         TRACE_VSVECTOR(R[5]);
1344 #endif
1345     }
1346 #if 0 /* Must not be 1 in cvs */
1347     TRACE("Output:\n");
1348     TRACE_VSVECTOR(output->oPos);
1349     TRACE_VSVECTOR(output->oD[0]);
1350     TRACE_VSVECTOR(output->oD[1]);
1351     TRACE_VSVECTOR(output->oT[0]);
1352     TRACE_VSVECTOR(output->oT[1]);
1353 #endif
1354     return WINED3D_OK;
1355 }
1356
1357 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1358     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1359     FIXME("(%p) : stub\n", This);
1360     return WINED3D_OK;
1361 }
1362
1363 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1364     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1365     FIXME("(%p) : stub\n", This);
1366     return WINED3D_OK;
1367 }
1368
1369 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1370     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1371     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1372         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1373         return WINED3DERR_INVALIDCALL;
1374     }
1375     if (NULL == pConstantData) {
1376         return WINED3DERR_INVALIDCALL;
1377     }
1378     FIXME("(%p) : stub\n", This);
1379     return WINED3D_OK;
1380 }
1381
1382 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1383     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1384     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1385     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1386         return WINED3DERR_INVALIDCALL;
1387     }
1388     if (NULL == pConstantData) {
1389         return WINED3DERR_INVALIDCALL;
1390     }
1391     FIXME("(%p) : stub\n", This);
1392     return WINED3D_OK;
1393 }
1394
1395 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1396     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1397     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1398         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1399         return WINED3DERR_INVALIDCALL;
1400     }
1401     if (NULL == pConstantData) {
1402         return WINED3DERR_INVALIDCALL;
1403     }
1404     FIXME("(%p) : stub\n", This);
1405     return WINED3D_OK;
1406 }
1407
1408 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1409     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1410     FIXME("(%p) : stub\n", This);
1411     return WINED3D_OK;
1412 }
1413
1414 #endif
1415
1416 /* *******************************************
1417    IWineD3DVertexShader IUnknown parts follow
1418    ******************************************* */
1419 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1420 {
1421     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1422     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1423     if (IsEqualGUID(riid, &IID_IUnknown) 
1424         || IsEqualGUID(riid, &IID_IWineD3DBase)
1425         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1426         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1427         IUnknown_AddRef(iface);
1428         *ppobj = This;
1429         return S_OK;
1430     }
1431     *ppobj = NULL;
1432     return E_NOINTERFACE;
1433 }
1434
1435 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1436     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1437     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1438     return InterlockedIncrement(&This->ref);
1439 }
1440
1441 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1442     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1443     ULONG ref;
1444     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1445     ref = InterlockedDecrement(&This->ref);
1446     if (ref == 0) {
1447         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1448         HeapFree(GetProcessHeap(), 0, This);
1449     }
1450     return ref;
1451 }
1452
1453 /* *******************************************
1454    IWineD3DVertexShader IWineD3DVertexShader parts follow
1455    ******************************************* */
1456
1457 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1458     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1459     
1460     *parent = This->parent;
1461     IUnknown_AddRef(*parent);
1462     TRACE("(%p) : returning %p\n", This, *parent);
1463     return WINED3D_OK;
1464 }
1465
1466 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1467     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1468     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1469     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1470     TRACE("(%p) returning %p\n", This, *pDevice);
1471     return WINED3D_OK;
1472 }
1473
1474 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1475     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1476     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1477
1478     if (NULL == pData) {
1479         *pSizeOfData = This->baseShader.functionLength;
1480         return WINED3D_OK;
1481     }
1482     if (*pSizeOfData < This->baseShader.functionLength) {
1483         *pSizeOfData = This->baseShader.functionLength;
1484         return WINED3DERR_MOREDATA;
1485     }
1486     if (NULL == This->baseShader.function) { /* no function defined */
1487         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1488         (*(DWORD **) pData) = NULL;
1489     } else {
1490         if(This->baseShader.functionLength == 0){
1491
1492         }
1493         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1494         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1495     }
1496     return WINED3D_OK;
1497 }
1498
1499 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1500     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1501     const DWORD* pToken = pFunction;
1502     const SHADER_OPCODE* curOpcode = NULL;
1503     DWORD opcode_token;
1504     DWORD len = 0;
1505     DWORD i;
1506     TRACE("(%p) : Parsing programme\n", This);
1507
1508     /* Initialise vertex input arrays */
1509     This->namedArrays = FALSE;
1510     This->declaredArrays = FALSE;
1511     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1512         This->arrayUsageMap[i] = -1;
1513
1514     if (NULL != pToken) {
1515         while (D3DVS_END() != *pToken) {
1516             if (shader_is_vshader_version(*pToken)) { /** version */
1517                 vshader_set_version(This, *pToken);
1518                 ++pToken;
1519                 ++len;
1520                 continue;
1521             }
1522             if (shader_is_comment(*pToken)) { /** comment */
1523                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1524                 ++pToken;
1525                 TRACE("//%s\n", (char*)pToken);
1526                 pToken += comment_len;
1527                 len += comment_len + 1;
1528                 continue;
1529             }
1530
1531             opcode_token = *pToken++;
1532             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1533             len++;
1534
1535             if (NULL == curOpcode) {
1536                 int tokens_read;
1537
1538                 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1539                 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1540                 pToken += tokens_read;
1541                 len += tokens_read;
1542
1543             } else {
1544                 if (curOpcode->opcode == D3DSIO_DCL) {
1545
1546                     DWORD usage = *pToken;
1547                     DWORD param = *(pToken + 1);
1548
1549                     parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1550                     shader_program_dump_decl_usage(usage, param);
1551                     shader_dump_ins_modifiers(param);
1552                     TRACE(" ");
1553                     shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1554                     pToken += 2;
1555                     len += 2;
1556
1557                 } else 
1558                     if (curOpcode->opcode == D3DSIO_DEF) {
1559                         TRACE("def c%lu = ", *pToken & 0xFF);
1560                         ++pToken;
1561                         ++len;
1562                         TRACE("%f ,", *(float *)pToken);
1563                         ++pToken;
1564                         ++len;
1565                         TRACE("%f ,", *(float *)pToken);
1566                         ++pToken;
1567                         ++len;
1568                         TRACE("%f ,", *(float *)pToken);
1569                         ++pToken;
1570                         ++len;
1571                         TRACE("%f", *(float *)pToken);
1572                         ++pToken;
1573                         ++len;
1574                 } else {
1575
1576                     DWORD param, addr_token;
1577                     int tokens_read;
1578
1579                     TRACE("%s", curOpcode->name);
1580                     if (curOpcode->num_params > 0) {
1581
1582                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1583                             pToken, &param, &addr_token);
1584                         pToken += tokens_read;
1585                         len += tokens_read;
1586
1587                         shader_dump_ins_modifiers(param);
1588                         TRACE(" ");
1589                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1590
1591                         for (i = 1; i < curOpcode->num_params; ++i) {
1592
1593                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1594                                pToken, &param, &addr_token);
1595                             pToken += tokens_read;
1596                             len += tokens_read;
1597
1598                             TRACE(", ");
1599                             shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1600                         }
1601                     }
1602                 }
1603                 TRACE("\n");
1604             }
1605         }
1606         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1607     } else {
1608         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1609     }
1610
1611 /* Handy for debugging using numbered arrays instead of named arrays */
1612 #if 1
1613     /* TODO: using numbered arrays for software shaders makes things easier */
1614     This->declaredArrays = TRUE;
1615 #endif
1616
1617     /* named arrays and declared arrays are mutually exclusive */
1618     if (This->declaredArrays) 
1619         This->namedArrays = FALSE;
1620
1621     /* Generate HW shader in needed */
1622     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1623 #if 1
1624         IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1625 #endif
1626     }
1627
1628     /* copy the function ... because it will certainly be released by application */
1629     if (NULL != pFunction) {
1630         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1631         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1632     } else {
1633         This->baseShader.function = NULL;
1634     }
1635     return WINED3D_OK;
1636 }
1637
1638 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1639 {
1640     /*** IUnknown methods ***/
1641     IWineD3DVertexShaderImpl_QueryInterface,
1642     IWineD3DVertexShaderImpl_AddRef,
1643     IWineD3DVertexShaderImpl_Release,
1644     /*** IWineD3DBase methods ***/
1645     IWineD3DVertexShaderImpl_GetParent,
1646     /*** IWineD3DBaseShader methods ***/
1647     IWineD3DVertexShaderImpl_SetFunction,
1648     /*** IWineD3DVertexShader methods ***/
1649     IWineD3DVertexShaderImpl_GetDevice,
1650     IWineD3DVertexShaderImpl_GetFunction
1651 };