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