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