crypt32: Fixed day/month mismatch in time encoding routines.
[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 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
366     FIXME(" : Stub\n");
367 }
368
369 void vshader_texkill(WINED3DSHADERVECTOR* d) {
370     FIXME(" : Stub\n");
371 }
372
373 void vshader_tex(WINED3DSHADERVECTOR* d) {
374     FIXME(" : Stub\n");
375 }
376 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
377     FIXME(" : Stub\n");
378 }
379
380 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
381     FIXME(" : Stub\n");
382 }
383
384 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
385     FIXME(" : Stub\n");
386 }
387
388 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
389     FIXME(" : Stub\n");
390 }
391
392 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393     FIXME(" : Stub\n");
394 }
395
396 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
397     FIXME(" : Stub\n");
398 }
399
400 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401     FIXME(" : Stub\n");
402 }
403
404 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405     FIXME(" : Stub\n");
406 }
407
408 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409     FIXME(" : Stub\n");
410 }
411
412 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
413     FIXME(" : Stub\n");
414 }
415
416 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
417     FIXME(" : Stub\n");
418 }
419
420 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421     FIXME(" : Stub\n");
422 }
423
424 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
425     FIXME(" : Stub\n");
426 }
427
428 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
429 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
430     FIXME(" : Stub\n");
431 }
432
433 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
434     FIXME(" : Stub\n");
435 }
436
437 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
438     FIXME(" : Stub\n");
439 }
440
441 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
442     FIXME(" : Stub\n");
443 }
444
445 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
446     FIXME(" : Stub\n");
447 }
448
449 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
450     FIXME(" : Stub\n");
451 }
452
453 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
454     FIXME(" : Stub\n");
455 }
456
457 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
458     FIXME(" : Stub\n");
459 }
460
461 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
462     FIXME(" : Stub\n");
463 }
464
465 void vshader_call(WINED3DSHADERVECTOR* d) {
466     FIXME(" : Stub\n");
467 }
468
469 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
470     FIXME(" : Stub\n");
471 }
472
473 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
474     FIXME(" : Stub\n");
475 }
476
477 void vshader_ret(WINED3DSHADERVECTOR* d) {
478     FIXME(" : Stub\n");
479 }
480
481 void vshader_endloop(WINED3DSHADERVECTOR* d) {
482     FIXME(" : Stub\n");
483 }
484
485 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486     FIXME(" : Stub\n");
487 }
488
489 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
490     FIXME(" : Stub\n");
491 }
492
493 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
494     FIXME(" : Stub\n");
495 }
496
497 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
498     FIXME(" : Stub\n");
499 }
500
501 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
502     FIXME(" : Stub\n");
503 }
504
505 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
506     FIXME(" : Stub\n");
507 }
508
509 void vshader_endrep(void) {
510     FIXME(" : Stub\n");
511 }
512
513 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514     FIXME(" : Stub\n");
515 }
516
517 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
518     FIXME(" : Stub\n");
519 }
520
521 void vshader_else(WINED3DSHADERVECTOR* d) {
522     FIXME(" : Stub\n");
523 }
524
525 void vshader_label(WINED3DSHADERVECTOR* d) {
526     FIXME(" : Stub\n");
527 }
528
529 void vshader_endif(WINED3DSHADERVECTOR* d) {
530     FIXME(" : Stub\n");
531 }
532
533 void vshader_break(WINED3DSHADERVECTOR* d) {
534     FIXME(" : Stub\n");
535 }
536
537 void vshader_breakc(WINED3DSHADERVECTOR* d) {
538     FIXME(" : Stub\n");
539 }
540
541 void vshader_mova(WINED3DSHADERVECTOR* d) {
542     FIXME(" : Stub\n");
543 }
544
545 void vshader_defb(WINED3DSHADERVECTOR* d) {
546     FIXME(" : Stub\n");
547 }
548
549 void vshader_defi(WINED3DSHADERVECTOR* d) {
550     FIXME(" : Stub\n");
551 }
552
553 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
554     FIXME(" : Stub\n");
555 }
556
557 void vshader_dsx(WINED3DSHADERVECTOR* d) {
558     FIXME(" : Stub\n");
559 }
560
561 void vshader_dsy(WINED3DSHADERVECTOR* d) {
562     FIXME(" : Stub\n");
563 }
564
565 void vshader_texldd(WINED3DSHADERVECTOR* d) {
566     FIXME(" : Stub\n");
567 }
568
569 void vshader_setp(WINED3DSHADERVECTOR* d) {
570     FIXME(" : Stub\n");
571 }
572
573 void vshader_texldl(WINED3DSHADERVECTOR* d) {
574     FIXME(" : Stub\n");
575 }
576
577 void vshader_breakp(WINED3DSHADERVECTOR* d) {
578     FIXME(" : Stub\n");
579 }
580
581
582 /**
583  * log, exp, frc, m*x* seems to be macros ins ... to see
584  */
585 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
586     {D3DSIO_NOP,  "nop", "NOP", 0, vshader_nop, 0, 0},
587     {D3DSIO_MOV,  "mov", "MOV", 2, vshader_mov, 0, 0},
588     {D3DSIO_ADD,  "add", "ADD", 3, vshader_add, 0, 0},
589     {D3DSIO_SUB,  "sub", "SUB", 3, vshader_sub, 0, 0},
590     {D3DSIO_MAD,  "mad", "MAD", 4, vshader_mad, 0, 0},
591     {D3DSIO_MUL,  "mul", "MUL", 3, vshader_mul, 0, 0},
592     {D3DSIO_RCP,  "rcp", "RCP",  2, vshader_rcp, 0, 0},
593     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, vshader_rsq, 0, 0},
594     {D3DSIO_DP3,  "dp3",  "DP3", 3, vshader_dp3, 0, 0},
595     {D3DSIO_DP4,  "dp4",  "DP4", 3, vshader_dp4, 0, 0},
596     {D3DSIO_MIN,  "min",  "MIN", 3, vshader_min, 0, 0},
597     {D3DSIO_MAX,  "max",  "MAX", 3, vshader_max, 0, 0},
598     {D3DSIO_SLT,  "slt",  "SLT", 3, vshader_slt, 0, 0},
599     {D3DSIO_SGE,  "sge",  "SGE", 3, vshader_sge, 0, 0},
600     {D3DSIO_ABS,  "abs",  "ABS", 2, vshader_abs, 0, 0},
601     {D3DSIO_EXP,  "exp",  "EX2", 2, vshader_exp, 0, 0},
602     {D3DSIO_LOG,  "log",  "LG2", 2, vshader_log, 0, 0},
603     {D3DSIO_LIT,  "lit",  "LIT", 2, vshader_lit, 0, 0},
604     {D3DSIO_DST,  "dst",  "DST", 3, vshader_dst, 0, 0},
605     {D3DSIO_LRP,  "lrp",  "LRP", 4, vshader_lrp, 0, 0},
606     {D3DSIO_FRC,  "frc",  "FRC", 2, vshader_frc, 0, 0},
607     {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
608     {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
609     {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
610     {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
611     {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
612     /** FIXME: use direct access so add the others opcodes as stubs */
613     /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
614         They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
615     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, vshader_call,    0, 0},
616     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, vshader_callnz,  0, 0},
617     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, vshader_loop,    0, 0},
618     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, vshader_ret,     0, 0},
619     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, vshader_endloop, 0, 0},
620     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, vshader_label,   0, 0},
621     /* DCL is a specil operation */
622     {D3DSIO_DCL,      "dcl",      NULL,   1, vshader_dcl,     0, 0},
623     {D3DSIO_POW,      "pow",      "POW",  3, vshader_pow,     0, 0},
624     {D3DSIO_CRS,      "crs",      "XPS",  3, vshader_crs,     0, 0},
625     /* TODO: sng can possibly be performed as
626         RCP tmp, vec
627         MUL out, tmp, vec*/
628     {D3DSIO_SGN,      "sng",      NULL,   2, vshader_sng,     0, 0},
629     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
630         DP3 tmp , vec, vec;
631         RSQ tmp, tmp.x;
632         MUL vec.xyz, vec, tmp;
633     but I think this is better because it accounts for w properly.
634         DP3 tmp , vec, vec;
635         RSQ tmp, tmp.x;
636         MUL vec, vec, tmp;
637     
638     */
639     {D3DSIO_NRM,      "nrm",      NULL,   2, vshader_nrm,     0, 0},
640     {D3DSIO_SINCOS,   "sincos",   NULL,   2, vshader_sincos,  0, 0},
641     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   2, vshader_rep,     0, 0},
642     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, vshader_endrep,  0, 0},
643     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   2, vshader_if,      0, 0},
644     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, vshader_ifc,     0, 0},
645     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   2, vshader_else,    0, 0},
646     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   2, vshader_endif,   0, 0},
647     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   2, vshader_break,   0, 0},
648     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, vshader_breakc,  0, 0},
649     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, vshader_mova,    0, 0},
650     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, vshader_defb,    0, 0},
651     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, vshader_defi,    0, 0},
652
653     {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL,   1, vshader_texcoord,    D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
654     {D3DSIO_TEXCOORD, "texcrd",   GLNAME_REQUIRE_GLSL,   2, vshader_texcoord,    D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
655     {D3DSIO_TEXKILL,  "texkill",  GLNAME_REQUIRE_GLSL,   1, vshader_texkill,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
656     {D3DSIO_TEX,      "tex",      GLNAME_REQUIRE_GLSL,   1, vshader_tex,         D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
657     {D3DSIO_TEX,      "texld",    GLNAME_REQUIRE_GLSL,   2, vshader_texld,       D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
658     {D3DSIO_TEXBEM,   "texbem",   GLNAME_REQUIRE_GLSL,   2, vshader_texbem,      D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
659     {D3DSIO_TEXBEML,  "texbeml",  GLNAME_REQUIRE_GLSL,   2, vshader_texbeml,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
660     {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL,   2, vshader_texreg2ar,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
661     {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL,   2, vshader_texreg2gb,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
662     {D3DSIO_TEXM3x2PAD,   "texm3x2pad",   GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2pad,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
663     {D3DSIO_TEXM3x2TEX,   "texm3x2tex",   GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2tex,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
664     {D3DSIO_TEXM3x3DIFF,  "texm3x3diff",  GLNAME_REQUIRE_GLSL,   2, vshader_texm3x3diff,  D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
665     {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  GLNAME_REQUIRE_GLSL,   3, vshader_texm3x3spec,  D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666     {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe",  GLNAME_REQUIRE_GLSL,   2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
667
668     {D3DSIO_EXPP,     "expp",     "EXP", 2, vshader_expp, 0, 0},
669     {D3DSIO_LOGP,     "logp",     "LOG", 2, vshader_logp, 0, 0},
670     {D3DSIO_CND,      "cnd",      GLNAME_REQUIRE_GLSL,   4, vshader_cnd,         D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
671     /* def is a special operation */
672     {D3DSIO_DEF,      "def",      NULL,   5, vshader_def,         D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
673     {D3DSIO_TEXREG2RGB,   "texreg2rgb",   GLNAME_REQUIRE_GLSL,   2, vshader_texreg2rgb,  D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674     {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL,   2, vshader_texdp3tex,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
675     {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL,   2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
676     {D3DSIO_TEXDP3,       "texdp3", GLNAME_REQUIRE_GLSL,  2, vshader_texdp3,     D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
677     {D3DSIO_TEXM3x3,      "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3,    D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
678     {D3DSIO_TEXDEPTH,     "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth,   D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
679     {D3DSIO_CMP,      "cmp",      GLNAME_REQUIRE_GLSL,   4, vshader_cmp,     D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
680     {D3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL,   3, vshader_bem,     D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
681     /* TODO: dp2add can be made out of multiple instuctions */
682     {D3DSIO_DP2ADD,   "dp2add",   GLNAME_REQUIRE_GLSL,   2, vshader_dp2add,  0, 0},
683     {D3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL,   2, vshader_dsx,     0, 0},
684     {D3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL,   2, vshader_dsy,     0, 0},
685     {D3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL,   2, vshader_texldd,  0, 0},
686     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, vshader_setp,    0, 0},
687     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, vshader_texldl,  0, 0},
688     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   2, vshader_breakp,  0, 0},
689     {D3DSIO_PHASE,    "phase",    GLNAME_REQUIRE_GLSL,   0, vshader_nop,     0, 0},
690     {0,               NULL,       NULL,   0, NULL,            0, 0}
691 };
692
693
694 inline static const SHADER_OPCODE* vshader_program_get_opcode(IWineD3DVertexShaderImpl *This, const DWORD code) {
695     DWORD i = 0;
696     const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
697
698     /** TODO: use dichotomic search or hash table */
699     while (NULL != shader_ins[i].name) {
700         if ((code & D3DSI_OPCODE_MASK) == shader_ins[i].opcode) {
701             return &shader_ins[i];
702         }
703         ++i;
704     }
705     FIXME("Unsupported opcode %lx\n",code);
706     return NULL;
707 }
708
709 inline static void vshader_program_dump_param(const DWORD param, int input) {
710   static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
711   static const char swizzle_reg_chars[] = "xyzw";
712
713   DWORD reg = param & 0x00001FFF;
714   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
715
716   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
717
718   switch (regtype) {
719   case D3DSPR_TEMP:
720     TRACE("R[%lu]", reg);
721     break;
722   case D3DSPR_INPUT:
723     TRACE("v%lu", reg);
724     break;
725   case D3DSPR_CONST:
726     TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
727     break;
728   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
729     TRACE("a[%lu]", reg);
730     break;
731   case D3DSPR_RASTOUT:
732     TRACE("%s", rastout_reg_names[reg]);
733     break;
734   case D3DSPR_ATTROUT:
735     TRACE("oD[%lu]", reg);
736     break;
737   case D3DSPR_TEXCRDOUT:
738     TRACE("oT[%lu]", reg);
739     break;
740   default:
741     FIXME("Unknown %lu %u reg %lu\n",regtype,  D3DSPR_ATTROUT, reg);
742     break;
743   }
744
745   if (!input) {
746     /** operand output */
747     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
748       if (param & D3DSP_WRITEMASK_0) TRACE(".x");
749       if (param & D3DSP_WRITEMASK_1) TRACE(".y");
750       if (param & D3DSP_WRITEMASK_2) TRACE(".z");
751       if (param & D3DSP_WRITEMASK_3) TRACE(".w");
752     }
753   } else {
754     /** operand input */
755     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
756     DWORD swizzle_x = swizzle & 0x03;
757     DWORD swizzle_y = (swizzle >> 2) & 0x03;
758     DWORD swizzle_z = (swizzle >> 4) & 0x03;
759     DWORD swizzle_w = (swizzle >> 6) & 0x03;
760     /**
761      * swizzle bits fields:
762      *  WWZZYYXX
763      */
764     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
765       if (swizzle_x == swizzle_y &&
766             swizzle_x == swizzle_z &&
767             swizzle_x == swizzle_w) {
768                 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
769             } else {
770                 TRACE(".%c%c%c%c",
771                     swizzle_reg_chars[swizzle_x],
772                     swizzle_reg_chars[swizzle_y],
773                     swizzle_reg_chars[swizzle_z],
774                     swizzle_reg_chars[swizzle_w]);
775       }
776     }
777   }
778 }
779
780 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
781   static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
782   static const char swizzle_reg_chars[] = "xyzw";
783    /* the unknown mask is for bits not yet accounted for by any other mask... */
784 #define UNKNOWN_MASK 0xC000
785
786    /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
787 #define EXTENDED_REG 0x1800
788
789   DWORD reg = param & D3DSP_REGNUM_MASK; /* 0x00001FFF;  isn't this D3DSP_REGNUM_MASK? */
790   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
791
792   if(param & UNKNOWN_MASK) { /* if this register has any of the unknown bits set then report them*/
793       FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype, (param & EXTENDED_REG), param & UNKNOWN_MASK);
794   }
795
796   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
797
798   switch (regtype /*<< D3DSP_REGTYPE_SHIFT*/) {
799   case D3DSPR_TEMP:
800     TRACE("r%lu", reg);
801     break;
802   case D3DSPR_INPUT:
803     TRACE("v%lu", reg);
804     break;
805   case D3DSPR_CONST:
806     TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
807     break;
808   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
809     TRACE("a%lu", reg);
810     break;
811   case D3DSPR_RASTOUT:
812     TRACE("%s", rastout_reg_names[reg]);
813     break;
814   case D3DSPR_ATTROUT:
815     TRACE("oD%lu", reg);
816     break;
817   case D3DSPR_TEXCRDOUT:
818     TRACE("oT%lu", reg);
819     break;
820   case D3DSPR_CONSTINT:
821     TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
822     break;
823   case D3DSPR_CONSTBOOL:
824     TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
825     break;
826   case D3DSPR_LABEL:
827     TRACE("l%lu", reg);
828     break;
829   case D3DSPR_LOOP:
830     TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
831     break;
832   default:
833     FIXME("Unknown %lu reg %lu\n",regtype, reg);
834     break;
835   }
836
837   if (!input) {
838     /** operand output */
839     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
840       if (param & D3DSP_WRITEMASK_0) TRACE(".x");
841       if (param & D3DSP_WRITEMASK_1) TRACE(".y");
842       if (param & D3DSP_WRITEMASK_2) TRACE(".z");
843       if (param & D3DSP_WRITEMASK_3) TRACE(".w");
844     }
845   } else {
846     /** operand input */
847     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
848     DWORD swizzle_x = swizzle & 0x03;
849     DWORD swizzle_y = (swizzle >> 2) & 0x03;
850     DWORD swizzle_z = (swizzle >> 4) & 0x03;
851     DWORD swizzle_w = (swizzle >> 6) & 0x03;
852     /**
853      * swizzle bits fields:
854      *  WWZZYYXX
855      */
856     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
857       if (swizzle_x == swizzle_y &&
858         swizzle_x == swizzle_z &&
859         swizzle_x == swizzle_w) {
860             TRACE(".%c", swizzle_reg_chars[swizzle_x]);
861       } else {
862         TRACE(".%c%c%c%c",
863         swizzle_reg_chars[swizzle_x],
864         swizzle_reg_chars[swizzle_y],
865         swizzle_reg_chars[swizzle_z],
866         swizzle_reg_chars[swizzle_w]);
867       }
868     }
869   }
870 }
871
872 inline static void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl *This, DWORD token) {
873     TRACE("dcl_");
874     switch(token & 0xFFFF) {
875         case D3DDECLUSAGE_POSITION:
876             TRACE("%s%ld ", "position",(token & 0xF0000) >> 16);
877             break;
878         case D3DDECLUSAGE_BLENDINDICES:
879             TRACE("%s ", "blend");
880             break;
881         case D3DDECLUSAGE_BLENDWEIGHT:
882             TRACE("%s ", "weight");
883             break;
884         case D3DDECLUSAGE_NORMAL:
885             TRACE("%s%ld ", "normal",(token & 0xF0000) >> 16);
886             break;
887         case D3DDECLUSAGE_PSIZE:
888             TRACE("%s ", "psize");
889             break;
890         case D3DDECLUSAGE_COLOR:
891             if((token & 0xF0000) >> 16 == 0)  {
892                 TRACE("%s ", "color");
893             } else {
894                 TRACE("%s ", "specular");
895             }
896             break;
897         case D3DDECLUSAGE_TEXCOORD:
898             TRACE("%s%ld ", "texture", (token & 0xF0000) >> 16);
899             break;
900         case D3DDECLUSAGE_TANGENT:
901             TRACE("%s ", "tangent");
902             break;
903         case D3DDECLUSAGE_BINORMAL:
904             TRACE("%s ", "binormal");
905             break;
906         case D3DDECLUSAGE_TESSFACTOR:
907             TRACE("%s ", "tessfactor");
908             break;
909         case D3DDECLUSAGE_POSITIONT:
910             TRACE("%s%ld ", "positionT",(token & 0xF0000) >> 16);
911             break;
912         case D3DDECLUSAGE_FOG:
913             TRACE("%s ", "fog");
914             break;
915         case D3DDECLUSAGE_DEPTH:
916             TRACE("%s ", "depth");
917             break;
918         case D3DDECLUSAGE_SAMPLE:
919             TRACE("%s ", "sample");
920             break;
921         default:
922             FIXME("Unrecognised dcl %08lx", token & 0xFFFF);
923     }
924 }
925
926 inline static BOOL vshader_is_version_token(DWORD token) {
927   return 0xFFFE0000 == (token & 0xFFFE0000);
928 }
929
930 inline static BOOL vshader_is_comment_token(DWORD token) {
931   return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
932 }
933
934 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
935     /** operand output */
936     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
937       strcat(hwLine, ".");
938       if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
939       if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
940       if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
941       if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
942     }  
943 }
944
945 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
946     static const char swizzle_reg_chars_color_fix[] = "zyxw";
947     static const char swizzle_reg_chars[] = "xyzw";
948     const char* swizzle_regs = NULL;
949     char  tmpReg[255];
950
951     /** operand input */
952     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
953     DWORD swizzle_x = swizzle & 0x03;
954     DWORD swizzle_y = (swizzle >> 2) & 0x03;
955     DWORD swizzle_z = (swizzle >> 4) & 0x03;
956     DWORD swizzle_w = (swizzle >> 6) & 0x03;
957
958     if (is_color) {
959       swizzle_regs = swizzle_reg_chars_color_fix;
960     } else {
961       swizzle_regs = swizzle_reg_chars;
962     }
963
964     /**
965      * swizzle bits fields:
966      *  WWZZYYXX
967      */
968     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
969       if (is_color) {
970         sprintf(tmpReg, ".%c%c%c%c",
971                 swizzle_regs[swizzle_x],
972                 swizzle_regs[swizzle_y],
973                 swizzle_regs[swizzle_z],
974                 swizzle_regs[swizzle_w]);
975         strcat(hwLine, tmpReg);
976       }
977       return ;
978     }
979     if (swizzle_x == swizzle_y &&
980         swizzle_x == swizzle_z &&
981         swizzle_x == swizzle_w)
982     {
983       sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
984       strcat(hwLine, tmpReg);
985     } else {
986       sprintf(tmpReg, ".%c%c%c%c",
987               swizzle_regs[swizzle_x],
988               swizzle_regs[swizzle_y],
989               swizzle_regs[swizzle_z],
990               swizzle_regs[swizzle_w]);
991       strcat(hwLine, tmpReg);
992     }
993 }
994
995 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
996   /* oPos, oFog and oPts in D3D */
997   static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
998
999   DWORD reg = param & 0x00001FFF;
1000   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1001   char  tmpReg[255];
1002   BOOL is_color = FALSE;
1003
1004   if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
1005       strcat(hwLine, " -");
1006   } else {
1007       strcat(hwLine, " ");
1008   }
1009
1010   switch (regtype) {
1011   case D3DSPR_TEMP:
1012     sprintf(tmpReg, "T%lu", reg);
1013     strcat(hwLine, tmpReg);
1014     break;
1015   case D3DSPR_INPUT:
1016     if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
1017         || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
1018         is_color = TRUE;
1019     }
1020     /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1021     if (This->namedArrays) {
1022         sprintf(tmpReg, "namedVertex%lu", reg);
1023     } else {
1024     /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1025         sprintf(tmpReg, "vertex.attrib[%lu]", reg);
1026     }
1027     strcat(hwLine, tmpReg);
1028     break;
1029   case D3DSPR_CONST:
1030     /* FIXME: some constants are named so we need a constants map*/
1031     if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
1032         if (param & D3DVS_ADDRMODE_RELATIVE) {
1033             FIXME("Relative addressing not expected for a named constant %lu\n", reg);
1034         }
1035         sprintf(tmpReg, "const%lu", reg);
1036     } else {
1037         sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
1038     }
1039     strcat(hwLine, tmpReg);
1040     break;
1041   case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
1042     sprintf(tmpReg, "A%lu", reg);
1043     strcat(hwLine, tmpReg);
1044     break;
1045   case D3DSPR_RASTOUT:
1046     sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
1047     strcat(hwLine, tmpReg);
1048     break;
1049   case D3DSPR_ATTROUT:
1050     if (reg==0) {
1051        strcat(hwLine, "result.color.primary");
1052     } else {
1053        strcat(hwLine, "result.color.secondary");
1054     }
1055     break;
1056   case D3DSPR_TEXCRDOUT:
1057     sprintf(tmpReg, "result.texcoord[%lu]", reg);
1058     strcat(hwLine, tmpReg);
1059     break;
1060   default:
1061     FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1062     break;
1063   }
1064
1065   if (!is_input) {
1066     vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1067   } else {
1068     vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1069   }
1070 }
1071
1072 DWORD MacroExpansion[4*4];
1073
1074 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1075  
1076   int i;
1077   int nComponents = 0;
1078   DWORD opcode =0;
1079   switch(macro_opcode) {
1080     case D3DSIO_M4x4:
1081       nComponents = 4;
1082       opcode = D3DSIO_DP4;
1083       break;
1084     case D3DSIO_M4x3:
1085       nComponents = 3;
1086       opcode = D3DSIO_DP4;
1087       break;
1088     case D3DSIO_M3x4:
1089       nComponents = 4;
1090       opcode = D3DSIO_DP3;
1091       break;
1092     case D3DSIO_M3x3:
1093       nComponents = 3;
1094       opcode = D3DSIO_DP3;
1095       break;
1096     case D3DSIO_M3x2:
1097       nComponents = 2;
1098       opcode = D3DSIO_DP3;
1099       break;
1100     default:
1101       break;
1102   }
1103   for (i = 0; i < nComponents; i++) {
1104     MacroExpansion[i*4+0] = opcode;
1105     MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1106     MacroExpansion[i*4+2] = *(args+1);
1107     MacroExpansion[i*4+3] = (*(args+2))+i;
1108   }
1109   return nComponents;
1110 }
1111
1112 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
1113 {
1114     switch(usage & 0xFFFF) {
1115         case D3DDECLUSAGE_POSITION:
1116             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1117                 TRACE("Setting position to %d\n", arrayNo);
1118                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
1119                 This->namedArrays = TRUE;
1120             } else {
1121                 /* TODO: position indexes go from 0-8!!*/
1122                 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1123                 /* robots uses positions up to 8, the position arrays are just packed.*/
1124                 if ((usage & 0xF0000) >> 16 > 1) {
1125                     TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1126                 }
1127                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1128                 This->declaredArrays = TRUE;
1129             }
1130         break;
1131         case D3DDECLUSAGE_BLENDINDICES:
1132             /* not supported by openGL */
1133             TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1134             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1135             This->declaredArrays = TRUE;
1136             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1137         break;
1138         case D3DDECLUSAGE_BLENDWEIGHT:
1139             TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1140             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
1141             This->namedArrays = TRUE;
1142             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1143         break;
1144         case D3DDECLUSAGE_NORMAL:
1145             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1146                 TRACE("Setting normal to %d\n", arrayNo);
1147                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
1148                 This->namedArrays = TRUE;
1149             } else {
1150                 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1151                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
1152                 This->declaredArrays = TRUE;
1153             }
1154         break;
1155         case D3DDECLUSAGE_PSIZE:
1156             TRACE("Setting PSIZE to %d\n", arrayNo);
1157             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
1158             This->namedArrays = TRUE;
1159             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1160         break;
1161         case D3DDECLUSAGE_COLOR:
1162             if((usage & 0xF0000) >> 16 == 0)  {
1163                 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1164                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
1165                 This->namedArrays = TRUE;
1166             } else {
1167                 TRACE("Setting SPECULAR to %d\n", arrayNo);
1168                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1169                 This->namedArrays = TRUE;
1170             }
1171         break;
1172         case D3DDECLUSAGE_TEXCOORD:
1173             This->namedArrays = TRUE;
1174             /* only 7 texture coords have been designed for, so run a quick sanity check */
1175             if ((usage & 0xF0000) >> 16 > 7) {
1176                 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1177             } else {
1178                 TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1179                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1180             }
1181         break;
1182         /* The following aren't supported by openGL,
1183             if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1184             this should be caught in the first pass */
1185         case D3DDECLUSAGE_TANGENT:
1186             TRACE("Setting TANGENT to %d\n", arrayNo);
1187             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
1188             This->declaredArrays = TRUE;
1189         break;
1190         case D3DDECLUSAGE_BINORMAL:
1191             TRACE("Setting BINORMAL to %d\n", arrayNo);
1192             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
1193             This->declaredArrays = TRUE;
1194         break;
1195         case D3DDECLUSAGE_TESSFACTOR:
1196             TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1197             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
1198             This->declaredArrays = TRUE;
1199         break;
1200         case D3DDECLUSAGE_POSITIONT:
1201             if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1202                 FIXME("Setting positiont to %d\n", arrayNo);
1203                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1204                 This->namedArrays = TRUE;
1205             } else {
1206                 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1207                 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1208                 This->declaredArrays = TRUE;
1209             if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1210             }
1211         break;
1212         case D3DDECLUSAGE_FOG:
1213             /* supported by OpenGL */
1214             TRACE("Setting FOG to %d\n", arrayNo);
1215             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
1216             This->namedArrays = TRUE;
1217         break;
1218         case D3DDECLUSAGE_DEPTH:
1219             TRACE("Setting DEPTH to %d\n", arrayNo);
1220             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
1221             This->declaredArrays = TRUE;
1222         break;
1223         case D3DDECLUSAGE_SAMPLE:
1224             TRACE("Setting SAMPLE to %d\n", arrayNo);
1225             This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
1226             This->declaredArrays = TRUE;
1227         break;
1228         default:
1229         FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1230     }
1231 }
1232
1233 /**
1234  * Function parser ...
1235  */
1236
1237 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1238     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1239     const DWORD* pToken = pFunction;
1240     const DWORD* pSavedToken = NULL;
1241     const SHADER_OPCODE* curOpcode = NULL;
1242     int nRemInstr = -1;
1243     DWORD i;
1244     unsigned lineNum = 0;
1245     char *pgmStr = NULL;
1246     char  tmpLine[255];
1247     DWORD nUseAddressRegister = 0;
1248     DWORD nUseTempRegister = 0;
1249     DWORD regtype;
1250     DWORD reg;
1251     BOOL tmpsUsed[32];
1252 #if 0 /* TODO: loope register (just another address register ) */
1253     BOOL hasLoops = FALSE;
1254 #endif
1255
1256 #define PGMSIZE 65535
1257 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1258     int pgmLength = 0;
1259
1260 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1261         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1262     if (This->device->fixupVertexBufferSize < PGMSIZE) {
1263         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1264         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1265         This->fixupVertexBufferSize = PGMSIZE;
1266         This->fixupVertexBuffer[0] = 0;
1267     }
1268     pgmStr = This->device->fixupVertexBuffer;
1269 #endif
1270 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1271         int _tmpLineLen = strlen(_tmpLine); \
1272         if(_tmpLineLen + pgmLength > PGMSIZE) { \
1273             ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1274         } else { \
1275            memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1276         } \
1277         pgmLength += _tmpLineLen; \
1278         }
1279
1280     pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1281     /* Initialise the shader */
1282     This->namedArrays = FALSE;
1283     This->declaredArrays = FALSE;
1284     for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1285         This->arrayUsageMap[i] = -1;
1286     }
1287     /* set all the tmpsUsed to not used */
1288     memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1289
1290     /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1291     This->highestConstant = -1;
1292
1293   /**
1294    * First pass to determine what we need to declare:
1295    *  - Temporary variables
1296    *  - Address variables
1297    */ 
1298     if (NULL != pToken) {
1299         while (D3DVS_END() != *pToken) {
1300             if (vshader_is_version_token(*pToken)) {
1301             /** skip version */
1302             ++pToken;
1303             continue;
1304             }
1305             if (vshader_is_comment_token(*pToken)) { /** comment */
1306                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1307                 ++pToken;
1308                 pToken += comment_len;
1309                 continue;
1310             }
1311             curOpcode = vshader_program_get_opcode(This, *pToken);
1312             ++pToken;
1313             /* TODO: dcl's */
1314             /* TODO: Consts */
1315
1316             if (NULL == curOpcode) {
1317                 while (*pToken & 0x80000000) {
1318                     FIXME("unrecognized opcode: %08lx\n", *pToken);
1319                     /* skip unrecognized opcode */
1320                     ++pToken;
1321                 }
1322             } else {
1323                 if (curOpcode->opcode == D3DSIO_DCL){
1324                     INT usage = *pToken++;
1325                     INT arrayNo = (*pToken++ & 0x00001FFF);
1326                     parse_decl_usage(This, usage, arrayNo);
1327                 } else if(curOpcode->opcode == D3DSIO_DEF) {
1328                             This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1329                             FIXME("Constant %ld\n", *pToken & 0xFF);
1330                             ++pToken;
1331                             ++pToken;
1332                             ++pToken;
1333                             ++pToken;
1334                             ++pToken;
1335
1336                 } else {
1337                     /* Check to see if and tmp or addressing redisters are used */
1338                     if (curOpcode->num_params > 0) {
1339                         regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1340                         reg = ((*pToken)  & 0x00001FFF);
1341                         if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1342                         if (D3DSPR_TEMP == regtype){
1343                             tmpsUsed[reg] = TRUE;
1344                             if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
1345                         }
1346                         ++pToken;
1347                         for (i = 1; i < curOpcode->num_params; ++i) {
1348                             regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1349                             reg = ((*pToken)  & 0x00001FFF);
1350                             if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1351                             if (D3DSPR_TEMP == regtype){
1352                                 tmpsUsed[reg] = TRUE;
1353                                 if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
1354                             }
1355                             ++pToken;
1356                         }
1357                     }
1358                 }
1359 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1360                 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1361                     FIXME("This shader requires gl shader language support\n");
1362 #if 0
1363                     This->shaderLanguage = GLSHADER_GLSL;
1364 #endif
1365                 }
1366 #endif
1367             }
1368         }
1369     }
1370 #if 1
1371 #define VSHADER_ALWAYS_NUMBERED
1372 #endif
1373
1374 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1375     /* TODO: using numbered arrays for software shaders makes things easier */
1376     This->declaredArrays = TRUE;
1377 #endif
1378
1379     /* named arrays and declared arrays are mutually exclusive */
1380     if (This->declaredArrays) {
1381         This->namedArrays = FALSE;
1382     }
1383     /* TODO: validate
1384         nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1385         nUseTempRegister    <=  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1386     */
1387
1388   /** second pass, now generate */
1389   pToken = pFunction;
1390
1391   if (NULL != pToken) {
1392     while (1) {
1393       tmpLine[0] = 0;
1394       if ((nRemInstr >= 0) && (--nRemInstr == -1))
1395             /* Macro is finished, continue normal path */ 
1396             pToken = pSavedToken;
1397       if (D3DVS_END() == *pToken)
1398             break;
1399
1400       if (vshader_is_version_token(*pToken)) { /** version */
1401         /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1402         int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1403         int numTemps;
1404         int numConstants;
1405
1406         TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1407
1408         /* Each release of vertex shaders has had different numbers of temp registers */
1409         switch (version) {
1410         case 10:
1411         case 11: numTemps=12;
1412                  numConstants=96;/* min(GL_LIMITS(constants),96) */
1413                  strcpy(tmpLine, "!!ARBvp1.0\n");
1414                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1415                  break;
1416         /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1417            TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1418             TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1419         case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1420                  numConstants=96; /* min(GL_LIMITS(constants),256) */
1421                  strcpy(tmpLine, "!!ARBvp1.0\n");
1422                  FIXME("No work done yet to support vs2.0 in hw\n");
1423                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1424                  break;
1425         case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1426                  numConstants=96; /* min(GL_LIMITS(constants),256) */
1427                  strcpy(tmpLine, "!!ARBvp1.0\n");
1428                  FIXME("No work done yet to support vs2.1 in hw\n");
1429                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1430                  break;
1431         case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1432                  numConstants=96;/* min(GL_LIMITS(constants),256) */
1433                  strcpy(tmpLine, "!!ARBvp3.0\n");
1434                  FIXME("No work done yet to support vs3.0 in hw\n");
1435                  TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1436                  break;
1437         default:
1438                  numTemps=12;/* min(GL_LIMITS(temps),12) */
1439                  numConstants=96;/* min(GL_LIMITS(constants),96) */
1440                  strcpy(tmpLine, "!!ARBvp1.0\n");
1441                  FIXME("Unrecognized vertex shader version %d!\n", version);
1442         }
1443         PNSTRCAT(pgmStr, tmpLine);
1444
1445         ++lineNum;
1446
1447         /* This should be a bitmap so that only temp registers that are used are declared. */
1448         for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1449             if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1450                 sprintf(tmpLine, "TEMP T%ld;\n", i);
1451                 ++lineNum;
1452                 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1453                 PNSTRCAT(pgmStr, tmpLine);
1454
1455             }
1456         }
1457         /* TODO: loop register counts as an address register */
1458         for (i = 0; i < nUseAddressRegister; i++) {
1459             sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1460             ++lineNum;
1461             TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1462                 PNSTRCAT(pgmStr, tmpLine);
1463
1464         }
1465         /* Due to the dynamic constants binding mechanism, we need to declare
1466         * all the constants for relative addressing. */
1467         /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1468         if (GL_VEND(MESA) || GL_VEND(WINE)) {
1469             numConstants = 95;
1470         }
1471         /* FIXME: We should  be counting the number of constants in the first pass and then validating that many are supported
1472                 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1473         */
1474         sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1475         TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1476         PNSTRCAT(pgmStr, tmpLine);
1477
1478         ++lineNum;
1479
1480         ++pToken;
1481         continue;
1482         }
1483         if (vshader_is_comment_token(*pToken)) { /** comment */
1484             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1485             ++pToken;
1486             TRACE("#%s\n", (char*)pToken);
1487             pToken += comment_len;
1488             continue;
1489       }
1490
1491       curOpcode = vshader_program_get_opcode(This, *pToken);
1492       ++pToken;
1493       if (NULL == curOpcode) {
1494         /* unknown current opcode ... (shouldn't be any!) */
1495         while (*pToken & 0x80000000) {
1496             FIXME("unrecognized opcode: %08lx\n", *pToken);
1497             ++pToken;
1498         }
1499       } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1500             /* if the token isn't supported by this cross compiler then skip it and its parameters */
1501           
1502             FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1503             pToken += curOpcode->num_params;
1504
1505       } else if (D3DSIO_DEF == curOpcode->opcode) {
1506
1507             /* Handle definitions here, they don't fit well with the
1508              * other instructions below [for now ] */
1509
1510             char tmpChar[80];
1511             sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1512             sprintf(tmpChar,"%f ,", *(float *) (pToken + 1));
1513             strcat(tmpLine, tmpChar);
1514             sprintf(tmpChar,"%f ,", *(float *) (pToken + 2));
1515             strcat(tmpLine, tmpChar);
1516             sprintf(tmpChar,"%f ,", *(float *) (pToken + 3));
1517             strcat(tmpLine, tmpChar);
1518             sprintf(tmpChar,"%f}", *(float *) (pToken + 4));
1519             strcat(tmpLine, tmpChar);
1520
1521             strcat(tmpLine,";\n");
1522             ++lineNum;
1523             TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1524             PNSTRCAT(pgmStr, tmpLine);
1525
1526             pToken += 5;
1527             continue;
1528
1529       } else if (D3DSIO_DCL == curOpcode->opcode) {
1530
1531             /* Handle declarations here, they don't fit well with the
1532              * other instructions below [for now ] */
1533
1534             if (This->namedArrays) {
1535                 const char* attribName = "undefined";
1536                 switch(*pToken & 0xFFFF) {
1537                     case D3DDECLUSAGE_POSITION:
1538                     attribName = "vertex.position";
1539                     break;
1540                     case D3DDECLUSAGE_BLENDINDICES:
1541                     /* not supported by openGL */
1542                     attribName = "vertex.blend";
1543                     break;
1544                     case D3DDECLUSAGE_BLENDWEIGHT:
1545                     attribName = "vertex.weight";
1546                     break;
1547                     case D3DDECLUSAGE_NORMAL:
1548                     attribName = "vertex.normal";
1549                     break;
1550                     case D3DDECLUSAGE_PSIZE:
1551                     attribName = "vertex.psize";
1552                     break;
1553                     case D3DDECLUSAGE_COLOR:
1554                     if((*pToken & 0xF0000) >> 16 == 0)  {
1555                         attribName = "vertex.color";
1556                     } else {
1557                         attribName = "vertex.color.secondary";
1558                     }
1559                     break;
1560                     case D3DDECLUSAGE_TEXCOORD:
1561                     {
1562                         char tmpChar[100];
1563                         tmpChar[0] = 0;
1564                         sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1565                         attribName = tmpChar;
1566                         break;
1567                     }
1568                     /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1569                     case D3DDECLUSAGE_TANGENT:
1570                     attribName = "vertex.tangent";
1571                     break;
1572                     case D3DDECLUSAGE_BINORMAL:
1573                     attribName = "vertex.binormal";
1574                     break;
1575                     case D3DDECLUSAGE_TESSFACTOR:
1576                     attribName = "vertex.tessfactor";
1577                     break;
1578                     case D3DDECLUSAGE_POSITIONT:
1579                     attribName = "vertex.possitionT";
1580                     break;
1581                     case D3DDECLUSAGE_FOG:
1582                     attribName = "vertex.fogcoord";
1583                     break;
1584                     case D3DDECLUSAGE_DEPTH:
1585                     attribName = "vertex.depth";
1586                     break;
1587                     case D3DDECLUSAGE_SAMPLE:
1588                     attribName = "vertex.sample";
1589                     break;
1590                     default:
1591                     FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1592                 }
1593                 {
1594                     char tmpChar[80];
1595                     ++pToken;
1596                     sprintf(tmpLine, "ATTRIB ");
1597                     vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1598
1599                     sprintf(tmpChar," = %s", attribName);
1600                     strcat(tmpLine, tmpChar);
1601                     strcat(tmpLine,";\n");
1602                     ++lineNum;
1603                     if (This->namedArrays) {
1604                         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1605                         PNSTRCAT(pgmStr, tmpLine);
1606
1607                     } else {
1608                         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1609                     }
1610                 }
1611             } else {
1612                 /* eat the token so it doesn't generate a warning */
1613                 ++pToken;
1614             }
1615             ++pToken;
1616             continue;
1617
1618       } else {
1619
1620         /* Common Processing: ([instr] [dst] [src]*) */
1621
1622         switch (curOpcode->opcode) {
1623         case D3DSIO_NOP:
1624             continue;
1625         case D3DSIO_MOV:
1626             /* Address registers must be loaded with the ARL instruction */
1627             if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1628                 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1629                     strcpy(tmpLine, "ARL");
1630                     break;
1631                 } else
1632                 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1633             }
1634             /* fall through */
1635         case D3DSIO_ADD:
1636         case D3DSIO_SUB:
1637         case D3DSIO_MAD:
1638         case D3DSIO_MUL:
1639         case D3DSIO_RCP:
1640         case D3DSIO_RSQ:
1641         case D3DSIO_DP3:
1642         case D3DSIO_DP4:
1643         case D3DSIO_MIN:
1644         case D3DSIO_MAX:
1645         case D3DSIO_SLT:
1646         case D3DSIO_SGE:
1647         case D3DSIO_LIT:
1648         case D3DSIO_DST:
1649         case D3DSIO_FRC:
1650         case D3DSIO_EXPP:
1651         case D3DSIO_LOGP:
1652         case D3DSIO_EXP:
1653         case D3DSIO_LOG:
1654             strcpy(tmpLine, curOpcode->glname);
1655             break;
1656         case D3DSIO_M4x4:
1657         case D3DSIO_M4x3:
1658         case D3DSIO_M3x4:
1659         case D3DSIO_M3x3:
1660         case D3DSIO_M3x2:
1661             /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1662             nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1663             /* Save point to next instruction */
1664             pSavedToken = pToken + 3;
1665             /* Execute expanded macro */
1666             pToken = MacroExpansion;
1667             continue;
1668
1669         default:
1670             if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1671                 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1672             } else {
1673                 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1674             }
1675         }
1676         if (curOpcode->num_params > 0) {
1677             vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1678
1679             ++pToken;
1680             for (i = 1; i < curOpcode->num_params; ++i) {
1681                 strcat(tmpLine, ",");
1682                 vshader_program_add_param(This, *pToken, TRUE, tmpLine);
1683                 ++pToken;
1684             }
1685         }
1686         strcat(tmpLine,";\n");
1687         ++lineNum;
1688         TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1689         PNSTRCAT(pgmStr, tmpLine);
1690
1691       }
1692     }
1693     strcpy(tmpLine, "END\n"); 
1694     ++lineNum;
1695     TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1696     PNSTRCAT(pgmStr, tmpLine);
1697
1698   }
1699   /* finally null terminate the pgmStr*/
1700   pgmStr[pgmLength] = 0;
1701
1702   /* Check that Vertex Shaders are supported */
1703   if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1704       /*  Create the hw shader */
1705       /* TODO: change to resource.glObjectHandel or something like that */
1706       GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1707       TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1708       GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1709
1710       /* Create the program and check for errors */
1711       GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1712       if (glGetError() == GL_INVALID_OPERATION) {
1713           GLint errPos;
1714           glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1715           FIXME("HW VertexShader Error at position %d: %s\n",
1716                 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1717           This->baseShader.prgId = -1;
1718       }
1719   }
1720 #if 1 /* if were using the data buffer of device then we don't need to free it */
1721   HeapFree(GetProcessHeap(), 0, pgmStr);
1722 #endif
1723 #undef PNSTRCAT
1724 }
1725
1726 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1727   /**
1728    * TODO: use the NV_vertex_program (or 1_1) extension
1729    *  and specifics vendors (ARB_vertex_program??) variants for it
1730    */
1731   return TRUE;
1732 }
1733
1734 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1735     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1736         
1737     /** Vertex Shader Temporary Registers */
1738     WINED3DSHADERVECTOR R[12];
1739       /*D3DSHADERSCALAR A0;*/
1740     WINED3DSHADERVECTOR A[1];
1741     /** temporary Vector for modifier management */
1742     WINED3DSHADERVECTOR d;
1743     WINED3DSHADERVECTOR s[3];
1744     /** parser datas */
1745     const DWORD* pToken = This->baseShader.function;
1746     const SHADER_OPCODE* curOpcode = NULL;
1747     /** functions parameters */
1748     WINED3DSHADERVECTOR* p[4];
1749     WINED3DSHADERVECTOR* p_send[4];
1750     DWORD i;
1751
1752     /** init temporary register */
1753     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1754
1755     /* vshader_program_parse(vshader); */
1756 #if 0 /* Must not be 1 in cvs */
1757     TRACE("Input:\n");
1758     TRACE_VSVECTOR(This->data->C[0]);
1759     TRACE_VSVECTOR(This->data->C[1]);
1760     TRACE_VSVECTOR(This->data->C[2]);
1761     TRACE_VSVECTOR(This->data->C[3]);
1762     TRACE_VSVECTOR(This->data->C[4]);
1763     TRACE_VSVECTOR(This->data->C[5]);
1764     TRACE_VSVECTOR(This->data->C[6]);
1765     TRACE_VSVECTOR(This->data->C[7]);
1766     TRACE_VSVECTOR(This->data->C[8]);
1767     TRACE_VSVECTOR(This->data->C[64]);
1768     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1769     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1770     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1771     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1772     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1773     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1774     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1775     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1776     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1777 #endif
1778
1779     TRACE_VSVECTOR(vshader->data->C[64]);
1780     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1781
1782     /* the first dword is the version tag */
1783     /* TODO: parse it */
1784
1785     if (vshader_is_version_token(*pToken)) { /** version */
1786         ++pToken;
1787     }
1788     while (D3DVS_END() != *pToken) {
1789         if (vshader_is_comment_token(*pToken)) { /** comment */
1790             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1791             ++pToken;
1792             pToken += comment_len;
1793             continue ;
1794         }
1795         curOpcode = vshader_program_get_opcode(This, *pToken);
1796         ++pToken;
1797         if (NULL == curOpcode) {
1798             i = 0;
1799             /* unknown current opcode ... */
1800             /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1801             while (*pToken & 0x80000000) {
1802                 if (i == 0) {
1803                     FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1804                 }
1805                 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1806                 vshader_program_dump_param(*pToken, i);
1807                 TRACE("\n");
1808                 ++i;
1809                 ++pToken;
1810             }
1811             /* return FALSE; */
1812         } else {
1813             if (curOpcode->num_params > 0) {
1814                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1815                 for (i = 0; i < curOpcode->num_params; ++i) {
1816                     DWORD reg = pToken[i] & 0x00001FFF;
1817                     DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1818     
1819                     switch (regtype << D3DSP_REGTYPE_SHIFT) {
1820                     case D3DSPR_TEMP:
1821                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
1822                         p[i] = &R[reg];
1823                         break;
1824                     case D3DSPR_INPUT:
1825                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1826                         p[i] = &input->V[reg];
1827                         break;
1828                     case D3DSPR_CONST:
1829                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1830                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
1831                         } else {
1832                             p[i] = &This->data->C[reg];
1833                         }
1834                         break;
1835                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1836                         if (0 != reg) {
1837                             ERR("cannot handle address registers != a0, forcing use of a0\n");
1838                             reg = 0;
1839                         }
1840                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
1841                         p[i] = &A[reg];
1842                         break;
1843                     case D3DSPR_RASTOUT:
1844                         switch (reg) {
1845                         case D3DSRO_POSITION:
1846                             p[i] = &output->oPos;
1847                             break;
1848                         case D3DSRO_FOG:
1849                             p[i] = &output->oFog;
1850                             break;
1851                         case D3DSRO_POINT_SIZE:
1852                             p[i] = &output->oPts;
1853                             break;
1854                         }
1855                         break;
1856                     case D3DSPR_ATTROUT:
1857                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1858                         p[i] = &output->oD[reg];
1859                         break;
1860                     case D3DSPR_TEXCRDOUT:
1861                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1862                         p[i] = &output->oT[reg];
1863                         break;
1864                     /* TODO Decls and defs */
1865 #if 0
1866                     case D3DSPR_DCL:
1867                     case D3DSPR_DEF:
1868 #endif
1869                     default:
1870                         break;
1871                     }
1872
1873                     if (i > 0) { /* input reg */
1874                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1875                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1876
1877                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1878                             /* TRACE("p[%d] not swizzled\n", i); */
1879                             p_send[i] = p[i];
1880                         } else {
1881                             DWORD swizzle_x = swizzle & 0x03;
1882                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
1883                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
1884                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
1885                             /* TRACE("p[%d] swizzled\n", i); */
1886                             float* tt = (float*) p[i];
1887                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1888                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1889                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1890                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1891                             p_send[i] = &s[i];
1892                         }
1893                     } else { /* output reg */
1894                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1895                             p_send[i] = p[i];
1896                         } else {
1897                             p_send[i] = &d; /* to be post-processed for modifiers management */
1898                         }
1899                     }
1900                 }
1901             }
1902
1903             switch (curOpcode->num_params) {
1904             case 0:
1905                 curOpcode->soft_fct();
1906                 break;
1907             case 1:
1908                 curOpcode->soft_fct(p_send[0]);
1909             break;
1910             case 2:
1911                 curOpcode->soft_fct(p_send[0], p_send[1]);
1912                 break;
1913             case 3:
1914                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1915                 break;
1916             case 4:
1917                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1918                 break;
1919             case 5:
1920                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1921                 break;
1922             case 6:
1923                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1924                 break;
1925             default:
1926                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1927             }
1928
1929             /* check if output reg modifier post-process */
1930             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1931                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
1932                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
1933                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
1934                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
1935             }
1936 #if 0
1937             TRACE_VSVECTOR(output->oPos);
1938             TRACE_VSVECTOR(output->oD[0]);
1939             TRACE_VSVECTOR(output->oD[1]);
1940             TRACE_VSVECTOR(output->oT[0]);
1941             TRACE_VSVECTOR(output->oT[1]);
1942             TRACE_VSVECTOR(R[0]);
1943             TRACE_VSVECTOR(R[1]);
1944             TRACE_VSVECTOR(R[2]);
1945             TRACE_VSVECTOR(R[3]);
1946             TRACE_VSVECTOR(R[4]);
1947             TRACE_VSVECTOR(R[5]);
1948 #endif
1949
1950             /* to next opcode token */
1951             pToken += curOpcode->num_params;
1952         }
1953 #if 0
1954         TRACE("End of current instruction:\n");
1955         TRACE_VSVECTOR(output->oPos);
1956         TRACE_VSVECTOR(output->oD[0]);
1957         TRACE_VSVECTOR(output->oD[1]);
1958         TRACE_VSVECTOR(output->oT[0]);
1959         TRACE_VSVECTOR(output->oT[1]);
1960         TRACE_VSVECTOR(R[0]);
1961         TRACE_VSVECTOR(R[1]);
1962         TRACE_VSVECTOR(R[2]);
1963         TRACE_VSVECTOR(R[3]);
1964         TRACE_VSVECTOR(R[4]);
1965         TRACE_VSVECTOR(R[5]);
1966 #endif
1967     }
1968 #if 0 /* Must not be 1 in cvs */
1969     TRACE("Output:\n");
1970     TRACE_VSVECTOR(output->oPos);
1971     TRACE_VSVECTOR(output->oD[0]);
1972     TRACE_VSVECTOR(output->oD[1]);
1973     TRACE_VSVECTOR(output->oT[0]);
1974     TRACE_VSVECTOR(output->oT[1]);
1975 #endif
1976     return WINED3D_OK;
1977 }
1978
1979 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1980     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1981     FIXME("(%p) : stub\n", This);
1982     return WINED3D_OK;
1983 }
1984
1985 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1986     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1987     FIXME("(%p) : stub\n", This);
1988     return WINED3D_OK;
1989 }
1990
1991 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1992     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1993     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1994         ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1995         return WINED3DERR_INVALIDCALL;
1996     }
1997     if (NULL == pConstantData) {
1998         return WINED3DERR_INVALIDCALL;
1999     }
2000     FIXME("(%p) : stub\n", This);
2001     return WINED3D_OK;
2002 }
2003
2004 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
2005     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2006     TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
2007     if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2008         return WINED3DERR_INVALIDCALL;
2009     }
2010     if (NULL == pConstantData) {
2011         return WINED3DERR_INVALIDCALL;
2012     }
2013     FIXME("(%p) : stub\n", This);
2014     return WINED3D_OK;
2015 }
2016
2017 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
2018     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2019     if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2020         ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
2021         return WINED3DERR_INVALIDCALL;
2022     }
2023     if (NULL == pConstantData) {
2024         return WINED3DERR_INVALIDCALL;
2025     }
2026     FIXME("(%p) : stub\n", This);
2027     return WINED3D_OK;
2028 }
2029
2030 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
2031     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
2032     FIXME("(%p) : stub\n", This);
2033     return WINED3D_OK;
2034 }
2035
2036 #endif
2037
2038 /* *******************************************
2039    IWineD3DVertexShader IUnknown parts follow
2040    ******************************************* */
2041 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
2042 {
2043     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2044     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
2045     if (IsEqualGUID(riid, &IID_IUnknown) 
2046         || IsEqualGUID(riid, &IID_IWineD3DBase)
2047         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
2048         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
2049         IUnknown_AddRef(iface);
2050         *ppobj = This;
2051         return WINED3D_OK;
2052     }
2053     return E_NOINTERFACE;
2054 }
2055
2056 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
2057     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2058     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2059     return InterlockedIncrement(&This->ref);
2060 }
2061
2062 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
2063     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2064     ULONG ref;
2065     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2066     ref = InterlockedDecrement(&This->ref);
2067     if (ref == 0) {
2068         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2069         HeapFree(GetProcessHeap(), 0, This);
2070     }
2071     return ref;
2072 }
2073
2074 /* *******************************************
2075    IWineD3DVertexShader IWineD3DVertexShader parts follow
2076    ******************************************* */
2077
2078 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2079     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2080     
2081     *parent = This->parent;
2082     IUnknown_AddRef(*parent);
2083     TRACE("(%p) : returning %p\n", This, *parent);
2084     return WINED3D_OK;
2085 }
2086
2087 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2088     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2089     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2090     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2091     TRACE("(%p) returning %p\n", This, *pDevice);
2092     return WINED3D_OK;
2093 }
2094
2095 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2096     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2097     FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2098
2099     if (NULL == pData) {
2100         *pSizeOfData = This->baseShader.functionLength;
2101         return WINED3D_OK;
2102     }
2103     if (*pSizeOfData < This->baseShader.functionLength) {
2104         *pSizeOfData = This->baseShader.functionLength;
2105         return WINED3DERR_MOREDATA;
2106     }
2107     if (NULL == This->baseShader.function) { /* no function defined */
2108         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2109         (*(DWORD **) pData) = NULL;
2110     } else {
2111         if(This->baseShader.functionLength == 0){
2112
2113         }
2114         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2115         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
2116     }
2117     return WINED3D_OK;
2118 }
2119
2120 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2121     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2122     const DWORD* pToken = pFunction;
2123     const SHADER_OPCODE* curOpcode = NULL;
2124     DWORD len = 0;
2125     DWORD i;
2126     TRACE("(%p) : Parsing programme\n", This);
2127
2128     if (NULL != pToken) {
2129         while (D3DVS_END() != *pToken) {
2130             if (vshader_is_version_token(*pToken)) { /** version */
2131                 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2132                 ++pToken;
2133                 ++len;
2134                 continue;
2135             }
2136             if (vshader_is_comment_token(*pToken)) { /** comment */
2137                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2138                 ++pToken;
2139                 TRACE("//%s\n", (char*)pToken);
2140                 pToken += comment_len;
2141                 len += comment_len + 1;
2142                 continue;
2143             }
2144             curOpcode = vshader_program_get_opcode(This, *pToken);
2145             ++pToken;
2146             ++len;
2147             if (NULL == curOpcode) {
2148                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2149                 while (*pToken & 0x80000000) {
2150                     /* unknown current opcode ... */
2151                     FIXME("unrecognized opcode: %08lx", *pToken);
2152                     ++pToken;
2153                     ++len;
2154                     TRACE("\n");
2155                 }
2156
2157             } else {
2158                 if (curOpcode->opcode == D3DSIO_DCL) {
2159                     vshader_program_dump_decl_usage(This, *pToken);
2160                     ++pToken;
2161                     ++len;
2162                     vshader_program_dump_vs_param(*pToken, 0);
2163                     ++pToken;
2164                     ++len;
2165                 } else 
2166                     if (curOpcode->opcode == D3DSIO_DEF) {
2167                         TRACE("def c%lu = ", *pToken & 0xFF);
2168                         ++pToken;
2169                         ++len;
2170                         TRACE("%f ,", *(float *)pToken);
2171                         ++pToken;
2172                         ++len;
2173                         TRACE("%f ,", *(float *)pToken);
2174                         ++pToken;
2175                         ++len;
2176                         TRACE("%f ,", *(float *)pToken);
2177                         ++pToken;
2178                         ++len;
2179                         TRACE("%f", *(float *)pToken);
2180                         ++pToken;
2181                         ++len;
2182                 } else {
2183                     TRACE("%s ", curOpcode->name);
2184                     if (curOpcode->num_params > 0) {
2185                         vshader_program_dump_vs_param(*pToken, 0);
2186                         ++pToken;
2187                         ++len;
2188                         for (i = 1; i < curOpcode->num_params; ++i) {
2189                             TRACE(", ");
2190                             vshader_program_dump_vs_param(*pToken, 1);
2191                             ++pToken;
2192                             ++len;
2193                         }
2194                     }
2195                 }
2196                 TRACE("\n");
2197             }
2198         }
2199         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
2200     } else {
2201         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
2202     }
2203
2204     /* Generate HW shader in needed */
2205     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
2206 #if 1
2207         IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2208 #endif
2209     }
2210
2211     /* copy the function ... because it will certainly be released by application */
2212     if (NULL != pFunction) {
2213         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
2214         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
2215     } else {
2216         This->baseShader.function = NULL;
2217     }
2218     return WINED3D_OK;
2219 }
2220
2221 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2222 {
2223     /*** IUnknown methods ***/
2224     IWineD3DVertexShaderImpl_QueryInterface,
2225     IWineD3DVertexShaderImpl_AddRef,
2226     IWineD3DVertexShaderImpl_Release,
2227     /*** IWineD3DBase methods ***/
2228     IWineD3DVertexShaderImpl_GetParent,
2229     /*** IWineD3DBaseShader methods ***/
2230     IWineD3DVertexShaderImpl_SetFunction,
2231     /*** IWineD3DVertexShader methods ***/
2232     IWineD3DVertexShaderImpl_GetDevice,
2233     IWineD3DVertexShaderImpl_GetFunction
2234 };