wined3d: Break out arithmetic instruction processing.
[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
478 /**
479  * log, exp, frc, m*x* seems to be macros ins ... to see
480  */
481 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
482
483     /* Arithmetic */ 
484     {D3DSIO_NOP,  "nop",  "NOP", 0, vshader_nop,  vshader_hw_map2gl, 0, 0},
485     {D3DSIO_MOV,  "mov",  "MOV", 2, vshader_mov,  vshader_hw_map2gl, 0, 0},
486     {D3DSIO_ADD,  "add",  "ADD", 3, vshader_add,  vshader_hw_map2gl, 0, 0},
487     {D3DSIO_SUB,  "sub",  "SUB", 3, vshader_sub,  vshader_hw_map2gl, 0, 0},
488     {D3DSIO_MAD,  "mad",  "MAD", 4, vshader_mad,  vshader_hw_map2gl, 0, 0},
489     {D3DSIO_MUL,  "mul",  "MUL", 3, vshader_mul,  vshader_hw_map2gl, 0, 0},
490     {D3DSIO_RCP,  "rcp",  "RCP", 2, vshader_rcp,  vshader_hw_map2gl, 0, 0},
491     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, vshader_rsq,  vshader_hw_map2gl, 0, 0},
492     {D3DSIO_DP3,  "dp3",  "DP3", 3, vshader_dp3,  vshader_hw_map2gl, 0, 0},
493     {D3DSIO_DP4,  "dp4",  "DP4", 3, vshader_dp4,  vshader_hw_map2gl, 0, 0},
494     {D3DSIO_MIN,  "min",  "MIN", 3, vshader_min,  vshader_hw_map2gl, 0, 0},
495     {D3DSIO_MAX,  "max",  "MAX", 3, vshader_max,  vshader_hw_map2gl, 0, 0},
496     {D3DSIO_SLT,  "slt",  "SLT", 3, vshader_slt,  vshader_hw_map2gl, 0, 0},
497     {D3DSIO_SGE,  "sge",  "SGE", 3, vshader_sge,  vshader_hw_map2gl, 0, 0},
498     {D3DSIO_ABS,  "abs",  "ABS", 2, vshader_abs,  vshader_hw_map2gl, 0, 0},
499     {D3DSIO_EXP,  "exp",  "EX2", 2, vshader_exp,  vshader_hw_map2gl, 0, 0},
500     {D3DSIO_LOG,  "log",  "LG2", 2, vshader_log,  vshader_hw_map2gl, 0, 0},
501     {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, 0, 0},
502     {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, 0, 0},
503     {D3DSIO_LIT,  "lit",  "LIT", 2, vshader_lit,  vshader_hw_map2gl, 0, 0},
504     {D3DSIO_DST,  "dst",  "DST", 3, vshader_dst,  vshader_hw_map2gl, 0, 0},
505     {D3DSIO_LRP,  "lrp",  "LRP", 4, vshader_lrp,  vshader_hw_map2gl, 0, 0},
506     {D3DSIO_FRC,  "frc",  "FRC", 2, vshader_frc,  vshader_hw_map2gl, 0, 0},
507     {D3DSIO_POW,  "pow",  "POW", 3, vshader_pow,  NULL, 0, 0},
508     {D3DSIO_CRS,  "crs",  "XPS", 3, vshader_crs,  NULL, 0, 0},
509     /* TODO: sng can possibly be performed a  s
510         RCP tmp, vec
511         MUL out, tmp, vec*/
512     {D3DSIO_SGN,  "sng",  NULL,  2, vshader_sng,  NULL,   0, 0},
513     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
514         DP3 tmp , vec, vec;
515         RSQ tmp, tmp.x;
516         MUL vec.xyz, vec, tmp;
517     but I think this is better because it accounts for w properly.
518         DP3 tmp , vec, vec;
519         RSQ tmp, tmp.x;
520         MUL vec, vec, tmp;
521
522     */
523     {D3DSIO_NRM,      "nrm",      NULL,   2, vshader_nrm,    NULL, 0, 0},
524     {D3DSIO_SINCOS,   "sincos",   NULL,   2, vshader_sincos, NULL, 0, 0},
525
526     /* Matrix */
527     {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, NULL, 0, 0},
528     {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, NULL, 0, 0},
529     {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, NULL, 0, 0},
530     {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, NULL, 0, 0},
531     {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, NULL, 0, 0},
532
533     /* Declare registers */
534     {D3DSIO_DCL,      "dcl",      NULL,                  2, vshader_dcl,     NULL, 0, 0},
535
536     /* Constant definitions */
537     {D3DSIO_DEF,      "def",      NULL,                  5, vshader_def,     NULL, 0, 0},
538     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, vshader_defb,    NULL, 0, 0},
539     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, vshader_defi,    NULL, 0, 0},
540
541     /* Flow control - requires GLSL or software shaders */
542     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   1, vshader_rep,     NULL, 0, 0},
543     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, vshader_endrep,  NULL, 0, 0},
544     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   1, vshader_if,      NULL, 0, 0},
545     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, vshader_ifc,     NULL, 0, 0},
546     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   0, vshader_else,    NULL, 0, 0},
547     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   0, vshader_endif,   NULL, 0, 0},
548     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   0, vshader_break,   NULL, 0, 0},
549     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, vshader_breakc,  NULL, 0, 0},
550     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   1, vshader_breakp,  NULL, 0, 0},
551     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, vshader_call,    NULL, 0, 0},
552     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, vshader_callnz,  NULL, 0, 0},
553     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, vshader_loop,    NULL, 0, 0},
554     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, vshader_ret,     NULL, 0, 0},
555     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, vshader_endloop, NULL, 0, 0},
556     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, vshader_label,   NULL, 0, 0},
557
558     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, vshader_mova,    NULL, 0, 0},
559     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, vshader_setp,    NULL, 0, 0},
560     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, vshader_texldl,  NULL, 0, 0},
561     {0,               NULL,       NULL,   0, NULL,            0, 0}
562 };
563
564 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
565   static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
566   static const char swizzle_reg_chars[] = "xyzw";
567
568   DWORD reg = param & D3DSP_REGNUM_MASK; 
569   DWORD regtype = shader_get_regtype(param);
570
571   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
572
573   switch (regtype) {
574   case D3DSPR_TEMP:
575     TRACE("r%lu", reg);
576     break;
577   case D3DSPR_INPUT:
578     TRACE("v%lu", reg);
579     break;
580   case D3DSPR_CONST:
581     TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
582     break;
583   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
584     TRACE("a%lu", reg);
585     break;
586   case D3DSPR_RASTOUT:
587     TRACE("%s", rastout_reg_names[reg]);
588     break;
589   case D3DSPR_ATTROUT:
590     TRACE("oD%lu", reg);
591     break;
592   case D3DSPR_TEXCRDOUT:
593     TRACE("oT%lu", reg);
594     break;
595   case D3DSPR_CONSTINT:
596     TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
597     break;
598   case D3DSPR_CONSTBOOL:
599     TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
600     break;
601   case D3DSPR_LABEL:
602     TRACE("l%lu", reg);
603     break;
604   case D3DSPR_LOOP:
605     TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
606     break;
607   case D3DSPR_SAMPLER:
608     TRACE("s%lu", reg);
609     break;
610   default:
611     FIXME("Unknown %lu reg %lu\n",regtype, reg);
612     break;
613   }
614
615   if (!input) {
616     /** operand output */
617     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
618       if (param & D3DSP_WRITEMASK_0) TRACE(".x");
619       if (param & D3DSP_WRITEMASK_1) TRACE(".y");
620       if (param & D3DSP_WRITEMASK_2) TRACE(".z");
621       if (param & D3DSP_WRITEMASK_3) TRACE(".w");
622     }
623   } else {
624     /** operand input */
625     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
626     DWORD swizzle_x = swizzle & 0x03;
627     DWORD swizzle_y = (swizzle >> 2) & 0x03;
628     DWORD swizzle_z = (swizzle >> 4) & 0x03;
629     DWORD swizzle_w = (swizzle >> 6) & 0x03;
630     /**
631      * swizzle bits fields:
632      *  WWZZYYXX
633      */
634     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
635       if (swizzle_x == swizzle_y &&
636         swizzle_x == swizzle_z &&
637         swizzle_x == swizzle_w) {
638             TRACE(".%c", swizzle_reg_chars[swizzle_x]);
639       } else {
640         TRACE(".%c%c%c%c",
641         swizzle_reg_chars[swizzle_x],
642         swizzle_reg_chars[swizzle_y],
643         swizzle_reg_chars[swizzle_z],
644         swizzle_reg_chars[swizzle_w]);
645       }
646     }
647   }
648 }
649
650 inline static void vshader_program_dump_decl_usage(
651     IWineD3DVertexShaderImpl *This, DWORD decl, DWORD param) {
652     DWORD regtype = shader_get_regtype(param);
653
654     TRACE("dcl_");
655
656     if (regtype == D3DSPR_SAMPLER) {
657         DWORD ttype = decl & D3DSP_TEXTURETYPE_MASK;
658
659         switch (ttype) {
660             case D3DSTT_2D: TRACE("2d "); break;
661             case D3DSTT_CUBE: TRACE("cube "); break;
662             case D3DSTT_VOLUME: TRACE("volume "); break;
663             default: TRACE("unknown_ttype(%08lx) ", ttype);
664        }
665
666     } else {
667
668         DWORD usage = decl & D3DSP_DCL_USAGE_MASK;
669         DWORD idx = (decl & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
670
671         switch(usage) {
672         case D3DDECLUSAGE_POSITION:
673             TRACE("%s%ld ", "position", idx);
674             break;
675         case D3DDECLUSAGE_BLENDINDICES:
676             TRACE("%s ", "blend");
677             break;
678         case D3DDECLUSAGE_BLENDWEIGHT:
679             TRACE("%s ", "weight");
680             break;
681         case D3DDECLUSAGE_NORMAL:
682             TRACE("%s%ld ", "normal", idx);
683             break;
684         case D3DDECLUSAGE_PSIZE:
685             TRACE("%s ", "psize");
686             break;
687         case D3DDECLUSAGE_COLOR:
688             if(idx == 0)  {
689                 TRACE("%s ", "color");
690             } else {
691                 TRACE("%s ", "specular");
692             }
693             break;
694         case D3DDECLUSAGE_TEXCOORD:
695             TRACE("%s%ld ", "texture", idx);
696             break;
697         case D3DDECLUSAGE_TANGENT:
698             TRACE("%s ", "tangent");
699             break;
700         case D3DDECLUSAGE_BINORMAL:
701             TRACE("%s ", "binormal");
702             break;
703         case D3DDECLUSAGE_TESSFACTOR:
704             TRACE("%s ", "tessfactor");
705             break;
706         case D3DDECLUSAGE_POSITIONT:
707             TRACE("%s%ld ", "positionT", idx);
708             break;
709         case D3DDECLUSAGE_FOG:
710             TRACE("%s ", "fog");
711             break;
712         case D3DDECLUSAGE_DEPTH:
713             TRACE("%s ", "depth");
714             break;
715         case D3DDECLUSAGE_SAMPLE:
716             TRACE("%s ", "sample");
717             break;
718         default:
719             FIXME("Unrecognised dcl %08lx", usage);
720         }
721     }
722 }
723
724 inline static BOOL vshader_is_version_token(DWORD token) {
725   return 0xFFFE0000 == (token & 0xFFFE0000);
726 }
727
728 inline static BOOL vshader_is_comment_token(DWORD token) {
729   return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
730 }
731
732 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
733     /** operand output */
734     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
735       strcat(hwLine, ".");
736       if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
737       if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
738       if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
739       if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
740     }  
741 }
742
743 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
744     static const char swizzle_reg_chars_color_fix[] = "zyxw";
745     static const char swizzle_reg_chars[] = "xyzw";
746     const char* swizzle_regs = NULL;
747     char  tmpReg[255];
748
749     /** operand input */
750     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
751     DWORD swizzle_x = swizzle & 0x03;
752     DWORD swizzle_y = (swizzle >> 2) & 0x03;
753     DWORD swizzle_z = (swizzle >> 4) & 0x03;
754     DWORD swizzle_w = (swizzle >> 6) & 0x03;
755
756     if (is_color) {
757       swizzle_regs = swizzle_reg_chars_color_fix;
758     } else {
759       swizzle_regs = swizzle_reg_chars;
760     }
761
762     /**
763      * swizzle bits fields:
764      *  WWZZYYXX
765      */
766     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
767       if (is_color) {
768         sprintf(tmpReg, ".%c%c%c%c",
769                 swizzle_regs[swizzle_x],
770                 swizzle_regs[swizzle_y],
771                 swizzle_regs[swizzle_z],
772                 swizzle_regs[swizzle_w]);
773         strcat(hwLine, tmpReg);
774       }
775       return ;
776     }
777     if (swizzle_x == swizzle_y &&
778         swizzle_x == swizzle_z &&
779         swizzle_x == swizzle_w)
780     {
781       sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
782       strcat(hwLine, tmpReg);
783     } else {
784       sprintf(tmpReg, ".%c%c%c%c",
785               swizzle_regs[swizzle_x],
786               swizzle_regs[swizzle_y],
787               swizzle_regs[swizzle_z],
788               swizzle_regs[swizzle_w]);
789       strcat(hwLine, tmpReg);
790     }
791 }
792
793 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
794   /* oPos, oFog and oPts in D3D */
795   static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
796
797   DWORD reg = param & D3DSP_REGNUM_MASK;
798   DWORD regtype = shader_get_regtype(param);
799   char  tmpReg[255];
800   BOOL is_color = FALSE;
801
802   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
803       strcat(hwLine, " -");
804   } else {
805       strcat(hwLine, " ");
806   }
807
808   switch (regtype) {
809   case D3DSPR_TEMP:
810     sprintf(tmpReg, "T%lu", reg);
811     strcat(hwLine, tmpReg);
812     break;
813   case D3DSPR_INPUT:
814     if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
815         || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
816         is_color = TRUE;
817     }
818     /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
819     if (This->namedArrays) {
820         sprintf(tmpReg, "namedVertex%lu", reg);
821     } else {
822     /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
823         sprintf(tmpReg, "vertex.attrib[%lu]", reg);
824     }
825     strcat(hwLine, tmpReg);
826     break;
827   case D3DSPR_CONST:
828     /* FIXME: some constants are named so we need a constants map*/
829     if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
830         if (param & D3DVS_ADDRMODE_RELATIVE) {
831             FIXME("Relative addressing not expected for a named constant %lu\n", reg);
832         }
833         sprintf(tmpReg, "const%lu", reg);
834     } else {
835         sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
836     }
837     strcat(hwLine, tmpReg);
838     break;
839   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
840     sprintf(tmpReg, "A%lu", reg);
841     strcat(hwLine, tmpReg);
842     break;
843   case D3DSPR_RASTOUT:
844     sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
845     strcat(hwLine, tmpReg);
846     break;
847   case D3DSPR_ATTROUT:
848     if (reg==0) {
849        strcat(hwLine, "result.color.primary");
850     } else {
851        strcat(hwLine, "result.color.secondary");
852     }
853     break;
854   case D3DSPR_TEXCRDOUT:
855     sprintf(tmpReg, "result.texcoord[%lu]", reg);
856     strcat(hwLine, tmpReg);
857     break;
858   default:
859     FIXME("Unknown reg type %ld %ld\n", regtype, reg);
860     break;
861   }
862
863   if (!is_input) {
864     vshader_program_add_output_param_swizzle(param, is_color, hwLine);
865   } else {
866     vshader_program_add_input_param_swizzle(param, is_color, hwLine);
867   }
868 }
869
870 DWORD MacroExpansion[4*4];
871
872 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
873  
874   int i;
875   int nComponents = 0;
876   DWORD opcode =0;
877   switch(macro_opcode) {
878     case D3DSIO_M4x4:
879       nComponents = 4;
880       opcode = D3DSIO_DP4;
881       break;
882     case D3DSIO_M4x3:
883       nComponents = 3;
884       opcode = D3DSIO_DP4;
885       break;
886     case D3DSIO_M3x4:
887       nComponents = 4;
888       opcode = D3DSIO_DP3;
889       break;
890     case D3DSIO_M3x3:
891       nComponents = 3;
892       opcode = D3DSIO_DP3;
893       break;
894     case D3DSIO_M3x2:
895       nComponents = 2;
896       opcode = D3DSIO_DP3;
897       break;
898     default:
899       break;
900   }
901   for (i = 0; i < nComponents; i++) {
902     MacroExpansion[i*4+0] = opcode;
903     MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
904     MacroExpansion[i*4+2] = *(args+1);
905     MacroExpansion[i*4+3] = (*(args+2))+i;
906   }
907   return nComponents;
908 }
909
910 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
911 {
912     switch(usage & 0xFFFF) {
913         case D3DDECLUSAGE_POSITION:
914             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
915                 TRACE("Setting position to %d\n", arrayNo);
916                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
917                 This->namedArrays = TRUE;
918             } else {
919                 /* TODO: position indexes go from 0-8!!*/
920                 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
921                 /* robots uses positions up to 8, the position arrays are just packed.*/
922                 if ((usage & 0xF0000) >> 16 > 1) {
923                     TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
924                 }
925                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
926                 This->declaredArrays = TRUE;
927             }
928         break;
929         case D3DDECLUSAGE_BLENDINDICES:
930             /* not supported by openGL */
931             TRACE("Setting BLENDINDICES to %d\n", arrayNo);
932             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
933             This->declaredArrays = TRUE;
934             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
935         break;
936         case D3DDECLUSAGE_BLENDWEIGHT:
937             TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
938             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
939             This->namedArrays = TRUE;
940             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
941         break;
942         case D3DDECLUSAGE_NORMAL:
943             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
944                 TRACE("Setting normal to %d\n", arrayNo);
945                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
946                 This->namedArrays = TRUE;
947             } else {
948                 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
949                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
950                 This->declaredArrays = TRUE;
951             }
952         break;
953         case D3DDECLUSAGE_PSIZE:
954             TRACE("Setting PSIZE to %d\n", arrayNo);
955             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
956             This->namedArrays = TRUE;
957             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
958         break;
959         case D3DDECLUSAGE_COLOR:
960             if((usage & 0xF0000) >> 16 == 0)  {
961                 TRACE("Setting DIFFUSE to %d\n", arrayNo);
962                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
963                 This->namedArrays = TRUE;
964             } else {
965                 TRACE("Setting SPECULAR to %d\n", arrayNo);
966                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
967                 This->namedArrays = TRUE;
968             }
969         break;
970         case D3DDECLUSAGE_TEXCOORD:
971             This->namedArrays = TRUE;
972             /* only 7 texture coords have been designed for, so run a quick sanity check */
973             if ((usage & 0xF0000) >> 16 > 7) {
974                 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
975             } else {
976                 TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
977                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
978             }
979         break;
980         /* The following aren't supported by openGL,
981             if we get them then everything needs to be mapped to numbered attributes instead of named ones.
982             this should be caught in the first pass */
983         case D3DDECLUSAGE_TANGENT:
984             TRACE("Setting TANGENT to %d\n", arrayNo);
985             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
986             This->declaredArrays = TRUE;
987         break;
988         case D3DDECLUSAGE_BINORMAL:
989             TRACE("Setting BINORMAL to %d\n", arrayNo);
990             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
991             This->declaredArrays = TRUE;
992         break;
993         case D3DDECLUSAGE_TESSFACTOR:
994             TRACE("Setting TESSFACTOR to %d\n", arrayNo);
995             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
996             This->declaredArrays = TRUE;
997         break;
998         case D3DDECLUSAGE_POSITIONT:
999             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1000                 FIXME("Setting positiont to %d\n", arrayNo);
1001                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1002                 This->namedArrays = TRUE;
1003             } else {
1004                 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1005                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1006                 This->declaredArrays = TRUE;
1007             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1008             }
1009         break;
1010         case D3DDECLUSAGE_FOG:
1011             /* supported by OpenGL */
1012             TRACE("Setting FOG to %d\n", arrayNo);
1013             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
1014             This->namedArrays = TRUE;
1015         break;
1016         case D3DDECLUSAGE_DEPTH:
1017             TRACE("Setting DEPTH to %d\n", arrayNo);
1018             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
1019             This->declaredArrays = TRUE;
1020         break;
1021         case D3DDECLUSAGE_SAMPLE:
1022             TRACE("Setting SAMPLE to %d\n", arrayNo);
1023             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
1024             This->declaredArrays = TRUE;
1025         break;
1026         default:
1027         FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1028     }
1029 }
1030
1031 void vshader_set_version(
1032       IWineD3DVertexShaderImpl *This,
1033       DWORD version) {
1034
1035       DWORD major = (version >> 8) & 0x0F;
1036       DWORD minor = version & 0x0F;
1037
1038       This->baseShader.hex_version = version;
1039       This->baseShader.version = major * 10 + minor;
1040       TRACE("vs_%lu_%lu\n", major, minor);
1041
1042       This->baseShader.limits.texture = 0;
1043
1044       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
1045       This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
1046
1047       switch (This->baseShader.version) {
1048           case 10:
1049           case 11: This->baseShader.limits.temporary = 12;
1050                    This->baseShader.limits.constant_bool = 0;
1051                    This->baseShader.limits.constant_int = 0;
1052                    This->baseShader.limits.address = 1;
1053                    break;
1054       
1055           case 20:
1056           case 21: This->baseShader.limits.temporary = 12;
1057                    This->baseShader.limits.constant_bool = 16;
1058                    This->baseShader.limits.constant_int = 16;
1059                    This->baseShader.limits.address = 1;
1060                    break;
1061
1062           case 30: This->baseShader.limits.temporary = 32;
1063                    This->baseShader.limits.constant_bool = 32;
1064                    This->baseShader.limits.constant_int = 32;
1065                    This->baseShader.limits.address = 1;
1066                    break;
1067
1068           default: This->baseShader.limits.temporary = 12;
1069                    This->baseShader.limits.constant_bool = 0;
1070                    This->baseShader.limits.constant_int = 0;
1071                    This->baseShader.limits.address = 1;
1072                    FIXME("Unrecognized vertex shader version %lu!\n", version);
1073       }
1074 }
1075
1076 /* Map the opcode 1-to-1 to the GL code */
1077 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
1078
1079     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
1080     CONST SHADER_OPCODE* curOpcode = arg->opcode;
1081     SHADER_BUFFER* buffer = arg->buffer;
1082     DWORD dst = arg->dst;
1083     DWORD* src = arg->src;
1084
1085     DWORD dst_regtype = shader_get_regtype(dst);
1086     char tmpLine[256];
1087     unsigned int i;
1088
1089     if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
1090         strcpy(tmpLine, "ARL");
1091     else
1092         strcpy(tmpLine, curOpcode->glname);
1093
1094     if (curOpcode->num_params > 0) {
1095         vshader_program_add_param(This, dst, FALSE, tmpLine);
1096         for (i = 1; i < curOpcode->num_params; ++i) {
1097            strcat(tmpLine, ",");
1098            vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
1099         }
1100     }
1101    shader_addline(buffer, "%s;\n", tmpLine);
1102 }
1103
1104 /**
1105  * Function parser ...
1106  */
1107
1108 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1109     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1110     const DWORD* pToken = pFunction;
1111     const DWORD* pSavedToken = NULL;
1112     const SHADER_OPCODE* curOpcode = NULL;
1113     int nRemInstr = -1;
1114     DWORD i;
1115     SHADER_BUFFER buffer;
1116     char  tmpLine[255];
1117     DWORD addressUsed, tempsUsed;
1118
1119 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1120         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1121     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1122         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1123         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1124         This->fixupVertexBufferSize = PGMSIZE;
1125         This->fixupVertexBuffer[0] = 0;
1126     }
1127     buffer.buffer = This->device->fixupVertexBuffer;
1128 #endif
1129     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
1130     buffer.bsize = 0;
1131     buffer.lineNo = 0;
1132
1133     /* First pass: figure out which temporary and texture registers are used */
1134     shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &addressUsed);
1135     TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
1136
1137     /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded
1138         nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1139         nUseTempRegister    <=  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1140     */
1141
1142     /* Mesa supports only 95 constants */
1143     if (GL_VEND(MESA) || GL_VEND(WINE))
1144         This->baseShader.limits.constant_float = 
1145            min(95, This->baseShader.limits.constant_float);
1146
1147     /* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
1148     shader_addline(&buffer, "!!ARBvp1.0\n");
1149
1150     /* Pre-declare registers */
1151     for (i = 0; i < This->baseShader.limits.temporary; i++) {
1152         if (tempsUsed & (1 << i))
1153             shader_addline(&buffer, "TEMP T%lu;\n", i);
1154     }
1155
1156     for (i = 0; i < This->baseShader.limits.address; i++) {
1157         if (addressUsed & (1 << i))
1158             shader_addline(&buffer, "ADDRESS A%ld;\n", i);
1159     }
1160
1161     /* Why do we need to alias those? */
1162     shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1163         This->baseShader.limits.constant_float, 
1164         This->baseShader.limits.constant_float - 1);            
1165
1166   /** second pass, now generate */
1167   pToken = pFunction;
1168
1169   if (NULL != pToken) {
1170     while (1) {
1171       tmpLine[0] = 0;
1172       if ((nRemInstr >= 0) && (--nRemInstr == -1))
1173             /* Macro is finished, continue normal path */ 
1174             pToken = pSavedToken;
1175       if (D3DVS_END() == *pToken)
1176             break;
1177
1178       /* Skip version */
1179       if (vshader_is_version_token(*pToken)) {
1180             ++pToken;
1181             continue;
1182       }
1183
1184       /* Skip comments */
1185       if (vshader_is_comment_token(*pToken)) {
1186             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1187             ++pToken;
1188             TRACE("#%s\n", (char*)pToken);
1189             pToken += comment_len;
1190             continue;
1191       }
1192
1193       curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1194       ++pToken;
1195       if (NULL == curOpcode) {
1196         /* unknown current opcode ... (shouldn't be any!) */
1197         while (*pToken & 0x80000000) {
1198             FIXME("unrecognized opcode: %08lx\n", *pToken);
1199             ++pToken;
1200         }
1201       } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1202             /* if the token isn't supported by this cross compiler then skip it and its parameters */
1203           
1204             FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1205             pToken += curOpcode->num_params;
1206
1207       } else if (D3DSIO_DEF == curOpcode->opcode) {
1208
1209             /* Handle definitions here, they don't fit well with the
1210              * other instructions below [for now ] */
1211
1212             shader_addline(&buffer, 
1213                 "PARAM const%lu = { %f, %f, %f, %f };\n", *pToken & 0xFF, 
1214                   *(float *) (pToken + 1), 
1215                   *(float *) (pToken + 2), 
1216                   *(float *) (pToken + 3), 
1217                   *(float *) (pToken + 4));
1218
1219             This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1220             pToken += 5;
1221             continue;
1222
1223       } else if (D3DSIO_DCL == curOpcode->opcode) {
1224
1225             /* Handle declarations here, they don't fit well with the
1226              * other instructions below [for now ] */
1227
1228             if (This->namedArrays) {
1229                 const char* attribName = "undefined";
1230                 switch(*pToken & 0xFFFF) {
1231                     case D3DDECLUSAGE_POSITION:
1232                     attribName = "vertex.position";
1233                     break;
1234                     case D3DDECLUSAGE_BLENDINDICES:
1235                     /* not supported by openGL */
1236                     attribName = "vertex.blend";
1237                     break;
1238                     case D3DDECLUSAGE_BLENDWEIGHT:
1239                     attribName = "vertex.weight";
1240                     break;
1241                     case D3DDECLUSAGE_NORMAL:
1242                     attribName = "vertex.normal";
1243                     break;
1244                     case D3DDECLUSAGE_PSIZE:
1245                     attribName = "vertex.psize";
1246                     break;
1247                     case D3DDECLUSAGE_COLOR:
1248                     if((*pToken & 0xF0000) >> 16 == 0)  {
1249                         attribName = "vertex.color";
1250                     } else {
1251                         attribName = "vertex.color.secondary";
1252                     }
1253                     break;
1254                     case D3DDECLUSAGE_TEXCOORD:
1255                     {
1256                         char tmpChar[100];
1257                         tmpChar[0] = 0;
1258                         sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1259                         attribName = tmpChar;
1260                         break;
1261                     }
1262                     /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1263                     case D3DDECLUSAGE_TANGENT:
1264                     attribName = "vertex.tangent";
1265                     break;
1266                     case D3DDECLUSAGE_BINORMAL:
1267                     attribName = "vertex.binormal";
1268                     break;
1269                     case D3DDECLUSAGE_TESSFACTOR:
1270                     attribName = "vertex.tessfactor";
1271                     break;
1272                     case D3DDECLUSAGE_POSITIONT:
1273                     attribName = "vertex.possitionT";
1274                     break;
1275                     case D3DDECLUSAGE_FOG:
1276                     attribName = "vertex.fogcoord";
1277                     break;
1278                     case D3DDECLUSAGE_DEPTH:
1279                     attribName = "vertex.depth";
1280                     break;
1281                     case D3DDECLUSAGE_SAMPLE:
1282                     attribName = "vertex.sample";
1283                     break;
1284                     default:
1285                     FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1286                 }
1287                 {
1288                     ++pToken;
1289                     sprintf(tmpLine, "ATTRIB ");
1290                     vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1291                     if (This->namedArrays) 
1292                         shader_addline(&buffer, "%s = %s;\n", tmpLine, attribName);
1293                 }
1294             } else {
1295                 /* eat the token so it doesn't generate a warning */
1296                 ++pToken;
1297             }
1298             ++pToken;
1299             continue;
1300
1301       /* If a generator function is set, use it */
1302       } else if (curOpcode->hw_fct != NULL) {
1303
1304           SHADER_OPCODE_ARG hw_arg;
1305
1306           hw_arg.shader = (IWineD3DBaseShader*) This;
1307           hw_arg.opcode = curOpcode;
1308           hw_arg.buffer = &buffer;
1309           if (curOpcode->num_params > 0) {
1310               hw_arg.dst = *pToken;
1311
1312               /* FIXME: this does not account for relative address tokens */
1313               for (i = 1; i < curOpcode->num_params; i++)
1314                  hw_arg.src[i-1] = *(pToken + i);
1315           }
1316
1317           curOpcode->hw_fct(&hw_arg);
1318           pToken += curOpcode->num_params;
1319
1320       } else {
1321
1322         switch (curOpcode->opcode) {
1323         case D3DSIO_NOP:
1324             break;
1325         case D3DSIO_M4x4:
1326         case D3DSIO_M4x3:
1327         case D3DSIO_M3x4:
1328         case D3DSIO_M3x3:
1329         case D3DSIO_M3x2:
1330             /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1331             nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1332             /* Save point to next instruction */
1333             pSavedToken = pToken + 3;
1334             /* Execute expanded macro */
1335             pToken = MacroExpansion;
1336             break;
1337
1338         default:
1339             if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1340                 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1341             } else {
1342                 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1343             }
1344
1345             pToken += curOpcode->num_params;
1346         }
1347       }
1348     }
1349     shader_addline(&buffer, "END\n"); 
1350   }
1351
1352   /* finally null terminate the buffer */
1353   buffer.buffer[buffer.bsize] = 0;
1354
1355   /* Check that Vertex Shaders are supported */
1356   if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1357       /*  Create the hw shader */
1358       /* TODO: change to resource.glObjectHandel or something like that */
1359       GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1360       TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1361       GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1362
1363       /* Create the program and check for errors */
1364       GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 
1365           buffer.bsize, buffer.buffer));
1366
1367       if (glGetError() == GL_INVALID_OPERATION) {
1368           GLint errPos;
1369           glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1370           FIXME("HW VertexShader Error at position %d: %s\n",
1371                 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1372           This->baseShader.prgId = -1;
1373       }
1374   }
1375 #if 1 /* if were using the data buffer of device then we don't need to free it */
1376   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1377 #endif
1378 }
1379
1380 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1381   /**
1382    * TODO: use the NV_vertex_program (or 1_1) extension
1383    *  and specifics vendors (ARB_vertex_program??) variants for it
1384    */
1385   return TRUE;
1386 }
1387
1388 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1389     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1390         
1391     /** Vertex Shader Temporary Registers */
1392     WINED3DSHADERVECTOR R[12];
1393       /*D3DSHADERSCALAR A0;*/
1394     WINED3DSHADERVECTOR A[1];
1395     /** temporary Vector for modifier management */
1396     WINED3DSHADERVECTOR d;
1397     WINED3DSHADERVECTOR s[3];
1398     /** parser datas */
1399     const DWORD* pToken = This->baseShader.function;
1400     const SHADER_OPCODE* curOpcode = NULL;
1401     /** functions parameters */
1402     WINED3DSHADERVECTOR* p[4];
1403     WINED3DSHADERVECTOR* p_send[4];
1404     DWORD i;
1405
1406     /** init temporary register */
1407     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1408
1409     /* vshader_program_parse(vshader); */
1410 #if 0 /* Must not be 1 in cvs */
1411     TRACE("Input:\n");
1412     TRACE_VSVECTOR(This->data->C[0]);
1413     TRACE_VSVECTOR(This->data->C[1]);
1414     TRACE_VSVECTOR(This->data->C[2]);
1415     TRACE_VSVECTOR(This->data->C[3]);
1416     TRACE_VSVECTOR(This->data->C[4]);
1417     TRACE_VSVECTOR(This->data->C[5]);
1418     TRACE_VSVECTOR(This->data->C[6]);
1419     TRACE_VSVECTOR(This->data->C[7]);
1420     TRACE_VSVECTOR(This->data->C[8]);
1421     TRACE_VSVECTOR(This->data->C[64]);
1422     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1423     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1424     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1425     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1426     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1427     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1428     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1429     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1430     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1431 #endif
1432
1433     TRACE_VSVECTOR(vshader->data->C[64]);
1434     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1435
1436     /* the first dword is the version tag */
1437     /* TODO: parse it */
1438
1439     if (vshader_is_version_token(*pToken)) { /** version */
1440         ++pToken;
1441     }
1442     while (D3DVS_END() != *pToken) {
1443         if (vshader_is_comment_token(*pToken)) { /** comment */
1444             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1445             ++pToken;
1446             pToken += comment_len;
1447             continue ;
1448         }
1449         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1450         ++pToken;
1451         if (NULL == curOpcode) {
1452             i = 0;
1453             /* unknown current opcode ... */
1454             /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1455             while (*pToken & 0x80000000) {
1456                 if (i == 0) {
1457                     FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1458                 }
1459                 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1460                 vshader_program_dump_vs_param(*pToken, i);
1461                 TRACE("\n");
1462                 ++i;
1463                 ++pToken;
1464             }
1465             /* return FALSE; */
1466         } else {
1467             if (curOpcode->num_params > 0) {
1468                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1469                 for (i = 0; i < curOpcode->num_params; ++i) {
1470                     DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1471                     DWORD regtype = shader_get_regtype(pToken[i]);
1472     
1473                     switch (regtype) {
1474                     case D3DSPR_TEMP:
1475                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1476                         p[i] = &R[reg];
1477                         break;
1478                     case D3DSPR_INPUT:
1479                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1480                         p[i] = &input->V[reg];
1481                         break;
1482                     case D3DSPR_CONST:
1483                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1484                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1485                         } else {
1486                             p[i] = &This->data->C[reg];
1487                         }
1488                         break;
1489                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1490                         if (0 != reg) {
1491                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1492                             reg = 0;
1493                         }
1494                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1495                         p[i] = &A[reg];
1496                         break;
1497                     case D3DSPR_RASTOUT:
1498                         switch (reg) {
1499                         case D3DSRO_POSITION:
1500                             p[i] = &output->oPos;
1501                             break;
1502                         case D3DSRO_FOG:
1503                             p[i] = &output->oFog;
1504                             break;
1505                         case D3DSRO_POINT_SIZE:
1506                             p[i] = &output->oPts;
1507                             break;
1508                         }
1509                         break;
1510                     case D3DSPR_ATTROUT:
1511                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1512                         p[i] = &output->oD[reg];
1513                         break;
1514                     case D3DSPR_TEXCRDOUT:
1515                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1516                         p[i] = &output->oT[reg];
1517                         break;
1518                     /* TODO Decls and defs */
1519 #if 0
1520                     case D3DSPR_DCL:
1521                     case D3DSPR_DEF:
1522 #endif
1523                     default:
1524                         break;
1525                     }
1526
1527                     if (i > 0) { /* input reg */
1528                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1529                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1530
1531                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1532                             /* TRACE("p[%d] not swizzled\n", i); */
1533                             p_send[i] = p[i];
1534                         } else {
1535                             DWORD swizzle_x = swizzle & 0x03;
1536                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1537                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1538                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1539                             /* TRACE("p[%d] swizzled\n", i); */
1540                             float* tt = (float*) p[i];
1541                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1542                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1543                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1544                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1545                             p_send[i] = &s[i];
1546                         }
1547                     } else { /* output reg */
1548                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1549                             p_send[i] = p[i];
1550                         } else {
1551                             p_send[i] = &d; /* to be post-processed for modifiers management */
1552                         }
1553                     }
1554                 }
1555             }
1556
1557             switch (curOpcode->num_params) {
1558             case 0:
1559                 curOpcode->soft_fct();
1560                 break;
1561             case 1:
1562                 curOpcode->soft_fct(p_send[0]);
1563             break;
1564             case 2:
1565                 curOpcode->soft_fct(p_send[0], p_send[1]);
1566                 break;
1567             case 3:
1568                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1569                 break;
1570             case 4:
1571                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1572                 break;
1573             case 5:
1574                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1575                 break;
1576             case 6:
1577                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1578                 break;
1579             default:
1580                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1581             }
1582
1583             /* check if output reg modifier post-process */
1584             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1585                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1586                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1587                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1588                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1589             }
1590 #if 0
1591             TRACE_VSVECTOR(output->oPos);
1592             TRACE_VSVECTOR(output->oD[0]);
1593             TRACE_VSVECTOR(output->oD[1]);
1594             TRACE_VSVECTOR(output->oT[0]);
1595             TRACE_VSVECTOR(output->oT[1]);
1596             TRACE_VSVECTOR(R[0]);
1597             TRACE_VSVECTOR(R[1]);
1598             TRACE_VSVECTOR(R[2]);
1599             TRACE_VSVECTOR(R[3]);
1600             TRACE_VSVECTOR(R[4]);
1601             TRACE_VSVECTOR(R[5]);
1602 #endif
1603
1604             /* to next opcode token */
1605             pToken += curOpcode->num_params;
1606         }
1607 #if 0
1608         TRACE("End of current instruction:\n");
1609         TRACE_VSVECTOR(output->oPos);
1610         TRACE_VSVECTOR(output->oD[0]);
1611         TRACE_VSVECTOR(output->oD[1]);
1612         TRACE_VSVECTOR(output->oT[0]);
1613         TRACE_VSVECTOR(output->oT[1]);
1614         TRACE_VSVECTOR(R[0]);
1615         TRACE_VSVECTOR(R[1]);
1616         TRACE_VSVECTOR(R[2]);
1617         TRACE_VSVECTOR(R[3]);
1618         TRACE_VSVECTOR(R[4]);
1619         TRACE_VSVECTOR(R[5]);
1620 #endif
1621     }
1622 #if 0 /* Must not be 1 in cvs */
1623     TRACE("Output:\n");
1624     TRACE_VSVECTOR(output->oPos);
1625     TRACE_VSVECTOR(output->oD[0]);
1626     TRACE_VSVECTOR(output->oD[1]);
1627     TRACE_VSVECTOR(output->oT[0]);
1628     TRACE_VSVECTOR(output->oT[1]);
1629 #endif
1630     return WINED3D_OK;
1631 }
1632
1633 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1634     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1635     FIXME("(%p) : stub\n", This);
1636     return WINED3D_OK;
1637 }
1638
1639 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1640     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1641     FIXME("(%p) : stub\n", This);
1642     return WINED3D_OK;
1643 }
1644
1645 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1646     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1647     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1648         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1649         return WINED3DERR_INVALIDCALL;
1650     }
1651     if (NULL == pConstantData) {
1652         return WINED3DERR_INVALIDCALL;
1653     }
1654     FIXME("(%p) : stub\n", This);
1655     return WINED3D_OK;
1656 }
1657
1658 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1659     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1660     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1661     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1662         return WINED3DERR_INVALIDCALL;
1663     }
1664     if (NULL == pConstantData) {
1665         return WINED3DERR_INVALIDCALL;
1666     }
1667     FIXME("(%p) : stub\n", This);
1668     return WINED3D_OK;
1669 }
1670
1671 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1672     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1673     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1674         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1675         return WINED3DERR_INVALIDCALL;
1676     }
1677     if (NULL == pConstantData) {
1678         return WINED3DERR_INVALIDCALL;
1679     }
1680     FIXME("(%p) : stub\n", This);
1681     return WINED3D_OK;
1682 }
1683
1684 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1685     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1686     FIXME("(%p) : stub\n", This);
1687     return WINED3D_OK;
1688 }
1689
1690 #endif
1691
1692 /* *******************************************
1693    IWineD3DVertexShader IUnknown parts follow
1694    ******************************************* */
1695 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1696 {
1697     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1698     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1699     if (IsEqualGUID(riid, &IID_IUnknown) 
1700         || IsEqualGUID(riid, &IID_IWineD3DBase)
1701         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1702         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1703         IUnknown_AddRef(iface);
1704         *ppobj = This;
1705         return S_OK;
1706     }
1707     *ppobj = NULL;
1708     return E_NOINTERFACE;
1709 }
1710
1711 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1712     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1713     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1714     return InterlockedIncrement(&This->ref);
1715 }
1716
1717 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1718     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1719     ULONG ref;
1720     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1721     ref = InterlockedDecrement(&This->ref);
1722     if (ref == 0) {
1723         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1724         HeapFree(GetProcessHeap(), 0, This);
1725     }
1726     return ref;
1727 }
1728
1729 /* *******************************************
1730    IWineD3DVertexShader IWineD3DVertexShader parts follow
1731    ******************************************* */
1732
1733 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1734     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1735     
1736     *parent = This->parent;
1737     IUnknown_AddRef(*parent);
1738     TRACE("(%p) : returning %p\n", This, *parent);
1739     return WINED3D_OK;
1740 }
1741
1742 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1743     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1744     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1745     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1746     TRACE("(%p) returning %p\n", This, *pDevice);
1747     return WINED3D_OK;
1748 }
1749
1750 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1751     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1752     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1753
1754     if (NULL == pData) {
1755         *pSizeOfData = This->baseShader.functionLength;
1756         return WINED3D_OK;
1757     }
1758     if (*pSizeOfData < This->baseShader.functionLength) {
1759         *pSizeOfData = This->baseShader.functionLength;
1760         return WINED3DERR_MOREDATA;
1761     }
1762     if (NULL == This->baseShader.function) { /* no function defined */
1763         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1764         (*(DWORD **) pData) = NULL;
1765     } else {
1766         if(This->baseShader.functionLength == 0){
1767
1768         }
1769         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1770         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1771     }
1772     return WINED3D_OK;
1773 }
1774
1775 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1776     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1777     const DWORD* pToken = pFunction;
1778     const SHADER_OPCODE* curOpcode = NULL;
1779     DWORD len = 0;
1780     DWORD i;
1781     TRACE("(%p) : Parsing programme\n", This);
1782
1783     /* Initialise vertex input arrays */
1784     This->namedArrays = FALSE;
1785     This->declaredArrays = FALSE;
1786     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1787         This->arrayUsageMap[i] = -1;
1788
1789     if (NULL != pToken) {
1790         while (D3DVS_END() != *pToken) {
1791             if (vshader_is_version_token(*pToken)) { /** version */
1792                 vshader_set_version(This, *pToken);
1793                 ++pToken;
1794                 ++len;
1795                 continue;
1796             }
1797             if (vshader_is_comment_token(*pToken)) { /** comment */
1798                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1799                 ++pToken;
1800                 TRACE("//%s\n", (char*)pToken);
1801                 pToken += comment_len;
1802                 len += comment_len + 1;
1803                 continue;
1804             }
1805             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1806             ++pToken;
1807             ++len;
1808             if (NULL == curOpcode) {
1809                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1810                 while (*pToken & 0x80000000) {
1811                     /* unknown current opcode ... */
1812                     FIXME("unrecognized opcode: %08lx", *pToken);
1813                     ++pToken;
1814                     ++len;
1815                     TRACE("\n");
1816                 }
1817
1818             } else {
1819                 if (curOpcode->opcode == D3DSIO_DCL) {
1820
1821                     DWORD usage = *pToken;
1822                     DWORD param = *(pToken + 1);
1823
1824                     parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1825                     vshader_program_dump_decl_usage(This, usage, param);
1826                     vshader_program_dump_vs_param(param, 0);
1827                     pToken += 2;
1828                     len += 2;
1829
1830                 } else 
1831                     if (curOpcode->opcode == D3DSIO_DEF) {
1832                         TRACE("def c%lu = ", *pToken & 0xFF);
1833                         ++pToken;
1834                         ++len;
1835                         TRACE("%f ,", *(float *)pToken);
1836                         ++pToken;
1837                         ++len;
1838                         TRACE("%f ,", *(float *)pToken);
1839                         ++pToken;
1840                         ++len;
1841                         TRACE("%f ,", *(float *)pToken);
1842                         ++pToken;
1843                         ++len;
1844                         TRACE("%f", *(float *)pToken);
1845                         ++pToken;
1846                         ++len;
1847                 } else {
1848                     TRACE("%s ", curOpcode->name);
1849                     if (curOpcode->num_params > 0) {
1850                         vshader_program_dump_vs_param(*pToken, 0);
1851                         ++pToken;
1852                         ++len;
1853                         for (i = 1; i < curOpcode->num_params; ++i) {
1854                             TRACE(", ");
1855                             vshader_program_dump_vs_param(*pToken, 1);
1856                             ++pToken;
1857                             ++len;
1858                         }
1859                     }
1860                 }
1861                 TRACE("\n");
1862             }
1863         }
1864         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1865     } else {
1866         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1867     }
1868
1869 /* Handy for debugging using numbered arrays instead of named arrays */
1870 #if 1
1871     /* TODO: using numbered arrays for software shaders makes things easier */
1872     This->declaredArrays = TRUE;
1873 #endif
1874
1875     /* named arrays and declared arrays are mutually exclusive */
1876     if (This->declaredArrays) 
1877         This->namedArrays = FALSE;
1878
1879     /* Generate HW shader in needed */
1880     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1881 #if 1
1882         IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
1883 #endif
1884     }
1885
1886     /* copy the function ... because it will certainly be released by application */
1887     if (NULL != pFunction) {
1888         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1889         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1890     } else {
1891         This->baseShader.function = NULL;
1892     }
1893     return WINED3D_OK;
1894 }
1895
1896 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1897 {
1898     /*** IUnknown methods ***/
1899     IWineD3DVertexShaderImpl_QueryInterface,
1900     IWineD3DVertexShaderImpl_AddRef,
1901     IWineD3DVertexShaderImpl_Release,
1902     /*** IWineD3DBase methods ***/
1903     IWineD3DVertexShaderImpl_GetParent,
1904     /*** IWineD3DBaseShader methods ***/
1905     IWineD3DVertexShaderImpl_SetFunction,
1906     /*** IWineD3DVertexShader methods ***/
1907     IWineD3DVertexShaderImpl_GetDevice,
1908     IWineD3DVertexShaderImpl_GetFunction
1909 };