wined3d: Correctly define the number of possible parameters.
[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 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
82
83 /*******************************
84  * vshader functions software VM
85  */
86
87 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
88   d->x = s0->x + s1->x;
89   d->y = s0->y + s1->y;
90   d->z = s0->z + s1->z;
91   d->w = s0->w + s1->w;
92   VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
93                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
94 }
95
96 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
97   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
98   VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
99                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
100 }
101
102 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
103   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
104   VSTRACE(("executing dp4: 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_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
109   d->x = 1.0f;
110   d->y = s0->y * s1->y;
111   d->z = s0->z;
112   d->w = s1->w;
113   VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
114           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
115 }
116
117 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
118   union {
119     float f;
120     DWORD d;
121   } tmp;
122
123   tmp.f = floorf(s0->w);
124   d->x  = powf(2.0f, tmp.f);
125   d->y  = s0->w - tmp.f;
126   tmp.f = powf(2.0f, s0->w);
127   tmp.d &= 0xFFFFFF00U;
128   d->z  = tmp.f;
129   d->w  = 1.0f;
130   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
131                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
132 }
133
134 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
135   d->x = 1.0f;
136   d->y = (0.0f < s0->x) ? s0->x : 0.0f;
137   d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
138   d->w = 1.0f;
139   VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
140                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
141 }
142
143 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
144   float tmp_f = fabsf(s0->w);
145   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
146   VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
147                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
148 }
149
150 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
151   d->x = s0->x * s1->x + s2->x;
152   d->y = s0->y * s1->y + s2->y;
153   d->z = s0->z * s1->z + s2->z;
154   d->w = s0->w * s1->w + s2->w;
155   VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
156           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));
157 }
158
159 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
160   d->x = (s0->x >= s1->x) ? s0->x : s1->x;
161   d->y = (s0->y >= s1->y) ? s0->y : s1->y;
162   d->z = (s0->z >= s1->z) ? s0->z : s1->z;
163   d->w = (s0->w >= s1->w) ? s0->w : s1->w;
164   VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
165           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
166 }
167
168 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
169   d->x = (s0->x < s1->x) ? s0->x : s1->x;
170   d->y = (s0->y < s1->y) ? s0->y : s1->y;
171   d->z = (s0->z < s1->z) ? s0->z : s1->z;
172   d->w = (s0->w < s1->w) ? s0->w : s1->w;
173   VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
174           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
175 }
176
177 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
178   d->x = s0->x;
179   d->y = s0->y;
180   d->z = s0->z;
181   d->w = s0->w;
182   VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
183           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
184 }
185
186 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
187   d->x = s0->x * s1->x;
188   d->y = s0->y * s1->y;
189   d->z = s0->z * s1->z;
190   d->w = s0->w * s1->w;
191   VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
192           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
193 }
194
195 void vshader_nop(void) {
196     /* NOPPPP ahhh too easy ;) */
197     VSTRACE(("executing nop\n"));
198 }
199
200 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
201   d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
202   VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
203           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
204 }
205
206 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
207   float tmp_f = fabsf(s0->w);
208   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);
209   VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
210           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
211 }
212
213 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
214   d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
215   d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
216   d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
217   d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
218   VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
219           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
220 }
221
222 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
223   d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
224   d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
225   d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
226   d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
227   VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
228           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
229 }
230
231 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
232   d->x = s0->x - s1->x;
233   d->y = s0->y - s1->y;
234   d->z = s0->z - s1->z;
235   d->w = s0->w - s1->w;
236   VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
237           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
238 }
239
240 /**
241  * Version 1.1 specific
242  */
243
244 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
245   d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
246   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
247           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
248 }
249
250 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
251   float tmp_f = fabsf(s0->w);
252   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
253   VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
254           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
255 }
256
257 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
258   d->x = s0->x - floorf(s0->x);
259   d->y = s0->y - floorf(s0->y);
260   d->z = 0.0f;
261   d->w = 1.0f;
262   VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
263           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
264 }
265
266 typedef FLOAT D3DMATRIX44[4][4];
267 typedef FLOAT D3DMATRIX43[4][3];
268 typedef FLOAT D3DMATRIX34[3][4];
269 typedef FLOAT D3DMATRIX33[3][3];
270 typedef FLOAT D3DMATRIX23[2][3];
271
272 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
273   /*
274    * Buggy CODE: here only if cast not work for copy/paste
275   WINED3DSHADERVECTOR* mat2 = mat1 + 1;
276   WINED3DSHADERVECTOR* mat3 = mat1 + 2;
277   WINED3DSHADERVECTOR* mat4 = mat1 + 3;
278   d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
279   d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
280   d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
281   d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
282   */
283   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
284   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
285   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
286   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
287   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));
288   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));
289   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));
290   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));
291 }
292
293 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
294   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
295   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
296   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
297   d->w = 1.0f;
298   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));
299   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));
300   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));
301   VSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
302 }
303
304 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
305   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
306   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
307   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
308   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
309   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));
310   VSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
311   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));
312   VSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
313 }
314
315 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
316   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
317   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
318   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
319   d->w = 1.0f;
320   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));
321   VSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
322   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));
323   VSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
324 }
325
326 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
327   FIXME("check\n");
328   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
329   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
330   d->z = 0.0f;
331   d->w = 1.0f;
332 }
333
334 /**
335  * Version 2.0 specific
336  */
337 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
338   d->x = s0->x * (s1->x - s2->x) + s2->x;
339   d->y = s0->y * (s1->y - s2->y) + s2->y;
340   d->z = s0->z * (s1->z - s2->z) + s2->z;
341   d->w = s0->w * (s1->w - s2->w) + s2->w;
342 }
343
344 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
345   d->x = s0->y * s1->z - s0->z * s1->y;
346   d->y = s0->z * s1->x - s0->x * s1->z;
347   d->z = s0->x * s1->y - s0->y * s1->x;
348   d->w = 0.9f; /* w is undefined, so set it to something safeish */
349
350   VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
351              s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
352 }
353
354 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
355
356   d->x = fabsf(s0->x);
357   d->y = fabsf(s0->y);
358   d->z = fabsf(s0->z);
359   d->w = fabsf(s0->w);
360   VSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
361              s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
362 }
363
364     /* Stubs */
365
366 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
367 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
368     FIXME(" : Stub\n");
369 }
370
371 void vshader_call(WINED3DSHADERVECTOR* d) {
372     FIXME(" : Stub\n");
373 }
374
375 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
376     FIXME(" : Stub\n");
377 }
378
379 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
380     FIXME(" : Stub\n");
381 }
382
383 void vshader_ret(void) {
384     FIXME(" : Stub\n");
385 }
386
387 void vshader_endloop(void) {
388     FIXME(" : Stub\n");
389 }
390
391 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
392     FIXME(" : Stub\n");
393 }
394
395 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
396     FIXME(" : Stub\n");
397 }
398
399 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
400     FIXME(" : Stub\n");
401 }
402
403 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404     FIXME(" : Stub\n");
405 }
406
407 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408     FIXME(" : Stub\n");
409 }
410
411 void vshader_rep(WINED3DSHADERVECTOR* d) {
412     FIXME(" : Stub\n");
413 }
414
415 void vshader_endrep(void) {
416     FIXME(" : Stub\n");
417 }
418
419 void vshader_if(WINED3DSHADERVECTOR* d) {
420     FIXME(" : Stub\n");
421 }
422
423 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424     FIXME(" : Stub\n");
425 }
426
427 void vshader_else(void) {
428     FIXME(" : Stub\n");
429 }
430
431 void vshader_label(WINED3DSHADERVECTOR* d) {
432     FIXME(" : Stub\n");
433 }
434
435 void vshader_endif(void) {
436     FIXME(" : Stub\n");
437 }
438
439 void vshader_break(void) {
440     FIXME(" : Stub\n");
441 }
442
443 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
444     FIXME(" : Stub\n");
445 }
446
447 void vshader_breakp(WINED3DSHADERVECTOR* d) {
448     FIXME(" : Stub\n");
449 }
450
451 void vshader_mova(WINED3DSHADERVECTOR* d) {
452     FIXME(" : Stub\n");
453 }
454
455 void vshader_defb(WINED3DSHADERVECTOR* d) {
456     FIXME(" : Stub\n");
457 }
458
459 void vshader_defi(WINED3DSHADERVECTOR* d) {
460     FIXME(" : Stub\n");
461 }
462
463 void vshader_texldd(WINED3DSHADERVECTOR* d) {
464     FIXME(" : Stub\n");
465 }
466
467 void vshader_setp(WINED3DSHADERVECTOR* d) {
468     FIXME(" : Stub\n");
469 }
470
471 void vshader_texldl(WINED3DSHADERVECTOR* d) {
472     FIXME(" : Stub\n");
473 }
474
475 /* Prototype */
476 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
477 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
478 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
479 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
480
481 /**
482  * log, exp, frc, m*x* seems to be macros ins ... to see
483  */
484 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
485
486     /* Arithmetic */ 
487     {D3DSIO_NOP,  "nop",  "NOP", 0, vshader_nop,  vshader_hw_map2gl, NULL, 0, 0},
488     {D3DSIO_MOV,  "mov",  "MOV", 2, vshader_mov,  vshader_hw_map2gl, NULL, 0, 0},
489     {D3DSIO_ADD,  "add",  "ADD", 3, vshader_add,  vshader_hw_map2gl, NULL, 0, 0},
490     {D3DSIO_SUB,  "sub",  "SUB", 3, vshader_sub,  vshader_hw_map2gl, NULL, 0, 0},
491     {D3DSIO_MAD,  "mad",  "MAD", 4, vshader_mad,  vshader_hw_map2gl, NULL, 0, 0},
492     {D3DSIO_MUL,  "mul",  "MUL", 3, vshader_mul,  vshader_hw_map2gl, NULL, 0, 0},
493     {D3DSIO_RCP,  "rcp",  "RCP", 2, vshader_rcp,  vshader_hw_map2gl, NULL, 0, 0},
494     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, vshader_rsq,  vshader_hw_map2gl, NULL, 0, 0},
495     {D3DSIO_DP3,  "dp3",  "DP3", 3, vshader_dp3,  vshader_hw_map2gl, NULL, 0, 0},
496     {D3DSIO_DP4,  "dp4",  "DP4", 3, vshader_dp4,  vshader_hw_map2gl, NULL, 0, 0},
497     {D3DSIO_MIN,  "min",  "MIN", 3, vshader_min,  vshader_hw_map2gl, NULL, 0, 0},
498     {D3DSIO_MAX,  "max",  "MAX", 3, vshader_max,  vshader_hw_map2gl, NULL, 0, 0},
499     {D3DSIO_SLT,  "slt",  "SLT", 3, vshader_slt,  vshader_hw_map2gl, NULL, 0, 0},
500     {D3DSIO_SGE,  "sge",  "SGE", 3, vshader_sge,  vshader_hw_map2gl, NULL, 0, 0},
501     {D3DSIO_ABS,  "abs",  "ABS", 2, vshader_abs,  vshader_hw_map2gl, NULL, 0, 0},
502     {D3DSIO_EXP,  "exp",  "EX2", 2, vshader_exp,  vshader_hw_map2gl, NULL, 0, 0},
503     {D3DSIO_LOG,  "log",  "LG2", 2, vshader_log,  vshader_hw_map2gl, NULL, 0, 0},
504     {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
505     {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
506     {D3DSIO_LIT,  "lit",  "LIT", 2, vshader_lit,  vshader_hw_map2gl, NULL, 0, 0},
507     {D3DSIO_DST,  "dst",  "DST", 3, vshader_dst,  vshader_hw_map2gl, NULL, 0, 0},
508     {D3DSIO_LRP,  "lrp",  "LRP", 4, vshader_lrp,  vshader_hw_map2gl, NULL, 0, 0},
509     {D3DSIO_FRC,  "frc",  "FRC", 2, vshader_frc,  vshader_hw_map2gl, NULL, 0, 0},
510     {D3DSIO_POW,  "pow",  "POW", 3, vshader_pow,  NULL, NULL, 0, 0},
511     {D3DSIO_CRS,  "crs",  "XPS", 3, vshader_crs,  NULL, NULL, 0, 0},
512     /* TODO: sng can possibly be performed a  s
513         RCP tmp, vec
514         MUL out, tmp, vec*/
515     {D3DSIO_SGN,  "sng",  NULL,  2, vshader_sng,  NULL,   NULL, 0, 0},
516     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
517         DP3 tmp , vec, vec;
518         RSQ tmp, tmp.x;
519         MUL vec.xyz, vec, tmp;
520     but I think this is better because it accounts for w properly.
521         DP3 tmp , vec, vec;
522         RSQ tmp, tmp.x;
523         MUL vec, vec, tmp;
524
525     */
526     {D3DSIO_NRM,      "nrm",      NULL,   2, vshader_nrm,    NULL, NULL, 0, 0},
527     {D3DSIO_SINCOS,   "sincos",   NULL,   2, vshader_sincos, NULL, NULL, 0, 0},
528
529     /* Matrix */
530     {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
531     {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
532     {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
533     {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
534     {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
535
536     /* Declare registers */
537     {D3DSIO_DCL,      "dcl",      NULL,                  2, vshader_dcl,     vshader_hw_dcl, NULL, 0, 0},
538
539     /* Constant definitions */
540     {D3DSIO_DEF,      "def",      NULL,                  5, vshader_def,     vshader_hw_def, NULL, 0, 0},
541     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, vshader_defb,    NULL, NULL, 0, 0},
542     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, vshader_defi,    NULL, NULL, 0, 0},
543
544     /* Flow control - requires GLSL or software shaders */
545     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   1, vshader_rep,     NULL, NULL, 0, 0},
546     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, vshader_endrep,  NULL, NULL, 0, 0},
547     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   1, vshader_if,      NULL, NULL, 0, 0},
548     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, vshader_ifc,     NULL, NULL, 0, 0},
549     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   0, vshader_else,    NULL, NULL, 0, 0},
550     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   0, vshader_endif,   NULL, NULL, 0, 0},
551     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   0, vshader_break,   NULL, NULL, 0, 0},
552     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, vshader_breakc,  NULL, NULL, 0, 0},
553     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   1, vshader_breakp,  NULL, NULL, 0, 0},
554     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, vshader_call,    NULL, NULL, 0, 0},
555     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, vshader_callnz,  NULL, NULL, 0, 0},
556     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, vshader_loop,    NULL, NULL, 0, 0},
557     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, vshader_ret,     NULL, NULL, 0, 0},
558     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, vshader_endloop, NULL, NULL, 0, 0},
559     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, vshader_label,   NULL, NULL, 0, 0},
560
561     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, vshader_mova,    NULL, NULL, 0, 0},
562     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, vshader_setp,    NULL, NULL, 0, 0},
563     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, vshader_texldl,  NULL, NULL, 0, 0},
564     {0,               NULL,       NULL,   0, NULL,            NULL, 0, 0}
565 };
566
567 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
568     /** operand output */
569     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
570       strcat(hwLine, ".");
571       if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
572       if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
573       if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
574       if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
575     }  
576 }
577
578 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
579     static const char swizzle_reg_chars_color_fix[] = "zyxw";
580     static const char swizzle_reg_chars[] = "xyzw";
581     const char* swizzle_regs = NULL;
582     char  tmpReg[255];
583
584     /** operand input */
585     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
586     DWORD swizzle_x = swizzle & 0x03;
587     DWORD swizzle_y = (swizzle >> 2) & 0x03;
588     DWORD swizzle_z = (swizzle >> 4) & 0x03;
589     DWORD swizzle_w = (swizzle >> 6) & 0x03;
590
591     if (is_color) {
592       swizzle_regs = swizzle_reg_chars_color_fix;
593     } else {
594       swizzle_regs = swizzle_reg_chars;
595     }
596
597     /**
598      * swizzle bits fields:
599      *  WWZZYYXX
600      */
601     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
602       if (is_color) {
603         sprintf(tmpReg, ".%c%c%c%c",
604                 swizzle_regs[swizzle_x],
605                 swizzle_regs[swizzle_y],
606                 swizzle_regs[swizzle_z],
607                 swizzle_regs[swizzle_w]);
608         strcat(hwLine, tmpReg);
609       }
610       return ;
611     }
612     if (swizzle_x == swizzle_y &&
613         swizzle_x == swizzle_z &&
614         swizzle_x == swizzle_w)
615     {
616       sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
617       strcat(hwLine, tmpReg);
618     } else {
619       sprintf(tmpReg, ".%c%c%c%c",
620               swizzle_regs[swizzle_x],
621               swizzle_regs[swizzle_y],
622               swizzle_regs[swizzle_z],
623               swizzle_regs[swizzle_w]);
624       strcat(hwLine, tmpReg);
625     }
626 }
627
628 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
629   /* oPos, oFog and oPts in D3D */
630   static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
631
632   DWORD reg = param & D3DSP_REGNUM_MASK;
633   DWORD regtype = shader_get_regtype(param);
634   char  tmpReg[255];
635   BOOL is_color = FALSE;
636
637   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
638       strcat(hwLine, " -");
639   } else {
640       strcat(hwLine, " ");
641   }
642
643   switch (regtype) {
644   case D3DSPR_TEMP:
645     sprintf(tmpReg, "R%lu", reg);
646     strcat(hwLine, tmpReg);
647     break;
648   case D3DSPR_INPUT:
649     if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
650         || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
651         is_color = TRUE;
652     }
653     /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
654     if (This->namedArrays) {
655         sprintf(tmpReg, "namedVertex%lu", reg);
656     } else {
657     /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
658         sprintf(tmpReg, "vertex.attrib[%lu]", reg);
659     }
660     strcat(hwLine, tmpReg);
661     break;
662   case D3DSPR_CONST:
663     /* FIXME: some constants are named so we need a constants map*/
664     if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
665         if (param & D3DVS_ADDRMODE_RELATIVE) {
666             FIXME("Relative addressing not expected for a named constant %lu\n", reg);
667         }
668         sprintf(tmpReg, "const%lu", reg);
669     } else {
670         sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
671     }
672     strcat(hwLine, tmpReg);
673     break;
674   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
675     sprintf(tmpReg, "A%lu", reg);
676     strcat(hwLine, tmpReg);
677     break;
678   case D3DSPR_RASTOUT:
679     sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
680     strcat(hwLine, tmpReg);
681     break;
682   case D3DSPR_ATTROUT:
683     if (reg==0) {
684        strcat(hwLine, "result.color.primary");
685     } else {
686        strcat(hwLine, "result.color.secondary");
687     }
688     break;
689   case D3DSPR_TEXCRDOUT:
690     sprintf(tmpReg, "result.texcoord[%lu]", reg);
691     strcat(hwLine, tmpReg);
692     break;
693   default:
694     FIXME("Unknown reg type %ld %ld\n", regtype, reg);
695     break;
696   }
697
698   if (!is_input) {
699     vshader_program_add_output_param_swizzle(param, is_color, hwLine);
700   } else {
701     vshader_program_add_input_param_swizzle(param, is_color, hwLine);
702   }
703 }
704
705 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
706 {
707     switch(usage & 0xFFFF) {
708         case D3DDECLUSAGE_POSITION:
709             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
710                 TRACE("Setting position to %d\n", arrayNo);
711                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
712                 This->namedArrays = TRUE;
713             } else {
714                 /* TODO: position indexes go from 0-8!!*/
715                 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
716                 /* robots uses positions up to 8, the position arrays are just packed.*/
717                 if ((usage & 0xF0000) >> 16 > 1) {
718                     TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
719                 }
720                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
721                 This->declaredArrays = TRUE;
722             }
723         break;
724         case D3DDECLUSAGE_BLENDINDICES:
725             /* not supported by openGL */
726             TRACE("Setting BLENDINDICES to %d\n", arrayNo);
727             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
728             This->declaredArrays = TRUE;
729             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
730         break;
731         case D3DDECLUSAGE_BLENDWEIGHT:
732             TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
733             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
734             This->namedArrays = TRUE;
735             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
736         break;
737         case D3DDECLUSAGE_NORMAL:
738             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
739                 TRACE("Setting normal to %d\n", arrayNo);
740                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
741                 This->namedArrays = TRUE;
742             } else {
743                 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
744                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
745                 This->declaredArrays = TRUE;
746             }
747         break;
748         case D3DDECLUSAGE_PSIZE:
749             TRACE("Setting PSIZE to %d\n", arrayNo);
750             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
751             This->namedArrays = TRUE;
752             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
753         break;
754         case D3DDECLUSAGE_COLOR:
755             if((usage & 0xF0000) >> 16 == 0)  {
756                 TRACE("Setting DIFFUSE to %d\n", arrayNo);
757                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
758                 This->namedArrays = TRUE;
759             } else {
760                 TRACE("Setting SPECULAR to %d\n", arrayNo);
761                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
762                 This->namedArrays = TRUE;
763             }
764         break;
765         case D3DDECLUSAGE_TEXCOORD:
766             This->namedArrays = TRUE;
767             /* only 7 texture coords have been designed for, so run a quick sanity check */
768             if ((usage & 0xF0000) >> 16 > 7) {
769                 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
770             } else {
771                 TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
772                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
773             }
774         break;
775         /* The following aren't supported by openGL,
776             if we get them then everything needs to be mapped to numbered attributes instead of named ones.
777             this should be caught in the first pass */
778         case D3DDECLUSAGE_TANGENT:
779             TRACE("Setting TANGENT to %d\n", arrayNo);
780             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
781             This->declaredArrays = TRUE;
782         break;
783         case D3DDECLUSAGE_BINORMAL:
784             TRACE("Setting BINORMAL to %d\n", arrayNo);
785             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
786             This->declaredArrays = TRUE;
787         break;
788         case D3DDECLUSAGE_TESSFACTOR:
789             TRACE("Setting TESSFACTOR to %d\n", arrayNo);
790             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
791             This->declaredArrays = TRUE;
792         break;
793         case D3DDECLUSAGE_POSITIONT:
794             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
795                 FIXME("Setting positiont to %d\n", arrayNo);
796                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
797                 This->namedArrays = TRUE;
798             } else {
799                 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
800                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
801                 This->declaredArrays = TRUE;
802             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
803             }
804         break;
805         case D3DDECLUSAGE_FOG:
806             /* supported by OpenGL */
807             TRACE("Setting FOG to %d\n", arrayNo);
808             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
809             This->namedArrays = TRUE;
810         break;
811         case D3DDECLUSAGE_DEPTH:
812             TRACE("Setting DEPTH to %d\n", arrayNo);
813             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
814             This->declaredArrays = TRUE;
815         break;
816         case D3DDECLUSAGE_SAMPLE:
817             TRACE("Setting SAMPLE to %d\n", arrayNo);
818             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
819             This->declaredArrays = TRUE;
820         break;
821         default:
822         FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
823     }
824 }
825
826 void vshader_set_version(
827       IWineD3DVertexShaderImpl *This,
828       DWORD version) {
829
830       DWORD major = (version >> 8) & 0x0F;
831       DWORD minor = version & 0x0F;
832
833       This->baseShader.hex_version = version;
834       This->baseShader.version = major * 10 + minor;
835       TRACE("vs_%lu_%lu\n", major, minor);
836
837       This->baseShader.limits.texture = 0;
838
839       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
840       This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
841
842       switch (This->baseShader.version) {
843           case 10:
844           case 11: This->baseShader.limits.temporary = 12;
845                    This->baseShader.limits.constant_bool = 0;
846                    This->baseShader.limits.constant_int = 0;
847                    This->baseShader.limits.address = 1;
848                    break;
849       
850           case 20:
851           case 21: This->baseShader.limits.temporary = 12;
852                    This->baseShader.limits.constant_bool = 16;
853                    This->baseShader.limits.constant_int = 16;
854                    This->baseShader.limits.address = 1;
855                    break;
856
857           case 30: This->baseShader.limits.temporary = 32;
858                    This->baseShader.limits.constant_bool = 32;
859                    This->baseShader.limits.constant_int = 32;
860                    This->baseShader.limits.address = 1;
861                    break;
862
863           default: This->baseShader.limits.temporary = 12;
864                    This->baseShader.limits.constant_bool = 0;
865                    This->baseShader.limits.constant_int = 0;
866                    This->baseShader.limits.address = 1;
867                    FIXME("Unrecognized vertex shader version %lx!\n", version);
868       }
869 }
870
871 /* Map the opcode 1-to-1 to the GL code */
872 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
873
874     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
875     CONST SHADER_OPCODE* curOpcode = arg->opcode;
876     SHADER_BUFFER* buffer = arg->buffer;
877     DWORD dst = arg->dst;
878     DWORD* src = arg->src;
879
880     DWORD dst_regtype = shader_get_regtype(dst);
881     char tmpLine[256];
882     unsigned int i;
883
884     if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
885         strcpy(tmpLine, "ARL");
886     else
887         strcpy(tmpLine, curOpcode->glname);
888
889     if (curOpcode->num_params > 0) {
890         vshader_program_add_param(This, dst, FALSE, tmpLine);
891         for (i = 1; i < curOpcode->num_params; ++i) {
892            strcat(tmpLine, ",");
893            vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
894         }
895     }
896    shader_addline(buffer, "%s;\n", tmpLine);
897 }
898
899 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
900     
901     DWORD dst = arg->dst;
902     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
903     char tmpLine[256];
904     SHADER_BUFFER* buffer = arg->buffer;
905     
906     if (This->namedArrays) {
907         const char* attribName = "undefined";
908         switch(dst & 0xFFFF) {
909             case D3DDECLUSAGE_POSITION:
910             attribName = "vertex.position";
911             break;
912             case D3DDECLUSAGE_BLENDINDICES:
913             /* not supported by openGL */
914             attribName = "vertex.blend";
915             break;
916             case D3DDECLUSAGE_BLENDWEIGHT:
917             attribName = "vertex.weight";
918             break;
919             case D3DDECLUSAGE_NORMAL:
920             attribName = "vertex.normal";
921             break;
922             case D3DDECLUSAGE_PSIZE:
923             attribName = "vertex.psize";
924             break;
925             case D3DDECLUSAGE_COLOR:
926             if((dst & 0xF0000) >> 16 == 0)  {
927                 attribName = "vertex.color";
928             } else {
929                 attribName = "vertex.color.secondary";
930             }
931             break;
932             case D3DDECLUSAGE_TEXCOORD:
933             {
934                 char tmpChar[100];
935                 tmpChar[0] = 0;
936                 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
937                 attribName = tmpChar;
938                 break;
939             }
940             /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
941             case D3DDECLUSAGE_TANGENT:
942             attribName = "vertex.tangent";
943             break;
944             case D3DDECLUSAGE_BINORMAL:
945             attribName = "vertex.binormal";
946             break;
947             case D3DDECLUSAGE_TESSFACTOR:
948             attribName = "vertex.tessfactor";
949             break;
950             case D3DDECLUSAGE_POSITIONT:
951             attribName = "vertex.possitionT";
952             break;
953             case D3DDECLUSAGE_FOG:
954             attribName = "vertex.fogcoord";
955             break;
956             case D3DDECLUSAGE_DEPTH:
957             attribName = "vertex.depth";
958             break;
959             case D3DDECLUSAGE_SAMPLE:
960             attribName = "vertex.sample";
961             break;
962             default:
963             FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
964         }
965         {
966             sprintf(tmpLine, "ATTRIB ");
967             vshader_program_add_param(This, dst, FALSE, tmpLine);
968             if (This->namedArrays) 
969                 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
970         }
971     }
972 }
973
974 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
975     
976     IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
977     SHADER_BUFFER* buffer = arg->buffer;
978     DWORD reg = arg->dst;
979
980     shader_addline(buffer, 
981         "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF, 
982           *((const float *)(arg->src + 0)), 
983           *((const float *)(arg->src + 1)), 
984           *((const float *)(arg->src + 2)), 
985           *((const float *)(arg->src + 3)) );
986
987     shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
988 }
989
990 /** Handles transforming all D3DSIO_M?x? opcodes for 
991     Vertex shaders to ARB_vertex_program codes */
992 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
993
994     int i;
995     int nComponents = 0;
996     SHADER_OPCODE_ARG tmpArg;
997     
998     /* Set constants for the temporary argument */
999     tmpArg.shader = arg->shader;
1000     tmpArg.buffer = arg->buffer;
1001     tmpArg.src[0] = arg->src[0];
1002    
1003     switch(arg->opcode->opcode) {
1004     case D3DSIO_M4x4:
1005         nComponents = 4;
1006         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1007         break;
1008     case D3DSIO_M4x3:
1009         nComponents = 3;
1010         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1011         break;
1012     case D3DSIO_M3x4:
1013         nComponents = 4;
1014         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1015         break;
1016     case D3DSIO_M3x3:
1017         nComponents = 3;
1018         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1019         break;
1020     case D3DSIO_M3x2:
1021         nComponents = 2;
1022         tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1023         break;
1024     default:
1025         break;
1026     }
1027     
1028     for (i = 0; i < nComponents; i++) {
1029         tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1030         tmpArg.src[1] = arg->src[1]+i;
1031         vshader_hw_map2gl(&tmpArg);
1032     }
1033 }
1034
1035 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1036     or GLSL and send it to the card */
1037 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1038     IWineD3DVertexShader *iface,
1039     CONST DWORD *pFunction) {
1040
1041     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1042     SHADER_BUFFER buffer;
1043
1044 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1045         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1046     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1047         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1048         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1049         This->fixupVertexBufferSize = PGMSIZE;
1050         This->fixupVertexBuffer[0] = 0;
1051     }
1052     buffer.buffer = This->device->fixupVertexBuffer;
1053 #else
1054     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
1055 #endif
1056     buffer.bsize = 0;
1057     buffer.lineNo = 0;
1058
1059     /* TODO: Optionally, generate the GLSL shader instead */
1060     if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1061         /*  Create the hw ARB shader */
1062         shader_addline(&buffer, "!!ARBvp1.0\n");
1063
1064         /* Mesa supports only 95 constants */
1065         if (GL_VEND(MESA) || GL_VEND(WINE))
1066             This->baseShader.limits.constant_float = 
1067                 min(95, This->baseShader.limits.constant_float);
1068
1069         shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1070             This->baseShader.limits.constant_float, 
1071             This->baseShader.limits.constant_float - 1);
1072
1073         /** Call the base shader generation routine to generate most 
1074             of the vertex shader string for us */
1075         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1076
1077         shader_addline(&buffer, "END\n\0"); 
1078
1079         /* TODO: change to resource.glObjectHandle or something like that */
1080         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1081
1082         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1083         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1084
1085         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1086         /* Create the program and check for errors */
1087         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1088             buffer.bsize, buffer.buffer));
1089
1090         if (glGetError() == GL_INVALID_OPERATION) {
1091             GLint errPos;
1092             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1093             FIXME("HW VertexShader Error at position %d: %s\n",
1094                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1095             This->baseShader.prgId = -1;
1096         }
1097     }
1098
1099 #if 1 /* if were using the data buffer of device then we don't need to free it */
1100   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1101 #endif
1102 }
1103
1104 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1105   /**
1106    * TODO: use the NV_vertex_program (or 1_1) extension
1107    *  and specifics vendors (ARB_vertex_program??) variants for it
1108    */
1109   return TRUE;
1110 }
1111
1112 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1113     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1114         
1115     /** Vertex Shader Temporary Registers */
1116     WINED3DSHADERVECTOR R[12];
1117       /*D3DSHADERSCALAR A0;*/
1118     WINED3DSHADERVECTOR A[1];
1119     /** temporary Vector for modifier management */
1120     WINED3DSHADERVECTOR d;
1121     WINED3DSHADERVECTOR s[3];
1122     /** parser datas */
1123     const DWORD* pToken = This->baseShader.function;
1124     const SHADER_OPCODE* curOpcode = NULL;
1125     /** functions parameters */
1126     WINED3DSHADERVECTOR* p[6];
1127     WINED3DSHADERVECTOR* p_send[6];
1128     DWORD i;
1129
1130     /** init temporary register */
1131     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1132
1133     /* vshader_program_parse(vshader); */
1134 #if 0 /* Must not be 1 in cvs */
1135     TRACE("Input:\n");
1136     TRACE_VSVECTOR(This->data->C[0]);
1137     TRACE_VSVECTOR(This->data->C[1]);
1138     TRACE_VSVECTOR(This->data->C[2]);
1139     TRACE_VSVECTOR(This->data->C[3]);
1140     TRACE_VSVECTOR(This->data->C[4]);
1141     TRACE_VSVECTOR(This->data->C[5]);
1142     TRACE_VSVECTOR(This->data->C[6]);
1143     TRACE_VSVECTOR(This->data->C[7]);
1144     TRACE_VSVECTOR(This->data->C[8]);
1145     TRACE_VSVECTOR(This->data->C[64]);
1146     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1147     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1148     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1149     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1150     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1151     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1152     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1153     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1154     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1155 #endif
1156
1157     TRACE_VSVECTOR(vshader->data->C[64]);
1158     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1159
1160     /* the first dword is the version tag */
1161     /* TODO: parse it */
1162
1163     if (shader_is_vshader_version(*pToken)) { /** version */
1164         ++pToken;
1165     }
1166     while (D3DVS_END() != *pToken) {
1167         if (shader_is_comment(*pToken)) { /** comment */
1168             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1169             ++pToken;
1170             pToken += comment_len;
1171             continue ;
1172         }
1173         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1174         ++pToken;
1175         if (NULL == curOpcode) {
1176             i = 0;
1177             /* unknown current opcode ... */
1178             /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1179             while (*pToken & 0x80000000) {
1180                 if (i == 0) {
1181                     FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1182                 }
1183                 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1184                 shader_dump_param((IWineD3DBaseShader*) This, *pToken, i);
1185                 TRACE("\n");
1186                 ++i;
1187                 ++pToken;
1188             }
1189             /* return FALSE; */
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 len = 0;
1504     DWORD i;
1505     TRACE("(%p) : Parsing programme\n", This);
1506
1507     /* Initialise vertex input arrays */
1508     This->namedArrays = FALSE;
1509     This->declaredArrays = FALSE;
1510     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1511         This->arrayUsageMap[i] = -1;
1512
1513     if (NULL != pToken) {
1514         while (D3DVS_END() != *pToken) {
1515             if (shader_is_vshader_version(*pToken)) { /** version */
1516                 vshader_set_version(This, *pToken);
1517                 ++pToken;
1518                 ++len;
1519                 continue;
1520             }
1521             if (shader_is_comment(*pToken)) { /** comment */
1522                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1523                 ++pToken;
1524                 TRACE("//%s\n", (char*)pToken);
1525                 pToken += comment_len;
1526                 len += comment_len + 1;
1527                 continue;
1528             }
1529             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1530             ++pToken;
1531             ++len;
1532             if (NULL == curOpcode) {
1533                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1534                 while (*pToken & 0x80000000) {
1535                     /* unknown current opcode ... */
1536                     FIXME("unrecognized opcode: %08lx", *pToken);
1537                     ++pToken;
1538                     ++len;
1539                     TRACE("\n");
1540                 }
1541
1542             } else {
1543                 if (curOpcode->opcode == D3DSIO_DCL) {
1544
1545                     DWORD usage = *pToken;
1546                     DWORD param = *(pToken + 1);
1547
1548                     parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1549                     shader_program_dump_decl_usage(usage, param);
1550                     shader_dump_ins_modifiers(param);
1551                     TRACE(" ");
1552                     shader_dump_param((IWineD3DBaseShader*) This, param, 0);
1553                     pToken += 2;
1554                     len += 2;
1555
1556                 } else 
1557                     if (curOpcode->opcode == D3DSIO_DEF) {
1558                         TRACE("def c%lu = ", *pToken & 0xFF);
1559                         ++pToken;
1560                         ++len;
1561                         TRACE("%f ,", *(float *)pToken);
1562                         ++pToken;
1563                         ++len;
1564                         TRACE("%f ,", *(float *)pToken);
1565                         ++pToken;
1566                         ++len;
1567                         TRACE("%f ,", *(float *)pToken);
1568                         ++pToken;
1569                         ++len;
1570                         TRACE("%f", *(float *)pToken);
1571                         ++pToken;
1572                         ++len;
1573                 } else {
1574                     TRACE("%s", curOpcode->name);
1575                     if (curOpcode->num_params > 0) {
1576                         shader_dump_ins_modifiers(*pToken);
1577                         TRACE(" ");
1578                         shader_dump_param((IWineD3DBaseShader*) This, *pToken, 0);
1579                         ++pToken;
1580                         ++len;
1581                         for (i = 1; i < curOpcode->num_params; ++i) {
1582                             TRACE(", ");
1583                             shader_dump_param((IWineD3DBaseShader*) This, *pToken, 1);
1584                             ++pToken;
1585                             ++len;
1586                         }
1587                     }
1588                 }
1589                 TRACE("\n");
1590             }
1591         }
1592         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1593     } else {
1594         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1595     }
1596
1597 /* Handy for debugging using numbered arrays instead of named arrays */
1598 #if 1
1599     /* TODO: using numbered arrays for software shaders makes things easier */
1600     This->declaredArrays = TRUE;
1601 #endif
1602
1603     /* named arrays and declared arrays are mutually exclusive */
1604     if (This->declaredArrays) 
1605         This->namedArrays = FALSE;
1606
1607     /* Generate HW shader in needed */
1608     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1609 #if 1
1610         IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1611 #endif
1612     }
1613
1614     /* copy the function ... because it will certainly be released by application */
1615     if (NULL != pFunction) {
1616         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1617         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1618     } else {
1619         This->baseShader.function = NULL;
1620     }
1621     return WINED3D_OK;
1622 }
1623
1624 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1625 {
1626     /*** IUnknown methods ***/
1627     IWineD3DVertexShaderImpl_QueryInterface,
1628     IWineD3DVertexShaderImpl_AddRef,
1629     IWineD3DVertexShaderImpl_Release,
1630     /*** IWineD3DBase methods ***/
1631     IWineD3DVertexShaderImpl_GetParent,
1632     /*** IWineD3DBaseShader methods ***/
1633     IWineD3DVertexShaderImpl_SetFunction,
1634     /*** IWineD3DVertexShader methods ***/
1635     IWineD3DVertexShaderImpl_GetDevice,
1636     IWineD3DVertexShaderImpl_GetFunction
1637 };