wined3d: Move PARAM C[] program.env[] into baseshader and out of vertex shaders.
[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, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
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,   3, 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         /** Call the base shader generation routine to generate most 
1077             of the vertex shader string for us */
1078         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1079
1080         shader_addline(&buffer, "END\n\0"); 
1081
1082         /* TODO: change to resource.glObjectHandle or something like that */
1083         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1084
1085         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1086         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1087
1088         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1089         /* Create the program and check for errors */
1090         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1091             buffer.bsize, buffer.buffer));
1092
1093         if (glGetError() == GL_INVALID_OPERATION) {
1094             GLint errPos;
1095             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1096             FIXME("HW VertexShader Error at position %d: %s\n",
1097                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1098             This->baseShader.prgId = -1;
1099         }
1100     }
1101
1102 #if 1 /* if were using the data buffer of device then we don't need to free it */
1103   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1104 #endif
1105 }
1106
1107 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1108   /**
1109    * TODO: use the NV_vertex_program (or 1_1) extension
1110    *  and specifics vendors (ARB_vertex_program??) variants for it
1111    */
1112   return TRUE;
1113 }
1114
1115 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1116     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1117     DWORD opcode_token;   
1118  
1119     /** Vertex Shader Temporary Registers */
1120     WINED3DSHADERVECTOR R[12];
1121       /*D3DSHADERSCALAR A0;*/
1122     WINED3DSHADERVECTOR A[1];
1123     /** temporary Vector for modifier management */
1124     WINED3DSHADERVECTOR d;
1125     WINED3DSHADERVECTOR s[3];
1126     /** parser datas */
1127     const DWORD* pToken = This->baseShader.function;
1128     const SHADER_OPCODE* curOpcode = NULL;
1129     /** functions parameters */
1130     WINED3DSHADERVECTOR* p[6];
1131     WINED3DSHADERVECTOR* p_send[6];
1132     DWORD i;
1133
1134     /** init temporary register */
1135     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1136
1137     /* vshader_program_parse(vshader); */
1138 #if 0 /* Must not be 1 in cvs */
1139     TRACE("Input:\n");
1140     TRACE_VSVECTOR(This->data->C[0]);
1141     TRACE_VSVECTOR(This->data->C[1]);
1142     TRACE_VSVECTOR(This->data->C[2]);
1143     TRACE_VSVECTOR(This->data->C[3]);
1144     TRACE_VSVECTOR(This->data->C[4]);
1145     TRACE_VSVECTOR(This->data->C[5]);
1146     TRACE_VSVECTOR(This->data->C[6]);
1147     TRACE_VSVECTOR(This->data->C[7]);
1148     TRACE_VSVECTOR(This->data->C[8]);
1149     TRACE_VSVECTOR(This->data->C[64]);
1150     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1151     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1152     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1153     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1154     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1155     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1156     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1157     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1158     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1159 #endif
1160
1161     TRACE_VSVECTOR(vshader->data->C[64]);
1162     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1163
1164     /* the first dword is the version tag */
1165     /* TODO: parse it */
1166
1167     if (shader_is_vshader_version(*pToken)) { /** version */
1168         ++pToken;
1169     }
1170     while (D3DVS_END() != *pToken) {
1171         if (shader_is_comment(*pToken)) { /** comment */
1172             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1173             ++pToken;
1174             pToken += comment_len;
1175             continue ;
1176         }
1177
1178         opcode_token = *pToken++;
1179         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1180
1181         if (NULL == curOpcode) {
1182             FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1183             pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1184             /* return FALSE; */
1185
1186         } else {
1187             if (curOpcode->num_params > 0) {
1188                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1189                 for (i = 0; i < curOpcode->num_params; ++i) {
1190                     DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1191                     DWORD regtype = shader_get_regtype(pToken[i]);
1192     
1193                     switch (regtype) {
1194                     case D3DSPR_TEMP:
1195                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1196                         p[i] = &R[reg];
1197                         break;
1198                     case D3DSPR_INPUT:
1199                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1200                         p[i] = &input->V[reg];
1201                         break;
1202                     case D3DSPR_CONST:
1203                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1204                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1205                         } else {
1206                             p[i] = &This->data->C[reg];
1207                         }
1208                         break;
1209                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1210                         if (0 != reg) {
1211                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1212                             reg = 0;
1213                         }
1214                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1215                         p[i] = &A[reg];
1216                         break;
1217                     case D3DSPR_RASTOUT:
1218                         switch (reg) {
1219                         case D3DSRO_POSITION:
1220                             p[i] = &output->oPos;
1221                             break;
1222                         case D3DSRO_FOG:
1223                             p[i] = &output->oFog;
1224                             break;
1225                         case D3DSRO_POINT_SIZE:
1226                             p[i] = &output->oPts;
1227                             break;
1228                         }
1229                         break;
1230                     case D3DSPR_ATTROUT:
1231                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1232                         p[i] = &output->oD[reg];
1233                         break;
1234                     case D3DSPR_TEXCRDOUT:
1235                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1236                         p[i] = &output->oT[reg];
1237                         break;
1238                     /* TODO Decls and defs */
1239 #if 0
1240                     case D3DSPR_DCL:
1241                     case D3DSPR_DEF:
1242 #endif
1243                     default:
1244                         break;
1245                     }
1246
1247                     if (i > 0) { /* input reg */
1248                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1249                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1250
1251                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1252                             /* TRACE("p[%d] not swizzled\n", i); */
1253                             p_send[i] = p[i];
1254                         } else {
1255                             DWORD swizzle_x = swizzle & 0x03;
1256                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1257                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1258                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1259                             /* TRACE("p[%d] swizzled\n", i); */
1260                             float* tt = (float*) p[i];
1261                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1262                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1263                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1264                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1265                             p_send[i] = &s[i];
1266                         }
1267                     } else { /* output reg */
1268                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1269                             p_send[i] = p[i];
1270                         } else {
1271                             p_send[i] = &d; /* to be post-processed for modifiers management */
1272                         }
1273                     }
1274                 }
1275             }
1276
1277             switch (curOpcode->num_params) {
1278             case 0:
1279                 curOpcode->soft_fct();
1280                 break;
1281             case 1:
1282                 curOpcode->soft_fct(p_send[0]);
1283             break;
1284             case 2:
1285                 curOpcode->soft_fct(p_send[0], p_send[1]);
1286                 break;
1287             case 3:
1288                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1289                 break;
1290             case 4:
1291                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1292                 break;
1293             case 5:
1294                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1295                 break;
1296             case 6:
1297                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1298                 break;
1299             default:
1300                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1301             }
1302
1303             /* check if output reg modifier post-process */
1304             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1305                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1306                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1307                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1308                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1309             }
1310 #if 0
1311             TRACE_VSVECTOR(output->oPos);
1312             TRACE_VSVECTOR(output->oD[0]);
1313             TRACE_VSVECTOR(output->oD[1]);
1314             TRACE_VSVECTOR(output->oT[0]);
1315             TRACE_VSVECTOR(output->oT[1]);
1316             TRACE_VSVECTOR(R[0]);
1317             TRACE_VSVECTOR(R[1]);
1318             TRACE_VSVECTOR(R[2]);
1319             TRACE_VSVECTOR(R[3]);
1320             TRACE_VSVECTOR(R[4]);
1321             TRACE_VSVECTOR(R[5]);
1322 #endif
1323
1324             /* to next opcode token */
1325             pToken += curOpcode->num_params;
1326         }
1327 #if 0
1328         TRACE("End of current instruction:\n");
1329         TRACE_VSVECTOR(output->oPos);
1330         TRACE_VSVECTOR(output->oD[0]);
1331         TRACE_VSVECTOR(output->oD[1]);
1332         TRACE_VSVECTOR(output->oT[0]);
1333         TRACE_VSVECTOR(output->oT[1]);
1334         TRACE_VSVECTOR(R[0]);
1335         TRACE_VSVECTOR(R[1]);
1336         TRACE_VSVECTOR(R[2]);
1337         TRACE_VSVECTOR(R[3]);
1338         TRACE_VSVECTOR(R[4]);
1339         TRACE_VSVECTOR(R[5]);
1340 #endif
1341     }
1342 #if 0 /* Must not be 1 in cvs */
1343     TRACE("Output:\n");
1344     TRACE_VSVECTOR(output->oPos);
1345     TRACE_VSVECTOR(output->oD[0]);
1346     TRACE_VSVECTOR(output->oD[1]);
1347     TRACE_VSVECTOR(output->oT[0]);
1348     TRACE_VSVECTOR(output->oT[1]);
1349 #endif
1350     return WINED3D_OK;
1351 }
1352
1353 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1354     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1355     FIXME("(%p) : stub\n", This);
1356     return WINED3D_OK;
1357 }
1358
1359 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1360     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1361     FIXME("(%p) : stub\n", This);
1362     return WINED3D_OK;
1363 }
1364
1365 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1366     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1367     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1368         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1369         return WINED3DERR_INVALIDCALL;
1370     }
1371     if (NULL == pConstantData) {
1372         return WINED3DERR_INVALIDCALL;
1373     }
1374     FIXME("(%p) : stub\n", This);
1375     return WINED3D_OK;
1376 }
1377
1378 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1379     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1380     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1381     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1382         return WINED3DERR_INVALIDCALL;
1383     }
1384     if (NULL == pConstantData) {
1385         return WINED3DERR_INVALIDCALL;
1386     }
1387     FIXME("(%p) : stub\n", This);
1388     return WINED3D_OK;
1389 }
1390
1391 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1392     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1393     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1394         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1395         return WINED3DERR_INVALIDCALL;
1396     }
1397     if (NULL == pConstantData) {
1398         return WINED3DERR_INVALIDCALL;
1399     }
1400     FIXME("(%p) : stub\n", This);
1401     return WINED3D_OK;
1402 }
1403
1404 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1405     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1406     FIXME("(%p) : stub\n", This);
1407     return WINED3D_OK;
1408 }
1409
1410 #endif
1411
1412 /* *******************************************
1413    IWineD3DVertexShader IUnknown parts follow
1414    ******************************************* */
1415 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1416 {
1417     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1418     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1419     if (IsEqualGUID(riid, &IID_IUnknown) 
1420         || IsEqualGUID(riid, &IID_IWineD3DBase)
1421         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1422         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1423         IUnknown_AddRef(iface);
1424         *ppobj = This;
1425         return S_OK;
1426     }
1427     *ppobj = NULL;
1428     return E_NOINTERFACE;
1429 }
1430
1431 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1432     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1433     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1434     return InterlockedIncrement(&This->ref);
1435 }
1436
1437 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1438     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1439     ULONG ref;
1440     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1441     ref = InterlockedDecrement(&This->ref);
1442     if (ref == 0) {
1443         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1444         HeapFree(GetProcessHeap(), 0, This);
1445     }
1446     return ref;
1447 }
1448
1449 /* *******************************************
1450    IWineD3DVertexShader IWineD3DVertexShader parts follow
1451    ******************************************* */
1452
1453 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1454     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1455     
1456     *parent = This->parent;
1457     IUnknown_AddRef(*parent);
1458     TRACE("(%p) : returning %p\n", This, *parent);
1459     return WINED3D_OK;
1460 }
1461
1462 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1463     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1464     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1465     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1466     TRACE("(%p) returning %p\n", This, *pDevice);
1467     return WINED3D_OK;
1468 }
1469
1470 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1471     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1472     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1473
1474     if (NULL == pData) {
1475         *pSizeOfData = This->baseShader.functionLength;
1476         return WINED3D_OK;
1477     }
1478     if (*pSizeOfData < This->baseShader.functionLength) {
1479         *pSizeOfData = This->baseShader.functionLength;
1480         return WINED3DERR_MOREDATA;
1481     }
1482     if (NULL == This->baseShader.function) { /* no function defined */
1483         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1484         (*(DWORD **) pData) = NULL;
1485     } else {
1486         if(This->baseShader.functionLength == 0){
1487
1488         }
1489         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1490         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1491     }
1492     return WINED3D_OK;
1493 }
1494
1495 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1496     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1497     const DWORD* pToken = pFunction;
1498     const SHADER_OPCODE* curOpcode = NULL;
1499     DWORD opcode_token;
1500     DWORD len = 0;
1501     DWORD i;
1502     TRACE("(%p) : Parsing programme\n", This);
1503
1504     /* Initialise vertex input arrays */
1505     This->namedArrays = FALSE;
1506     This->declaredArrays = FALSE;
1507     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1508         This->arrayUsageMap[i] = -1;
1509
1510     if (NULL != pToken) {
1511         while (D3DVS_END() != *pToken) {
1512             if (shader_is_vshader_version(*pToken)) { /** version */
1513                 vshader_set_version(This, *pToken);
1514                 ++pToken;
1515                 ++len;
1516                 continue;
1517             }
1518             if (shader_is_comment(*pToken)) { /** comment */
1519                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1520                 ++pToken;
1521                 TRACE("//%s\n", (char*)pToken);
1522                 pToken += comment_len;
1523                 len += comment_len + 1;
1524                 continue;
1525             }
1526
1527             opcode_token = *pToken++;
1528             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1529             len++;
1530
1531             if (NULL == curOpcode) {
1532                 int tokens_read;
1533
1534                 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1535                 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1536                 pToken += tokens_read;
1537                 len += tokens_read;
1538
1539             } else {
1540                 if (curOpcode->opcode == D3DSIO_DCL) {
1541
1542                     DWORD usage = *pToken;
1543                     DWORD param = *(pToken + 1);
1544
1545                     parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1546                     shader_program_dump_decl_usage(usage, param);
1547                     shader_dump_ins_modifiers(param);
1548                     TRACE(" ");
1549                     shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1550                     pToken += 2;
1551                     len += 2;
1552
1553                 } else 
1554                     if (curOpcode->opcode == D3DSIO_DEF) {
1555                         TRACE("def c%lu = ", *pToken & 0xFF);
1556                         ++pToken;
1557                         ++len;
1558                         TRACE("%f ,", *(float *)pToken);
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                 } else {
1571
1572                     DWORD param, addr_token;
1573                     int tokens_read;
1574
1575                     /* Print out predication source token first - it follows
1576                      * the destination token. */
1577                     if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1578                         TRACE("(");
1579                         shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1580                         TRACE(") ");
1581                     }
1582
1583                     TRACE("%s", curOpcode->name);
1584                     if (curOpcode->num_params > 0) {
1585
1586                         /* Destination token */
1587                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1588                             pToken, &param, &addr_token);
1589                         pToken += tokens_read;
1590                         len += tokens_read;
1591
1592                         shader_dump_ins_modifiers(param);
1593                         TRACE(" ");
1594                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1595
1596                         /* Predication token - already printed out, just skip it */
1597                         if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1598                             pToken++;
1599                             len++;
1600                         }
1601
1602                         /* Other source tokens */
1603                         for (i = 1; i < curOpcode->num_params; ++i) {
1604
1605                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1606                                pToken, &param, &addr_token);
1607                             pToken += tokens_read;
1608                             len += tokens_read;
1609
1610                             TRACE(", ");
1611                             shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1612                         }
1613                     }
1614                 }
1615                 TRACE("\n");
1616             }
1617         }
1618         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1619     } else {
1620         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1621     }
1622
1623 /* Handy for debugging using numbered arrays instead of named arrays */
1624 #if 1
1625     /* TODO: using numbered arrays for software shaders makes things easier */
1626     This->declaredArrays = TRUE;
1627 #endif
1628
1629     /* named arrays and declared arrays are mutually exclusive */
1630     if (This->declaredArrays) 
1631         This->namedArrays = FALSE;
1632
1633     /* Generate HW shader in needed */
1634     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1635 #if 1
1636         IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1637 #endif
1638     }
1639
1640     /* copy the function ... because it will certainly be released by application */
1641     if (NULL != pFunction) {
1642         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1643         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1644     } else {
1645         This->baseShader.function = NULL;
1646     }
1647     return WINED3D_OK;
1648 }
1649
1650 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1651 {
1652     /*** IUnknown methods ***/
1653     IWineD3DVertexShaderImpl_QueryInterface,
1654     IWineD3DVertexShaderImpl_AddRef,
1655     IWineD3DVertexShaderImpl_Release,
1656     /*** IWineD3DBase methods ***/
1657     IWineD3DVertexShaderImpl_GetParent,
1658     /*** IWineD3DBaseShader methods ***/
1659     IWineD3DVertexShaderImpl_SetFunction,
1660     /*** IWineD3DVertexShader methods ***/
1661     IWineD3DVertexShaderImpl_GetDevice,
1662     IWineD3DVertexShaderImpl_GetFunction
1663 };