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