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