wined3d: Fix matching WINED3DDECLUSAGE_POSITION against WINED3DDECLUSAGE_POSITIONT.
[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     /* This table is not order or position dependent. */
477     
478     /* Arithmetic */ 
479     {WINED3DSIO_NOP,  "nop",  "NOP", 0, 0, vshader_nop,  vshader_hw_map2gl, NULL, 0, 0},
480     {WINED3DSIO_MOV,  "mov",  "MOV", 1, 2, vshader_mov,  vshader_hw_map2gl, shader_glsl_mov, 0, 0},
481     {WINED3DSIO_MOVA, "mova",  NULL, 1, 2, vshader_mova, vshader_hw_map2gl, shader_glsl_mov, WINED3DVS_VERSION(2,0), -1},
482     {WINED3DSIO_ADD,  "add",  "ADD", 1, 3, vshader_add,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
483     {WINED3DSIO_SUB,  "sub",  "SUB", 1, 3, vshader_sub,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
484     {WINED3DSIO_MAD,  "mad",  "MAD", 1, 4, vshader_mad,  vshader_hw_map2gl, shader_glsl_mad, 0, 0},
485     {WINED3DSIO_MUL,  "mul",  "MUL", 1, 3, vshader_mul,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
486     {WINED3DSIO_RCP,  "rcp",  "RCP", 1, 2, vshader_rcp,  vshader_hw_rsq_rcp,shader_glsl_rcp, 0, 0},
487     {WINED3DSIO_RSQ,  "rsq",  "RSQ", 1, 2, vshader_rsq,  vshader_hw_rsq_rcp,shader_glsl_map2gl, 0, 0},
488     {WINED3DSIO_DP3,  "dp3",  "DP3", 1, 3, vshader_dp3,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
489     {WINED3DSIO_DP4,  "dp4",  "DP4", 1, 3, vshader_dp4,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
490     {WINED3DSIO_MIN,  "min",  "MIN", 1, 3, vshader_min,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
491     {WINED3DSIO_MAX,  "max",  "MAX", 1, 3, vshader_max,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
492     {WINED3DSIO_SLT,  "slt",  "SLT", 1, 3, vshader_slt,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
493     {WINED3DSIO_SGE,  "sge",  "SGE", 1, 3, vshader_sge,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
494     {WINED3DSIO_ABS,  "abs",  "ABS", 1, 2, vshader_abs,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
495     {WINED3DSIO_EXP,  "exp",  "EX2", 1, 2, vshader_exp,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
496     {WINED3DSIO_LOG,  "log",  "LG2", 1, 2, vshader_log,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
497     {WINED3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_expp, 0, 0},
498     {WINED3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
499     {WINED3DSIO_LIT,  "lit",  "LIT", 1, 2, vshader_lit,  vshader_hw_map2gl, shader_glsl_lit, 0, 0},
500     {WINED3DSIO_DST,  "dst",  "DST", 1, 3, vshader_dst,  vshader_hw_map2gl, shader_glsl_dst, 0, 0},
501     {WINED3DSIO_LRP,  "lrp",  "LRP", 1, 4, vshader_lrp,  NULL,              shader_glsl_lrp, 0, 0},
502     {WINED3DSIO_FRC,  "frc",  "FRC", 1, 2, vshader_frc,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
503     {WINED3DSIO_POW,  "pow",  "POW", 1, 3, vshader_pow,  NULL, shader_glsl_map2gl, 0, 0},
504     {WINED3DSIO_CRS,  "crs",  "XPS", 1, 3, vshader_crs,  NULL, shader_glsl_cross, 0, 0},
505     /* TODO: sng can possibly be performed a  s
506         RCP tmp, vec
507         MUL out, tmp, vec*/
508     {WINED3DSIO_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     {WINED3DSIO_NRM,      "nrm",      NULL, 1, 2, vshader_nrm,    NULL, shader_glsl_map2gl, 0, 0},
520     {WINED3DSIO_SINCOS,   "sincos",   NULL, 1, 4, vshader_sincos2, NULL, shader_glsl_sincos, WINED3DVS_VERSION(2,0), WINED3DVS_VERSION(2,1)},
521     {WINED3DSIO_SINCOS,   "sincos",   NULL, 1, 2, vshader_sincos3, NULL, shader_glsl_sincos, WINED3DVS_VERSION(3,0), -1},
522
523     /* Matrix */
524     {WINED3DSIO_M4x4, "m4x4", "undefined", 1, 3, vshader_m4x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
525     {WINED3DSIO_M4x3, "m4x3", "undefined", 1, 3, vshader_m4x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
526     {WINED3DSIO_M3x4, "m3x4", "undefined", 1, 3, vshader_m3x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
527     {WINED3DSIO_M3x3, "m3x3", "undefined", 1, 3, vshader_m3x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
528     {WINED3DSIO_M3x2, "m3x2", "undefined", 1, 3, vshader_m3x2, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
529
530     /* Declare registers */
531     {WINED3DSIO_DCL,      "dcl",      NULL,                0, 2, vshader_dcl,     NULL, NULL, 0, 0},
532
533     /* Constant definitions */
534     {WINED3DSIO_DEF,      "def",      NULL,                1, 5, vshader_def,     NULL, NULL, 0, 0},
535     {WINED3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_defb,    NULL, NULL, 0, 0},
536     {WINED3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi,    NULL, NULL, 0, 0},
537
538     /* Flow control - requires GLSL or software shaders */
539     {WINED3DSIO_REP ,     "rep",      NULL, 0, 1, vshader_rep,     NULL, shader_glsl_rep,    WINED3DVS_VERSION(2,0), -1},
540     {WINED3DSIO_ENDREP,   "endrep",   NULL, 0, 0, vshader_endrep,  NULL, shader_glsl_end,    WINED3DVS_VERSION(2,0), -1},
541     {WINED3DSIO_IF,       "if",       NULL, 0, 1, vshader_if,      NULL, shader_glsl_if,     WINED3DVS_VERSION(2,0), -1},
542     {WINED3DSIO_IFC,      "ifc",      NULL, 0, 2, vshader_ifc,     NULL, shader_glsl_ifc,    WINED3DVS_VERSION(2,1), -1},
543     {WINED3DSIO_ELSE,     "else",     NULL, 0, 0, vshader_else,    NULL, shader_glsl_else,   WINED3DVS_VERSION(2,0), -1},
544     {WINED3DSIO_ENDIF,    "endif",    NULL, 0, 0, vshader_endif,   NULL, shader_glsl_end,    WINED3DVS_VERSION(2,0), -1},
545     {WINED3DSIO_BREAK,    "break",    NULL, 0, 0, vshader_break,   NULL, shader_glsl_break,  WINED3DVS_VERSION(2,1), -1},
546     {WINED3DSIO_BREAKC,   "breakc",   NULL, 0, 2, vshader_breakc,  NULL, shader_glsl_breakc, WINED3DVS_VERSION(2,1), -1},
547     {WINED3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp,  NULL, NULL, 0, 0},
548     {WINED3DSIO_CALL,     "call",     NULL, 0, 1, vshader_call,    NULL, shader_glsl_call,   WINED3DVS_VERSION(2,0), -1},
549     {WINED3DSIO_CALLNZ,   "callnz",   NULL, 0, 2, vshader_callnz,  NULL, shader_glsl_callnz, WINED3DVS_VERSION(2,0), -1},
550     {WINED3DSIO_LOOP,     "loop",     NULL, 0, 2, vshader_loop,    NULL, shader_glsl_loop,   WINED3DVS_VERSION(2,0), -1},
551     {WINED3DSIO_RET,      "ret",      NULL, 0, 0, vshader_ret,     NULL, NULL,               WINED3DVS_VERSION(2,0), -1},
552     {WINED3DSIO_ENDLOOP,  "endloop",  NULL, 0, 0, vshader_endloop, NULL, shader_glsl_end,    WINED3DVS_VERSION(2,0), -1},
553     {WINED3DSIO_LABEL,    "label",    NULL, 0, 1, vshader_label,   NULL, shader_glsl_label,  WINED3DVS_VERSION(2,0), -1},
554
555     {WINED3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL, 1, 3, vshader_setp,    NULL, NULL, 0, 0},
556     {WINED3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL, 1, 2, vshader_texldl,  NULL, NULL, 0, 0},
557     {0,               NULL,       NULL,   0, 0, NULL,            NULL, 0, 0}
558 };
559
560 static void vshader_set_limits(
561       IWineD3DVertexShaderImpl *This) {
562
563       This->baseShader.limits.texcoord = 0;
564       This->baseShader.limits.attributes = 16;
565       This->baseShader.limits.packed_input = 0;
566
567       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
568       This->baseShader.limits.constant_float = GL_LIMITS(vshader_constantsF);
569
570       switch (This->baseShader.hex_version) {
571           case WINED3DVS_VERSION(1,0):
572           case WINED3DVS_VERSION(1,1):
573                    This->baseShader.limits.temporary = 12;
574                    This->baseShader.limits.constant_bool = 0;
575                    This->baseShader.limits.constant_int = 0;
576                    This->baseShader.limits.address = 1;
577                    This->baseShader.limits.packed_output = 0;
578                    This->baseShader.limits.sampler = 0;
579                    This->baseShader.limits.label = 0;
580                    break;
581       
582           case WINED3DVS_VERSION(2,0):
583           case WINED3DVS_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                    This->baseShader.limits.label = 16;
591                    break;
592
593           case WINED3DVS_VERSION(3,0):
594                    This->baseShader.limits.temporary = 32;
595                    This->baseShader.limits.constant_bool = 32;
596                    This->baseShader.limits.constant_int = 32;
597                    This->baseShader.limits.address = 1;
598                    This->baseShader.limits.packed_output = 12;
599                    This->baseShader.limits.sampler = 4;
600                    This->baseShader.limits.label = 16; /* FIXME: 2048 */
601                    break;
602
603           default: This->baseShader.limits.temporary = 12;
604                    This->baseShader.limits.constant_bool = 16;
605                    This->baseShader.limits.constant_int = 16;
606                    This->baseShader.limits.address = 1;
607                    This->baseShader.limits.packed_output = 0;
608                    This->baseShader.limits.sampler = 0;
609                    This->baseShader.limits.label = 16;
610                    FIXME("Unrecognized vertex shader version %#x\n",
611                        This->baseShader.hex_version);
612       }
613 }
614
615 /* This is an internal function,
616  * used to create fake semantics for shaders
617  * that don't have them - d3d8 shaders where the declaration
618  * stores the register for each input
619  */
620 static void vshader_set_input(
621     IWineD3DVertexShaderImpl* This,
622     unsigned int regnum,
623     BYTE usage, BYTE usage_idx) {
624
625     /* Fake usage: set reserved bit, usage, usage_idx */
626     DWORD usage_token = (0x1 << 31) |
627         (usage << WINED3DSP_DCL_USAGE_SHIFT) | (usage_idx << WINED3DSP_DCL_USAGEINDEX_SHIFT);
628
629     /* Fake register; set reserved bit, regnum, type: input, wmask: all */
630     DWORD reg_token = (0x1 << 31) |
631         WINED3DSP_WRITEMASK_ALL | (WINED3DSPR_INPUT << WINED3DSP_REGTYPE_SHIFT) | regnum;
632
633     This->semantics_in[regnum].usage = usage_token;
634     This->semantics_in[regnum].reg = reg_token;
635 }
636
637 static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2) {
638     if (usage_idx1 != usage_idx2) return FALSE;
639     if (usage1 == usage2) return TRUE;
640     if (usage1 == WINED3DDECLUSAGE_POSITION && usage2 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
641     if (usage2 == WINED3DDECLUSAGE_POSITION && usage1 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
642
643     return FALSE;
644 }
645
646 BOOL vshader_get_input(
647     IWineD3DVertexShader* iface,
648     BYTE usage_req, BYTE usage_idx_req,
649     unsigned int* regnum) {
650
651     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
652     int i;
653
654     for (i = 0; i < MAX_ATTRIBS; i++) {
655         DWORD usage_token = This->semantics_in[i].usage;
656         DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
657         DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
658
659         if (usage_token && match_usage(usage, usage_idx, usage_req, usage_idx_req)) {
660             *regnum = i;
661             return TRUE;
662         }
663     }
664     return FALSE;
665 }
666
667 BOOL vshader_input_is_color(
668     IWineD3DVertexShader* iface,
669     unsigned int regnum) {
670
671     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
672     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
673     IWineD3DVertexDeclarationImpl *vertexDeclaration = (IWineD3DVertexDeclarationImpl *)deviceImpl->stateBlock->vertexDecl;
674
675     DWORD usage_token = This->semantics_in[regnum].usage;
676     DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
677     DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
678
679     if (vertexDeclaration) {
680         int i;
681         /* Find the declaration element that matches our register, then check
682          * if it has D3DCOLOR as it's type. This works for both d3d8 and d3d9. */
683         for (i = 0; i < vertexDeclaration->declarationWNumElements-1; ++i) {
684             WINED3DVERTEXELEMENT *element = vertexDeclaration->pDeclarationWine + i;
685             if (match_usage(element->Usage, element->UsageIndex, usage, usage_idx)) {
686                 return element->Type == WINED3DDECLTYPE_D3DCOLOR;
687             }
688         }
689     }
690
691     ERR("Either no vertexdeclaration present, or register not matched. This should never happen.\n");
692     return FALSE;
693 }
694
695 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
696     or GLSL and send it to the card */
697 static VOID IWineD3DVertexShaderImpl_GenerateShader(
698     IWineD3DVertexShader *iface,
699     shader_reg_maps* reg_maps,
700     CONST DWORD *pFunction) {
701
702     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
703     SHADER_BUFFER buffer;
704
705 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
706         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
707     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
708         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
709         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
710         This->fixupVertexBufferSize = PGMSIZE;
711         This->fixupVertexBuffer[0] = 0;
712     }
713     buffer.buffer = This->device->fixupVertexBuffer;
714 #else
715     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
716 #endif
717     buffer.bsize = 0;
718     buffer.lineNo = 0;
719     buffer.newline = TRUE;
720
721     if (This->baseShader.shader_mode == SHADER_GLSL) {
722
723         /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
724         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
725
726         /* Base Declarations */
727         shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
728
729         /* Base Shader Body */
730         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
731
732         /* Unpack 3.0 outputs */
733         if (This->baseShader.hex_version >= WINED3DVS_VERSION(3,0))
734             vshader_glsl_output_unpack(&buffer, This->semantics_out);
735
736         /* Clamp the fog from 0 to 1 if it's used */
737         if (reg_maps->fog) {
738             This->usesFog = 1;
739             shader_addline(&buffer, "gl_FogFragCoord = clamp(gl_FogFragCoord, 0.0, 1.0);\n");
740         }
741         
742         /* Write the final position.
743          *
744          * OpenGL coordinates specify the center of the pixel while d3d coords specify
745          * the corner. The offsets are stored in z and w in the 2nd row of the projection
746          * matrix to avoid wasting a free shader constant. Add them to the w and z coord
747          * of the 2nd row
748          */
749         shader_addline(&buffer, "gl_Position.x = gl_Position.x + posFixup[2];\n");
750         shader_addline(&buffer, "gl_Position.y = gl_Position.y + posFixup[3];\n");
751         /* Account for any inverted textures (render to texture case) by reversing the y coordinate
752          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
753          */
754         shader_addline(&buffer, "gl_Position.y = gl_Position.y * posFixup[1];\n");
755
756         shader_addline(&buffer, "}\n");
757
758         TRACE("Compiling shader object %u\n", shader_obj);
759         GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
760         GL_EXTCALL(glCompileShaderARB(shader_obj));
761         print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
762
763         /* Store the shader object */
764         This->baseShader.prgId = shader_obj;
765
766     } else if (This->baseShader.shader_mode == SHADER_ARB) {
767
768         /*  Create the hw ARB shader */
769         shader_addline(&buffer, "!!ARBvp1.0\n");
770
771         /* Mesa supports only 95 constants */
772         if (GL_VEND(MESA) || GL_VEND(WINE))
773             This->baseShader.limits.constant_float = 
774                 min(95, This->baseShader.limits.constant_float);
775
776         /* Base Declarations */
777         shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
778
779         /* We need a constant to fixup the final position */
780         shader_addline(&buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
781
782         if (reg_maps->fog) {
783             This->usesFog = 1;
784             shader_addline(&buffer, "TEMP TMP_FOG;\n");
785         }
786
787         /* Base Shader Body */
788         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
789
790         /* Make sure the fog value is positive - values above 1.0 are ignored */
791         if (reg_maps->fog)
792             shader_addline(&buffer, "MAX result.fogcoord, TMP_FOG, 0.0;\n");
793
794         /* Write the final position.
795          *
796          * OpenGL coordinates specify the center of the pixel while d3d coords specify
797          * the corner. The offsets are stored in the 2nd row of the projection matrix,
798          * the x offset in z and the y offset in w. Add them to the resulting position
799          */
800         shader_addline(&buffer, "ADD TMP_OUT.x, TMP_OUT.x, posFixup.z;\n");
801         shader_addline(&buffer, "ADD TMP_OUT.y, TMP_OUT.y, posFixup.w;\n");
802         /* Account for any inverted textures (render to texture case) by reversing the y coordinate
803          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
804          */
805         shader_addline(&buffer, "MUL TMP_OUT.y, TMP_OUT.y, posFixup.y;\n");
806
807         shader_addline(&buffer, "MOV result.position, TMP_OUT;\n");
808         
809         shader_addline(&buffer, "END\n"); 
810
811         /* TODO: change to resource.glObjectHandle or something like that */
812         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
813
814         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
815         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
816
817         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
818         /* Create the program and check for errors */
819         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
820             buffer.bsize, buffer.buffer));
821
822         if (glGetError() == GL_INVALID_OPERATION) {
823             GLint errPos;
824             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
825             FIXME("HW VertexShader Error at position %d: %s\n",
826                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
827             This->baseShader.prgId = -1;
828         }
829     }
830
831 #if 1 /* if were using the data buffer of device then we don't need to free it */
832   HeapFree(GetProcessHeap(), 0, buffer.buffer);
833 #endif
834 }
835
836 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
837   /**
838    * TODO: use the NV_vertex_program (or 1_1) extension
839    *  and specifics vendors (ARB_vertex_program??) variants for it
840    */
841   return TRUE;
842 }
843
844 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
845     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
846     DWORD opcode_token;   
847  
848     /** Vertex Shader Temporary Registers */
849     WINED3DSHADERVECTOR R[12];
850       /*D3DSHADERSCALAR A0;*/
851     WINED3DSHADERVECTOR A[1];
852     /** temporary Vector for modifier management */
853     WINED3DSHADERVECTOR d;
854     WINED3DSHADERVECTOR s[3];
855     /** parser datas */
856     const DWORD* pToken = This->baseShader.function;
857     const SHADER_OPCODE* curOpcode = NULL;
858     /** functions parameters */
859     WINED3DSHADERVECTOR* p[6];
860     WINED3DSHADERVECTOR* p_send[6];
861     DWORD i;
862
863     /** init temporary register */
864     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
865
866     /* vshader_program_parse(vshader); */
867 #if 0 /* Must not be 1 in cvs */
868     TRACE("Input:\n");
869     TRACE_VSVECTOR(This->data->C[0]);
870     TRACE_VSVECTOR(This->data->C[1]);
871     TRACE_VSVECTOR(This->data->C[2]);
872     TRACE_VSVECTOR(This->data->C[3]);
873     TRACE_VSVECTOR(This->data->C[4]);
874     TRACE_VSVECTOR(This->data->C[5]);
875     TRACE_VSVECTOR(This->data->C[6]);
876     TRACE_VSVECTOR(This->data->C[7]);
877     TRACE_VSVECTOR(This->data->C[8]);
878     TRACE_VSVECTOR(This->data->C[64]);
879     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
880     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
881     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
882     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
883     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
884     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
885     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
886     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
887     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
888 #endif
889
890     TRACE_VSVECTOR(vshader->data->C[64]);
891     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
892
893     /* the first dword is the version tag */
894     /* TODO: parse it */
895
896     if (shader_is_vshader_version(*pToken)) { /** version */
897         ++pToken;
898     }
899     while (WINED3DVS_END() != *pToken) {
900         if (shader_is_comment(*pToken)) { /** comment */
901             DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
902             ++pToken;
903             pToken += comment_len;
904             continue ;
905         }
906
907         opcode_token = *pToken++;
908         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
909
910         if (NULL == curOpcode) {
911             FIXME("Unrecognized opcode: token=%08x\n", opcode_token);
912             pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
913             /* return FALSE; */
914
915         } else {
916             if (curOpcode->num_params > 0) {
917                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
918                 for (i = 0; i < curOpcode->num_params; ++i) {
919                     DWORD reg = pToken[i] & WINED3DSP_REGNUM_MASK;
920                     DWORD regtype = shader_get_regtype(pToken[i]);
921     
922                     switch (regtype) {
923                     case WINED3DSPR_TEMP:
924                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
925                         p[i] = &R[reg];
926                         break;
927                     case WINED3DSPR_INPUT:
928                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
929                         p[i] = &input->V[reg];
930                         break;
931                     case WINED3DSPR_CONST:
932                         if (pToken[i] & WINED3DSHADER_ADDRMODE_RELATIVE) {
933                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
934                         } else {
935                             p[i] = &This->data->C[reg];
936                         }
937                         break;
938                     case WINED3DSPR_ADDR: /* case WINED3DSPR_TEXTURE: */
939                         if (0 != reg) {
940                             ERR("cannot handle address registers != a0, forcing use of a0\n");
941                             reg = 0;
942                         }
943                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
944                         p[i] = &A[reg];
945                         break;
946                     case WINED3DSPR_RASTOUT:
947                         switch (reg) {
948                         case WINED3DSRO_POSITION:
949                             p[i] = &output->oPos;
950                             break;
951                         case WINED3DSRO_FOG:
952                             p[i] = &output->oFog;
953                             break;
954                         case WINED3DSRO_POINT_SIZE:
955                             p[i] = &output->oPts;
956                             break;
957                         }
958                         break;
959                     case WINED3DSPR_ATTROUT:
960                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
961                         p[i] = &output->oD[reg];
962                         break;
963                     case WINED3DSPR_TEXCRDOUT:
964                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
965                         p[i] = &output->oT[reg];
966                         break;
967                     /* TODO Decls and defs */
968 #if 0
969                     case WINED3DSPR_DCL:
970                     case WINED3DSPR_DEF:
971 #endif
972                     default:
973                         break;
974                     }
975
976                     if (i > 0) { /* input reg */
977                         DWORD swizzle = (pToken[i] & WINED3DVS_SWIZZLE_MASK) >> WINED3DVS_SWIZZLE_SHIFT;
978                         UINT isNegative = ((pToken[i] & WINED3DSP_SRCMOD_MASK) == WINED3DSPSM_NEG);
979
980                         if (!isNegative && (WINED3DVS_NOSWIZZLE >> WINED3DVS_SWIZZLE_SHIFT) == swizzle) {
981                             /* TRACE("p[%d] not swizzled\n", i); */
982                             p_send[i] = p[i];
983                         } else {
984                             DWORD swizzle_x = swizzle & 0x03;
985                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
986                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
987                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
988                             /* TRACE("p[%d] swizzled\n", i); */
989                             float* tt = (float*) p[i];
990                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
991                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
992                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
993                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
994                             p_send[i] = &s[i];
995                         }
996                     } else { /* output reg */
997                         if ((pToken[i] & WINED3DSP_WRITEMASK_ALL) == WINED3DSP_WRITEMASK_ALL) {
998                             p_send[i] = p[i];
999                         } else {
1000                             p_send[i] = &d; /* to be post-processed for modifiers management */
1001                         }
1002                     }
1003                 }
1004             }
1005
1006             switch (curOpcode->num_params) {
1007             case 0:
1008                 curOpcode->soft_fct();
1009                 break;
1010             case 1:
1011                 curOpcode->soft_fct(p_send[0]);
1012             break;
1013             case 2:
1014                 curOpcode->soft_fct(p_send[0], p_send[1]);
1015                 break;
1016             case 3:
1017                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1018                 break;
1019             case 4:
1020                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1021                 break;
1022             case 5:
1023                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1024                 break;
1025             case 6:
1026                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1027                 break;
1028             default:
1029                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1030             }
1031
1032             /* check if output reg modifier post-process */
1033             if (curOpcode->num_params > 0 &&
1034                 (pToken[0] & WINED3DSP_WRITEMASK_ALL) != WINED3DSP_WRITEMASK_ALL) {
1035
1036                 if (pToken[0] & WINED3DSP_WRITEMASK_0) p[0]->x = d.x; 
1037                 if (pToken[0] & WINED3DSP_WRITEMASK_1) p[0]->y = d.y; 
1038                 if (pToken[0] & WINED3DSP_WRITEMASK_2) p[0]->z = d.z; 
1039                 if (pToken[0] & WINED3DSP_WRITEMASK_3) p[0]->w = d.w; 
1040             }
1041 #if 0
1042             TRACE_VSVECTOR(output->oPos);
1043             TRACE_VSVECTOR(output->oD[0]);
1044             TRACE_VSVECTOR(output->oD[1]);
1045             TRACE_VSVECTOR(output->oT[0]);
1046             TRACE_VSVECTOR(output->oT[1]);
1047             TRACE_VSVECTOR(R[0]);
1048             TRACE_VSVECTOR(R[1]);
1049             TRACE_VSVECTOR(R[2]);
1050             TRACE_VSVECTOR(R[3]);
1051             TRACE_VSVECTOR(R[4]);
1052             TRACE_VSVECTOR(R[5]);
1053 #endif
1054
1055             /* to next opcode token */
1056             pToken += curOpcode->num_params;
1057         }
1058 #if 0
1059         TRACE("End of current instruction:\n");
1060         TRACE_VSVECTOR(output->oPos);
1061         TRACE_VSVECTOR(output->oD[0]);
1062         TRACE_VSVECTOR(output->oD[1]);
1063         TRACE_VSVECTOR(output->oT[0]);
1064         TRACE_VSVECTOR(output->oT[1]);
1065         TRACE_VSVECTOR(R[0]);
1066         TRACE_VSVECTOR(R[1]);
1067         TRACE_VSVECTOR(R[2]);
1068         TRACE_VSVECTOR(R[3]);
1069         TRACE_VSVECTOR(R[4]);
1070         TRACE_VSVECTOR(R[5]);
1071 #endif
1072     }
1073 #if 0 /* Must not be 1 in cvs */
1074     TRACE("Output:\n");
1075     TRACE_VSVECTOR(output->oPos);
1076     TRACE_VSVECTOR(output->oD[0]);
1077     TRACE_VSVECTOR(output->oD[1]);
1078     TRACE_VSVECTOR(output->oT[0]);
1079     TRACE_VSVECTOR(output->oT[1]);
1080 #endif
1081     return WINED3D_OK;
1082 }
1083
1084 /* *******************************************
1085    IWineD3DVertexShader IUnknown parts follow
1086    ******************************************* */
1087 static HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1088 {
1089     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1090     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1091     if (IsEqualGUID(riid, &IID_IUnknown) 
1092         || IsEqualGUID(riid, &IID_IWineD3DBase)
1093         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1094         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1095         IUnknown_AddRef(iface);
1096         *ppobj = This;
1097         return S_OK;
1098     }
1099     *ppobj = NULL;
1100     return E_NOINTERFACE;
1101 }
1102
1103 static ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1104     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1105     TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
1106     return InterlockedIncrement(&This->ref);
1107 }
1108
1109 static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1110     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1111     ULONG ref;
1112     TRACE("(%p) : Releasing from %d\n", This, This->ref);
1113     ref = InterlockedDecrement(&This->ref);
1114     if (ref == 0) {
1115         if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
1116             /* If this shader is still attached to a program, GL will perform a lazy delete */
1117             TRACE("Deleting shader object %u\n", This->baseShader.prgId);
1118             GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
1119             checkGLcall("glDeleteObjectARB");
1120         }
1121         shader_delete_constant_list(&This->baseShader.constantsF);
1122         shader_delete_constant_list(&This->baseShader.constantsB);
1123         shader_delete_constant_list(&This->baseShader.constantsI);
1124         HeapFree(GetProcessHeap(), 0, This);
1125
1126     }
1127     return ref;
1128 }
1129
1130 /* *******************************************
1131    IWineD3DVertexShader IWineD3DVertexShader parts follow
1132    ******************************************* */
1133
1134 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1135     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1136     
1137     *parent = This->parent;
1138     IUnknown_AddRef(*parent);
1139     TRACE("(%p) : returning %p\n", This, *parent);
1140     return WINED3D_OK;
1141 }
1142
1143 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1144     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1145     IWineD3DDevice_AddRef(This->baseShader.device);
1146     *pDevice = This->baseShader.device;
1147     TRACE("(%p) returning %p\n", This, *pDevice);
1148     return WINED3D_OK;
1149 }
1150
1151 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1152     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1153     TRACE("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1154
1155     if (NULL == pData) {
1156         *pSizeOfData = This->baseShader.functionLength;
1157         return WINED3D_OK;
1158     }
1159     if (*pSizeOfData < This->baseShader.functionLength) {
1160         *pSizeOfData = This->baseShader.functionLength;
1161         return WINED3DERR_MOREDATA;
1162     }
1163     if (NULL == This->baseShader.function) { /* no function defined */
1164         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1165         (*(DWORD **) pData) = NULL;
1166     } else {
1167         if(This->baseShader.functionLength == 0){
1168
1169         }
1170         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1171         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1172     }
1173     return WINED3D_OK;
1174 }
1175
1176 /* Note that for vertex shaders CompileShader isn't called until the
1177  * shader is first used. The reason for this is that we need the vertex
1178  * declaration the shader will be used with in order to determine if
1179  * the data in a register is of type D3DCOLOR, and needs swizzling. */
1180 static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1181
1182     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1183     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
1184     HRESULT hr;
1185     shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
1186
1187     TRACE("(%p) : pFunction %p\n", iface, pFunction);
1188
1189     /* First pass: trace shader */
1190     shader_trace_init((IWineD3DBaseShader*) This, pFunction);
1191     vshader_set_limits(This);
1192
1193     /* Initialize immediate constant lists */
1194     list_init(&This->baseShader.constantsF);
1195     list_init(&This->baseShader.constantsB);
1196     list_init(&This->baseShader.constantsI);
1197
1198     /* Second pass: figure out registers used, semantics, etc.. */
1199     memset(reg_maps, 0, sizeof(shader_reg_maps));
1200     hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
1201        This->semantics_in, This->semantics_out, pFunction, deviceImpl->stateBlock);
1202     if (hr != WINED3D_OK) return hr;
1203
1204     This->baseShader.shader_mode = deviceImpl->vs_selected_mode;
1205
1206     /* copy the function ... because it will certainly be released by application */
1207     if (NULL != pFunction) {
1208         void *function;
1209
1210         function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1211         if (!function) return E_OUTOFMEMORY;
1212         memcpy(function, pFunction, This->baseShader.functionLength);
1213         This->baseShader.function = function;
1214     } else {
1215         This->baseShader.function = NULL;
1216     }
1217
1218     return WINED3D_OK;
1219 }
1220
1221 /* Preload semantics for d3d8 shaders */
1222 static void WINAPI IWineD3DVertexShaderImpl_FakeSemantics(IWineD3DVertexShader *iface, IWineD3DVertexDeclaration *vertex_declaration) {
1223     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1224     IWineD3DVertexDeclarationImpl* vdecl = (IWineD3DVertexDeclarationImpl*)vertex_declaration;
1225
1226     int i;
1227     for (i = 0; i < vdecl->declarationWNumElements - 1; ++i) {
1228         WINED3DVERTEXELEMENT* element = vdecl->pDeclarationWine + i;
1229         vshader_set_input(This, element->Reg, element->Usage, element->UsageIndex);
1230     }
1231 }
1232
1233 /* Set local constants for d3d8 shaders */
1234 static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertexShader *iface,
1235         UINT start_idx, const float *src_data, UINT count) {
1236     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1237     UINT i, end_idx;
1238
1239     TRACE("(%p) : start_idx %u, src_data %p, count %u\n", This, start_idx, src_data, count);
1240
1241     end_idx = start_idx + count;
1242     if (end_idx > GL_LIMITS(vshader_constantsF)) {
1243         WARN("end_idx %u > float constants limit %u\n", end_idx, GL_LIMITS(vshader_constantsF));
1244         end_idx = GL_LIMITS(vshader_constantsF);
1245     }
1246
1247     for (i = start_idx; i < end_idx; ++i) {
1248         local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
1249         if (!lconst) return E_OUTOFMEMORY;
1250
1251         lconst->idx = i;
1252         CopyMemory(lconst->value, src_data + i * 4, 4 * sizeof(float));
1253         list_add_head(&This->baseShader.constantsF, &lconst->entry);
1254     }
1255
1256     return WINED3D_OK;
1257 }
1258
1259 static HRESULT WINAPI IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
1260     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1261     CONST DWORD *function = This->baseShader.function;
1262
1263     TRACE("(%p) : function %p\n", iface, function);
1264
1265     /* We're already compiled. */
1266     if (This->baseShader.is_compiled) return WINED3D_OK;
1267
1268     /* We don't need to compile */
1269     if (!function || This->baseShader.shader_mode == SHADER_SW) {
1270         This->baseShader.is_compiled = TRUE;
1271         return WINED3D_OK;
1272     }
1273
1274     /* Generate the HW shader */
1275     TRACE("(%p) : Generating hardware program\n", This);
1276     IWineD3DVertexShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
1277
1278     This->baseShader.is_compiled = TRUE;
1279
1280     return WINED3D_OK;
1281 }
1282
1283 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1284 {
1285     /*** IUnknown methods ***/
1286     IWineD3DVertexShaderImpl_QueryInterface,
1287     IWineD3DVertexShaderImpl_AddRef,
1288     IWineD3DVertexShaderImpl_Release,
1289     /*** IWineD3DBase methods ***/
1290     IWineD3DVertexShaderImpl_GetParent,
1291     /*** IWineD3DBaseShader methods ***/
1292     IWineD3DVertexShaderImpl_SetFunction,
1293     IWineD3DVertexShaderImpl_CompileShader,
1294     /*** IWineD3DVertexShader methods ***/
1295     IWineD3DVertexShaderImpl_GetDevice,
1296     IWineD3DVertexShaderImpl_GetFunction,
1297     IWineD3DVertexShaderImpl_FakeSemantics,
1298     IWIneD3DVertexShaderImpl_SetLocalConstantsF
1299 };