.gitignore: Added wildcards to ignore generated resource files.
[wine] / dlls / wined3d / vertexshader.c
1 /*
2  * shaders implementation
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  * Copyright 2006 Ivan Gyurdiev
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25
26 #include <math.h>
27 #include <stdio.h>
28
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
32
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34
35 /* Shader debugging - Change the following line to enable debugging of software
36       vertex shaders                                                             */
37 #if 0 /* Musxt not be 1 in cvs version */
38 # define VSTRACE(A) TRACE A
39 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
40 #else
41 # define VSTRACE(A)
42 # define TRACE_VSVECTOR(name)
43 #endif
44
45 /**
46  * DirectX9 SDK download
47  *  http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
48  *
49  * Exploring D3DX
50  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
51  *
52  * Using Vertex Shaders
53  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
54  *
55  * Dx9 New
56  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
57  *
58  * Dx9 Shaders
59  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
60  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
61  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
62  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
63  *
64  * Dx9 D3DX
65  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
66  *
67  * FVF
68  *  http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
69  *
70  * NVIDIA: DX8 Vertex Shader to NV Vertex Program
71  *  http://developer.nvidia.com/view.asp?IO=vstovp
72  *
73  * NVIDIA: Memory Management with VAR
74  *  http://developer.nvidia.com/view.asp?IO=var_memory_management
75  */
76
77 /* 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
78 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 */
79
80 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
81
82 /*******************************
83  * vshader functions software VM
84  */
85
86 static void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
87   d->x = s0->x + s1->x;
88   d->y = s0->y + s1->y;
89   d->z = s0->z + s1->z;
90   d->w = s0->w + s1->w;
91   VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
92                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
93 }
94
95 static void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
96   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
97   VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
98                  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
99 }
100
101 static void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
102   d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
103   VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
104           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
105 }
106
107 static void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
108   d->x = 1.0f;
109   d->y = s0->y * s1->y;
110   d->z = s0->z;
111   d->w = s1->w;
112   VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
113           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
114 }
115
116 static void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
117   union {
118     float f;
119     DWORD d;
120   } tmp;
121
122   tmp.f = floorf(s0->w);
123   d->x  = powf(2.0f, tmp.f);
124   d->y  = s0->w - tmp.f;
125   tmp.f = powf(2.0f, s0->w);
126   tmp.d &= 0xFFFFFF00U;
127   d->z  = tmp.f;
128   d->w  = 1.0f;
129   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
130                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
131 }
132
133 static void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
134   d->x = 1.0f;
135   d->y = (0.0f < s0->x) ? s0->x : 0.0f;
136   d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
137   d->w = 1.0f;
138   VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
139                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
140 }
141
142 static void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
143   float tmp_f = fabsf(s0->w);
144   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
145   VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
146                  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
147 }
148
149 static void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
150   d->x = s0->x * s1->x + s2->x;
151   d->y = s0->y * s1->y + s2->y;
152   d->z = s0->z * s1->z + s2->z;
153   d->w = s0->w * s1->w + s2->w;
154   VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
155           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));
156 }
157
158 static void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
159   d->x = (s0->x >= s1->x) ? s0->x : s1->x;
160   d->y = (s0->y >= s1->y) ? s0->y : s1->y;
161   d->z = (s0->z >= s1->z) ? s0->z : s1->z;
162   d->w = (s0->w >= s1->w) ? s0->w : s1->w;
163   VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
164           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
165 }
166
167 static void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
168   d->x = (s0->x < s1->x) ? s0->x : s1->x;
169   d->y = (s0->y < s1->y) ? s0->y : s1->y;
170   d->z = (s0->z < s1->z) ? s0->z : s1->z;
171   d->w = (s0->w < s1->w) ? s0->w : s1->w;
172   VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
173           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
174 }
175
176 static void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
177   d->x = s0->x;
178   d->y = s0->y;
179   d->z = s0->z;
180   d->w = s0->w;
181   VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
182           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
183 }
184
185 static void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
186   d->x = s0->x * s1->x;
187   d->y = s0->y * s1->y;
188   d->z = s0->z * s1->z;
189   d->w = s0->w * s1->w;
190   VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
191           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
192 }
193
194 static void vshader_nop(void) {
195     /* NOPPPP ahhh too easy ;) */
196     VSTRACE(("executing nop\n"));
197 }
198
199 static void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
200   d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
201   VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
202           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
203 }
204
205 static void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
206   float tmp_f = fabsf(s0->w);
207   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);
208   VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
209           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
210 }
211
212 static void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
213   d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
214   d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
215   d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
216   d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
217   VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
218           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
219 }
220
221 static void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
222   d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
223   d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
224   d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
225   d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
226   VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
227           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
228 }
229
230 static void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
231   d->x = s0->x - s1->x;
232   d->y = s0->y - s1->y;
233   d->z = s0->z - s1->z;
234   d->w = s0->w - s1->w;
235   VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
236           s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
237 }
238
239 /**
240  * Version 1.1 specific
241  */
242
243 static void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
244   d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
245   VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
246           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
247 }
248
249 static void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
250   float tmp_f = fabsf(s0->w);
251   d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
252   VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
253           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
254 }
255
256 static void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
257   d->x = s0->x - floorf(s0->x);
258   d->y = s0->y - floorf(s0->y);
259   d->z = 0.0f;
260   d->w = 1.0f;
261   VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
262           s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
263 }
264
265 typedef FLOAT D3DMATRIX44[4][4];
266 typedef FLOAT D3DMATRIX43[4][3];
267 typedef FLOAT D3DMATRIX34[3][4];
268 typedef FLOAT D3DMATRIX33[3][3];
269 typedef FLOAT D3DMATRIX23[2][3];
270
271 static void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
272   /*
273    * Buggy CODE: here only if cast not work for copy/paste
274   WINED3DSHADERVECTOR* mat2 = mat1 + 1;
275   WINED3DSHADERVECTOR* mat3 = mat1 + 2;
276   WINED3DSHADERVECTOR* mat4 = mat1 + 3;
277   d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
278   d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
279   d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
280   d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
281   */
282   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
283   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
284   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
285   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
286   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));
287   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));
288   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));
289   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));
290 }
291
292 static void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
293   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
294   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
295   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
296   d->w = 1.0f;
297   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));
298   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));
299   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));
300   VSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
301 }
302
303 static void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
304   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
305   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
306   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
307   d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
308   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));
309   VSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
310   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));
311   VSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
312 }
313
314 static void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
315   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
316   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
317   d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
318   d->w = 1.0f;
319   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));
320   VSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
321   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));
322   VSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
323 }
324
325 static void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
326   FIXME("check\n");
327   d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
328   d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
329   d->z = 0.0f;
330   d->w = 1.0f;
331 }
332
333 /**
334  * Version 2.0 specific
335  */
336 static void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
337   d->x = s0->x * (s1->x - s2->x) + s2->x;
338   d->y = s0->y * (s1->y - s2->y) + s2->y;
339   d->z = s0->z * (s1->z - s2->z) + s2->z;
340   d->w = s0->w * (s1->w - s2->w) + s2->w;
341 }
342
343 static void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
344   d->x = s0->y * s1->z - s0->z * s1->y;
345   d->y = s0->z * s1->x - s0->x * s1->z;
346   d->z = s0->x * s1->y - s0->y * s1->x;
347   d->w = 0.9f; /* w is undefined, so set it to something safeish */
348
349   VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
350              s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
351 }
352
353 static void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
354
355   d->x = fabsf(s0->x);
356   d->y = fabsf(s0->y);
357   d->z = fabsf(s0->z);
358   d->w = fabsf(s0->w);
359   VSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
360              s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
361 }
362
363     /* Stubs */
364
365 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
366 static void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
367     FIXME(" : Stub\n");
368 }
369
370 static void vshader_call(WINED3DSHADERVECTOR* d) {
371     FIXME(" : Stub\n");
372 }
373
374 static void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
375     FIXME(" : Stub\n");
376 }
377
378 static void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
379     FIXME(" : Stub\n");
380 }
381
382 static void vshader_ret(void) {
383     FIXME(" : Stub\n");
384 }
385
386 static void vshader_endloop(void) {
387     FIXME(" : Stub\n");
388 }
389
390 static void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
391     FIXME(" : Stub\n");
392 }
393
394 static void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
395     FIXME(" : Stub\n");
396 }
397
398 static void vshader_sgn(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
399     FIXME(" : Stub\n");
400 }
401
402 static void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
403     FIXME(" : Stub\n");
404 }
405
406 static void vshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
407     FIXME(" : Stub\n");
408 }
409
410 static void vshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
411      FIXME(" : Stub\n");
412 }
413
414 static void vshader_rep(WINED3DSHADERVECTOR* d) {
415     FIXME(" : Stub\n");
416 }
417
418 static void vshader_endrep(void) {
419     FIXME(" : Stub\n");
420 }
421
422 static void vshader_if(WINED3DSHADERVECTOR* d) {
423     FIXME(" : Stub\n");
424 }
425
426 static void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
427     FIXME(" : Stub\n");
428 }
429
430 static void vshader_else(void) {
431     FIXME(" : Stub\n");
432 }
433
434 static void vshader_label(WINED3DSHADERVECTOR* d) {
435     FIXME(" : Stub\n");
436 }
437
438 static void vshader_endif(void) {
439     FIXME(" : Stub\n");
440 }
441
442 static void vshader_break(void) {
443     FIXME(" : Stub\n");
444 }
445
446 static void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
447     FIXME(" : Stub\n");
448 }
449
450 static void vshader_breakp(WINED3DSHADERVECTOR* d) {
451     FIXME(" : Stub\n");
452 }
453
454 static void vshader_mova(WINED3DSHADERVECTOR* d) {
455     FIXME(" : Stub\n");
456 }
457
458 static void vshader_defb(WINED3DSHADERVECTOR* d) {
459     FIXME(" : Stub\n");
460 }
461
462 static void vshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
463     FIXME(" : Stub\n");
464 }
465
466 static void vshader_setp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
467     FIXME(" : Stub\n");
468 }
469
470 static void vshader_texldl(WINED3DSHADERVECTOR* d) {
471     FIXME(" : Stub\n");
472 }
473
474 /**
475  * log, exp, frc, m*x* seems to be macros ins ... to see
476  */
477 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
478
479     /* Arithmetic */ 
480     {D3DSIO_NOP,  "nop",  "NOP", 0, 0, vshader_nop,  vshader_hw_map2gl, NULL, 0, 0},
481     {D3DSIO_MOV,  "mov",  "MOV", 1, 2, vshader_mov,  vshader_hw_map2gl, shader_glsl_mov, 0, 0},
482     {D3DSIO_ADD,  "add",  "ADD", 1, 3, vshader_add,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
483     {D3DSIO_SUB,  "sub",  "SUB", 1, 3, vshader_sub,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
484     {D3DSIO_MAD,  "mad",  "MAD", 1, 4, vshader_mad,  vshader_hw_map2gl, shader_glsl_mad, 0, 0},
485     {D3DSIO_MUL,  "mul",  "MUL", 1, 3, vshader_mul,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
486     {D3DSIO_RCP,  "rcp",  "RCP", 1, 2, vshader_rcp,  vshader_hw_map2gl, shader_glsl_rcp, 0, 0},
487     {D3DSIO_RSQ,  "rsq",  "RSQ", 1, 2, vshader_rsq,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
488     {D3DSIO_DP3,  "dp3",  "DP3", 1, 3, vshader_dp3,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
489     {D3DSIO_DP4,  "dp4",  "DP4", 1, 3, vshader_dp4,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
490     {D3DSIO_MIN,  "min",  "MIN", 1, 3, vshader_min,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
491     {D3DSIO_MAX,  "max",  "MAX", 1, 3, vshader_max,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
492     {D3DSIO_SLT,  "slt",  "SLT", 1, 3, vshader_slt,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
493     {D3DSIO_SGE,  "sge",  "SGE", 1, 3, vshader_sge,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
494     {D3DSIO_ABS,  "abs",  "ABS", 1, 2, vshader_abs,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
495     {D3DSIO_EXP,  "exp",  "EX2", 1, 2, vshader_exp,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
496     {D3DSIO_LOG,  "log",  "LG2", 1, 2, vshader_log,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
497     {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
498     {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
499     {D3DSIO_LIT,  "lit",  "LIT", 1, 2, vshader_lit,  vshader_hw_map2gl, shader_glsl_lit, 0, 0},
500     {D3DSIO_DST,  "dst",  "DST", 1, 3, vshader_dst,  vshader_hw_map2gl, shader_glsl_dst, 0, 0},
501     {D3DSIO_LRP,  "lrp",  "LRP", 1, 4, vshader_lrp,  NULL,              shader_glsl_lrp, 0, 0},
502     {D3DSIO_FRC,  "frc",  "FRC", 1, 2, vshader_frc,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
503     {D3DSIO_POW,  "pow",  "POW", 1, 3, vshader_pow,  NULL, shader_glsl_map2gl, 0, 0},
504     {D3DSIO_CRS,  "crs",  "XPS", 1, 3, vshader_crs,  NULL, shader_glsl_map2gl, 0, 0},
505     /* TODO: sng can possibly be performed a  s
506         RCP tmp, vec
507         MUL out, tmp, vec*/
508     {D3DSIO_SGN,  "sgn",  NULL, 1, 2, vshader_sgn,  NULL,   shader_glsl_map2gl, 0, 0},
509     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
510         DP3 tmp , vec, vec;
511         RSQ tmp, tmp.x;
512         MUL vec.xyz, vec, tmp;
513     but I think this is better because it accounts for w properly.
514         DP3 tmp , vec, vec;
515         RSQ tmp, tmp.x;
516         MUL vec, vec, tmp;
517
518     */
519     {D3DSIO_NRM,      "nrm",      NULL, 1, 2, vshader_nrm,    NULL, shader_glsl_map2gl, 0, 0},
520     {D3DSIO_SINCOS,   "sincos",   NULL, 1, 4, vshader_sincos2, NULL, shader_glsl_sincos, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
521     {D3DSIO_SINCOS,   "sincos",   NULL, 1, 2, vshader_sincos3, NULL, shader_glsl_sincos, D3DVS_VERSION(3,0), -1},
522
523     /* Matrix */
524     {D3DSIO_M4x4, "m4x4", "undefined", 1, 3, vshader_m4x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
525     {D3DSIO_M4x3, "m4x3", "undefined", 1, 3, vshader_m4x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
526     {D3DSIO_M3x4, "m3x4", "undefined", 1, 3, vshader_m3x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
527     {D3DSIO_M3x3, "m3x3", "undefined", 1, 3, vshader_m3x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
528     {D3DSIO_M3x2, "m3x2", "undefined", 1, 3, vshader_m3x2, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
529
530     /* Declare registers */
531     {D3DSIO_DCL,      "dcl",      NULL,                0, 2, vshader_dcl,     NULL, NULL, 0, 0},
532
533     /* Constant definitions */
534     {D3DSIO_DEF,      "def",      NULL,                1, 5, vshader_def,     shader_hw_def, shader_glsl_def, 0, 0},
535     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_defb,    NULL, shader_glsl_defb, 0, 0},
536     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi,    NULL, shader_glsl_defi, 0, 0},
537
538     /* Flow control - requires GLSL or software shaders */
539     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL, 0, 1, vshader_rep,     NULL, NULL, 0, 0},
540     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL, 0, 0, vshader_endrep,  NULL, NULL, 0, 0},
541     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL, 0, 1, vshader_if,      NULL, NULL, 0, 0},
542     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL, 0, 2, vshader_ifc,     NULL, NULL, 0, 0},
543     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL, 0, 0, vshader_else,    NULL, NULL, 0, 0},
544     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL, 0, 0, vshader_endif,   NULL, NULL, 0, 0},
545     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL, 0, 0, vshader_break,   NULL, NULL, 0, 0},
546     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL, 0, 2, vshader_breakc,  NULL, NULL, 0, 0},
547     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp,  NULL, NULL, 0, 0},
548     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL, 0, 1, vshader_call,    NULL, NULL, 0, 0},
549     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL, 0, 2, vshader_callnz,  NULL, NULL, 0, 0},
550     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL, 0, 2, vshader_loop,    NULL, shader_glsl_loop, 0, 0},
551     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL, 0, 0, vshader_ret,     NULL, NULL, 0, 0},
552     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL, 0, 0, vshader_endloop, NULL, shader_glsl_endloop, 0, 0},
553     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL, 0, 1, vshader_label,   NULL, NULL, 0, 0},
554
555     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova,    NULL, shader_glsl_mov, 0, 0},
556     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL, 1, 3, vshader_setp,    NULL, NULL, 0, 0},
557     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL, 1, 2, vshader_texldl,  NULL, NULL, 0, 0},
558     {0,               NULL,       NULL,   0, 0, NULL,            NULL, 0, 0}
559 };
560
561 static void vshader_set_limits(
562       IWineD3DVertexShaderImpl *This) {
563
564       This->baseShader.limits.texcoord = 0;
565       This->baseShader.limits.attributes = 16;
566       This->baseShader.limits.packed_input = 0;
567
568       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
569       This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
570
571       switch (This->baseShader.hex_version) {
572           case D3DVS_VERSION(1,0):
573           case D3DVS_VERSION(1,1):
574                    This->baseShader.limits.temporary = 12;
575                    This->baseShader.limits.constant_bool = 0;
576                    This->baseShader.limits.constant_int = 0;
577                    This->baseShader.limits.address = 1;
578                    This->baseShader.limits.packed_output = 0;
579                    This->baseShader.limits.sampler = 0;
580                    break;
581       
582           case D3DVS_VERSION(2,0):
583           case D3DVS_VERSION(2,1):
584                    This->baseShader.limits.temporary = 12;
585                    This->baseShader.limits.constant_bool = 16;
586                    This->baseShader.limits.constant_int = 16;
587                    This->baseShader.limits.address = 1;
588                    This->baseShader.limits.packed_output = 0;
589                    This->baseShader.limits.sampler = 0;
590                    break;
591
592           case D3DVS_VERSION(3,0):
593                    This->baseShader.limits.temporary = 32;
594                    This->baseShader.limits.constant_bool = 32;
595                    This->baseShader.limits.constant_int = 32;
596                    This->baseShader.limits.address = 1;
597                    This->baseShader.limits.packed_output = 12;
598                    This->baseShader.limits.sampler = 4;
599                    break;
600
601           default: This->baseShader.limits.temporary = 12;
602                    This->baseShader.limits.constant_bool = 16;
603                    This->baseShader.limits.constant_int = 16;
604                    This->baseShader.limits.address = 1;
605                    This->baseShader.limits.packed_output = 0;
606                    This->baseShader.limits.sampler = 0;
607                    FIXME("Unrecognized vertex shader version %#lx\n",
608                        This->baseShader.hex_version);
609       }
610 }
611
612 /* This is an internal function,
613  * used to create fake semantics for shaders
614  * that don't have them - d3d8 shaders where the declaration
615  * stores the register for each input
616  */
617 static void vshader_set_input(
618     IWineD3DVertexShaderImpl* This,
619     unsigned int regnum,
620     BYTE usage, BYTE usage_idx) {
621
622     /* Fake usage: set reserved bit, usage, usage_idx */
623     DWORD usage_token = (0x1 << 31) |
624         (usage << D3DSP_DCL_USAGE_SHIFT) | (usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT);
625
626     /* Fake register; set reserved bit, regnum, type: input, wmask: all */
627     DWORD reg_token = (0x1 << 31) |
628         D3DSP_WRITEMASK_ALL | (D3DSPR_INPUT << D3DSP_REGTYPE_SHIFT) | regnum;
629
630     This->semantics_in[regnum].usage = usage_token;
631     This->semantics_in[regnum].reg = reg_token;
632 }
633
634 BOOL vshader_get_input(
635     IWineD3DVertexShader* iface,
636     BYTE usage_req, BYTE usage_idx_req,
637     unsigned int* regnum) {
638
639     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
640     int i;
641
642     for (i = 0; i < MAX_ATTRIBS; i++) {
643         DWORD usage_token = This->semantics_in[i].usage;
644         DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
645         DWORD usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
646
647         if (usage_token && (usage == usage_req && usage_idx == usage_idx_req)) {
648             *regnum = i;
649             return TRUE;
650         }
651     }
652     return FALSE;
653 }
654
655 BOOL vshader_input_is_color(
656     IWineD3DVertexShader* iface,
657     unsigned int regnum) {
658
659     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
660     DWORD usage_token = This->semantics_in[regnum].usage;
661     DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
662
663     /* FIXME: D3D8 shader: the semantics token is not the way to 
664      * determine color info, since it is just a fake map to shader inputs */
665     if (This->vertexDeclaration != NULL)
666         return FALSE; 
667     else
668         return usage == D3DDECLUSAGE_COLOR;
669 }
670
671 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
672     or GLSL and send it to the card */
673 static VOID IWineD3DVertexShaderImpl_GenerateShader(
674     IWineD3DVertexShader *iface,
675     shader_reg_maps* reg_maps,
676     CONST DWORD *pFunction) {
677
678     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
679     SHADER_BUFFER buffer;
680
681 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
682         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
683     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
684         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
685         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
686         This->fixupVertexBufferSize = PGMSIZE;
687         This->fixupVertexBuffer[0] = 0;
688     }
689     buffer.buffer = This->device->fixupVertexBuffer;
690 #else
691     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
692 #endif
693     buffer.bsize = 0;
694     buffer.lineNo = 0;
695
696     if (This->baseShader.shader_mode == SHADER_GLSL) {
697
698         /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
699         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
700
701         /* Base Declarations */
702         shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
703
704         /* Base Shader Body */
705         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
706
707         /* Unpack 3.0 outputs */
708         if (This->baseShader.hex_version >= D3DVS_VERSION(3,0))
709             vshader_glsl_output_unpack(&buffer, This->semantics_out);
710
711         shader_addline(&buffer, "}\n\0");
712
713         TRACE("Compiling shader object %u\n", shader_obj);
714         GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
715         GL_EXTCALL(glCompileShaderARB(shader_obj));
716         print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
717
718         /* Store the shader object */
719         This->baseShader.prgId = shader_obj;
720
721     } else if (This->baseShader.shader_mode == SHADER_ARB) {
722
723         /*  Create the hw ARB shader */
724         shader_addline(&buffer, "!!ARBvp1.0\n");
725
726         /* Mesa supports only 95 constants */
727         if (GL_VEND(MESA) || GL_VEND(WINE))
728             This->baseShader.limits.constant_float = 
729                 min(95, This->baseShader.limits.constant_float);
730
731         /* Base Declarations */
732         shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
733
734         /* Base Shader Body */
735         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
736
737         shader_addline(&buffer, "END\n\0"); 
738
739         /* TODO: change to resource.glObjectHandle or something like that */
740         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
741
742         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
743         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
744
745         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
746         /* Create the program and check for errors */
747         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
748             buffer.bsize, buffer.buffer));
749
750         if (glGetError() == GL_INVALID_OPERATION) {
751             GLint errPos;
752             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
753             FIXME("HW VertexShader Error at position %d: %s\n",
754                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
755             This->baseShader.prgId = -1;
756         }
757     }
758
759 #if 1 /* if were using the data buffer of device then we don't need to free it */
760   HeapFree(GetProcessHeap(), 0, buffer.buffer);
761 #endif
762 }
763
764 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
765   /**
766    * TODO: use the NV_vertex_program (or 1_1) extension
767    *  and specifics vendors (ARB_vertex_program??) variants for it
768    */
769   return TRUE;
770 }
771
772 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
773     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
774     DWORD opcode_token;   
775  
776     /** Vertex Shader Temporary Registers */
777     WINED3DSHADERVECTOR R[12];
778       /*D3DSHADERSCALAR A0;*/
779     WINED3DSHADERVECTOR A[1];
780     /** temporary Vector for modifier management */
781     WINED3DSHADERVECTOR d;
782     WINED3DSHADERVECTOR s[3];
783     /** parser datas */
784     const DWORD* pToken = This->baseShader.function;
785     const SHADER_OPCODE* curOpcode = NULL;
786     /** functions parameters */
787     WINED3DSHADERVECTOR* p[6];
788     WINED3DSHADERVECTOR* p_send[6];
789     DWORD i;
790
791     /** init temporary register */
792     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
793
794     /* vshader_program_parse(vshader); */
795 #if 0 /* Must not be 1 in cvs */
796     TRACE("Input:\n");
797     TRACE_VSVECTOR(This->data->C[0]);
798     TRACE_VSVECTOR(This->data->C[1]);
799     TRACE_VSVECTOR(This->data->C[2]);
800     TRACE_VSVECTOR(This->data->C[3]);
801     TRACE_VSVECTOR(This->data->C[4]);
802     TRACE_VSVECTOR(This->data->C[5]);
803     TRACE_VSVECTOR(This->data->C[6]);
804     TRACE_VSVECTOR(This->data->C[7]);
805     TRACE_VSVECTOR(This->data->C[8]);
806     TRACE_VSVECTOR(This->data->C[64]);
807     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
808     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
809     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
810     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
811     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
812     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
813     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
814     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
815     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
816 #endif
817
818     TRACE_VSVECTOR(vshader->data->C[64]);
819     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
820
821     /* the first dword is the version tag */
822     /* TODO: parse it */
823
824     if (shader_is_vshader_version(*pToken)) { /** version */
825         ++pToken;
826     }
827     while (D3DVS_END() != *pToken) {
828         if (shader_is_comment(*pToken)) { /** comment */
829             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
830             ++pToken;
831             pToken += comment_len;
832             continue ;
833         }
834
835         opcode_token = *pToken++;
836         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
837
838         if (NULL == curOpcode) {
839             FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
840             pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
841             /* return FALSE; */
842
843         } else {
844             if (curOpcode->num_params > 0) {
845                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
846                 for (i = 0; i < curOpcode->num_params; ++i) {
847                     DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
848                     DWORD regtype = shader_get_regtype(pToken[i]);
849     
850                     switch (regtype) {
851                     case D3DSPR_TEMP:
852                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
853                         p[i] = &R[reg];
854                         break;
855                     case D3DSPR_INPUT:
856                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
857                         p[i] = &input->V[reg];
858                         break;
859                     case D3DSPR_CONST:
860                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
861                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
862                         } else {
863                             p[i] = &This->data->C[reg];
864                         }
865                         break;
866                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
867                         if (0 != reg) {
868                             ERR("cannot handle address registers != a0, forcing use of a0\n");
869                             reg = 0;
870                         }
871                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
872                         p[i] = &A[reg];
873                         break;
874                     case D3DSPR_RASTOUT:
875                         switch (reg) {
876                         case D3DSRO_POSITION:
877                             p[i] = &output->oPos;
878                             break;
879                         case D3DSRO_FOG:
880                             p[i] = &output->oFog;
881                             break;
882                         case D3DSRO_POINT_SIZE:
883                             p[i] = &output->oPts;
884                             break;
885                         }
886                         break;
887                     case D3DSPR_ATTROUT:
888                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
889                         p[i] = &output->oD[reg];
890                         break;
891                     case D3DSPR_TEXCRDOUT:
892                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
893                         p[i] = &output->oT[reg];
894                         break;
895                     /* TODO Decls and defs */
896 #if 0
897                     case D3DSPR_DCL:
898                     case D3DSPR_DEF:
899 #endif
900                     default:
901                         break;
902                     }
903
904                     if (i > 0) { /* input reg */
905                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
906                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
907
908                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
909                             /* TRACE("p[%d] not swizzled\n", i); */
910                             p_send[i] = p[i];
911                         } else {
912                             DWORD swizzle_x = swizzle & 0x03;
913                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
914                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
915                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
916                             /* TRACE("p[%d] swizzled\n", i); */
917                             float* tt = (float*) p[i];
918                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
919                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
920                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
921                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
922                             p_send[i] = &s[i];
923                         }
924                     } else { /* output reg */
925                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
926                             p_send[i] = p[i];
927                         } else {
928                             p_send[i] = &d; /* to be post-processed for modifiers management */
929                         }
930                     }
931                 }
932             }
933
934             switch (curOpcode->num_params) {
935             case 0:
936                 curOpcode->soft_fct();
937                 break;
938             case 1:
939                 curOpcode->soft_fct(p_send[0]);
940             break;
941             case 2:
942                 curOpcode->soft_fct(p_send[0], p_send[1]);
943                 break;
944             case 3:
945                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
946                 break;
947             case 4:
948                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
949                 break;
950             case 5:
951                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
952                 break;
953             case 6:
954                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
955                 break;
956             default:
957                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
958             }
959
960             /* check if output reg modifier post-process */
961             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
962                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
963                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
964                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
965                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
966             }
967 #if 0
968             TRACE_VSVECTOR(output->oPos);
969             TRACE_VSVECTOR(output->oD[0]);
970             TRACE_VSVECTOR(output->oD[1]);
971             TRACE_VSVECTOR(output->oT[0]);
972             TRACE_VSVECTOR(output->oT[1]);
973             TRACE_VSVECTOR(R[0]);
974             TRACE_VSVECTOR(R[1]);
975             TRACE_VSVECTOR(R[2]);
976             TRACE_VSVECTOR(R[3]);
977             TRACE_VSVECTOR(R[4]);
978             TRACE_VSVECTOR(R[5]);
979 #endif
980
981             /* to next opcode token */
982             pToken += curOpcode->num_params;
983         }
984 #if 0
985         TRACE("End of current instruction:\n");
986         TRACE_VSVECTOR(output->oPos);
987         TRACE_VSVECTOR(output->oD[0]);
988         TRACE_VSVECTOR(output->oD[1]);
989         TRACE_VSVECTOR(output->oT[0]);
990         TRACE_VSVECTOR(output->oT[1]);
991         TRACE_VSVECTOR(R[0]);
992         TRACE_VSVECTOR(R[1]);
993         TRACE_VSVECTOR(R[2]);
994         TRACE_VSVECTOR(R[3]);
995         TRACE_VSVECTOR(R[4]);
996         TRACE_VSVECTOR(R[5]);
997 #endif
998     }
999 #if 0 /* Must not be 1 in cvs */
1000     TRACE("Output:\n");
1001     TRACE_VSVECTOR(output->oPos);
1002     TRACE_VSVECTOR(output->oD[0]);
1003     TRACE_VSVECTOR(output->oD[1]);
1004     TRACE_VSVECTOR(output->oT[0]);
1005     TRACE_VSVECTOR(output->oT[1]);
1006 #endif
1007     return WINED3D_OK;
1008 }
1009
1010 /* *******************************************
1011    IWineD3DVertexShader IUnknown parts follow
1012    ******************************************* */
1013 static HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1014 {
1015     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1016     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1017     if (IsEqualGUID(riid, &IID_IUnknown) 
1018         || IsEqualGUID(riid, &IID_IWineD3DBase)
1019         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1020         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1021         IUnknown_AddRef(iface);
1022         *ppobj = This;
1023         return S_OK;
1024     }
1025     *ppobj = NULL;
1026     return E_NOINTERFACE;
1027 }
1028
1029 static ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1030     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1031     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1032     return InterlockedIncrement(&This->ref);
1033 }
1034
1035 static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1036     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1037     ULONG ref;
1038     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1039     ref = InterlockedDecrement(&This->ref);
1040     if (ref == 0) {
1041         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1042         if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
1043             /* If this shader is still attached to a program, GL will perform a lazy delete */
1044             TRACE("Deleting shader object %u\n", This->baseShader.prgId);
1045             GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
1046             checkGLcall("glDeleteObjectARB");
1047         }
1048             HeapFree(GetProcessHeap(), 0, This);
1049     }
1050     return ref;
1051 }
1052
1053 /* *******************************************
1054    IWineD3DVertexShader IWineD3DVertexShader parts follow
1055    ******************************************* */
1056
1057 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1058     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1059     
1060     *parent = This->parent;
1061     IUnknown_AddRef(*parent);
1062     TRACE("(%p) : returning %p\n", This, *parent);
1063     return WINED3D_OK;
1064 }
1065
1066 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1067     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1068     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1069     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1070     TRACE("(%p) returning %p\n", This, *pDevice);
1071     return WINED3D_OK;
1072 }
1073
1074 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1075     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1076     TRACE("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1077
1078     if (NULL == pData) {
1079         *pSizeOfData = This->baseShader.functionLength;
1080         return WINED3D_OK;
1081     }
1082     if (*pSizeOfData < This->baseShader.functionLength) {
1083         *pSizeOfData = This->baseShader.functionLength;
1084         return WINED3DERR_MOREDATA;
1085     }
1086     if (NULL == This->baseShader.function) { /* no function defined */
1087         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1088         (*(DWORD **) pData) = NULL;
1089     } else {
1090         if(This->baseShader.functionLength == 0){
1091
1092         }
1093         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1094         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1095     }
1096     return WINED3D_OK;
1097 }
1098
1099 static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1100
1101     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1102     shader_reg_maps reg_maps;
1103
1104     /* First pass: trace shader */
1105     shader_trace_init((IWineD3DBaseShader*) This, pFunction);
1106     vshader_set_limits(This);
1107
1108     /* Preload semantics for d3d8 shaders */
1109     if (This->vertexDeclaration) {
1110        IWineD3DVertexDeclarationImpl* vdecl = (IWineD3DVertexDeclarationImpl*) This->vertexDeclaration;
1111        int i;
1112        for (i = 0; i < vdecl->declarationWNumElements - 1; ++i) {
1113            WINED3DVERTEXELEMENT* element = vdecl->pDeclarationWine + i;
1114            vshader_set_input(This, element->Reg, element->Usage, element->UsageIndex);
1115        }
1116     }
1117
1118     /* Second pass: figure out registers used, semantics, etc.. */
1119     memset(&reg_maps, 0, sizeof(shader_reg_maps));
1120     shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
1121        This->semantics_in, This->semantics_out, pFunction);
1122
1123     /* Generate HW shader in needed */
1124     This->baseShader.shader_mode = wined3d_settings.vs_selected_mode;
1125     if (NULL != pFunction && This->baseShader.shader_mode != SHADER_SW) 
1126         IWineD3DVertexShaderImpl_GenerateShader(iface, &reg_maps, pFunction);
1127
1128     /* copy the function ... because it will certainly be released by application */
1129     if (NULL != pFunction) {
1130         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1131         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1132     } else {
1133         This->baseShader.function = NULL;
1134     }
1135
1136     return WINED3D_OK;
1137 }
1138
1139 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1140 {
1141     /*** IUnknown methods ***/
1142     IWineD3DVertexShaderImpl_QueryInterface,
1143     IWineD3DVertexShaderImpl_AddRef,
1144     IWineD3DVertexShaderImpl_Release,
1145     /*** IWineD3DBase methods ***/
1146     IWineD3DVertexShaderImpl_GetParent,
1147     /*** IWineD3DBaseShader methods ***/
1148     IWineD3DVertexShaderImpl_SetFunction,
1149     /*** IWineD3DVertexShader methods ***/
1150     IWineD3DVertexShaderImpl_GetDevice,
1151     IWineD3DVertexShaderImpl_GetFunction
1152 };