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