wined3d: More shader fixes / new instructions.
[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->wineD3DDevice)->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     {D3DSIO_NOP,  "nop",  "NOP", 0, 0, vshader_nop,  vshader_hw_map2gl, NULL, 0, 0},
479     {D3DSIO_MOV,  "mov",  "MOV", 1, 2, vshader_mov,  vshader_hw_map2gl, shader_glsl_mov, 0, 0},
480     {D3DSIO_ADD,  "add",  "ADD", 1, 3, vshader_add,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
481     {D3DSIO_SUB,  "sub",  "SUB", 1, 3, vshader_sub,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
482     {D3DSIO_MAD,  "mad",  "MAD", 1, 4, vshader_mad,  vshader_hw_map2gl, shader_glsl_mad, 0, 0},
483     {D3DSIO_MUL,  "mul",  "MUL", 1, 3, vshader_mul,  vshader_hw_map2gl, shader_glsl_arith, 0, 0},
484     {D3DSIO_RCP,  "rcp",  "RCP", 1, 2, vshader_rcp,  vshader_hw_map2gl, shader_glsl_rcp, 0, 0},
485     {D3DSIO_RSQ,  "rsq",  "RSQ", 1, 2, vshader_rsq,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
486     {D3DSIO_DP3,  "dp3",  "DP3", 1, 3, vshader_dp3,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
487     {D3DSIO_DP4,  "dp4",  "DP4", 1, 3, vshader_dp4,  vshader_hw_map2gl, shader_glsl_dot, 0, 0},
488     {D3DSIO_MIN,  "min",  "MIN", 1, 3, vshader_min,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
489     {D3DSIO_MAX,  "max",  "MAX", 1, 3, vshader_max,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
490     {D3DSIO_SLT,  "slt",  "SLT", 1, 3, vshader_slt,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
491     {D3DSIO_SGE,  "sge",  "SGE", 1, 3, vshader_sge,  vshader_hw_map2gl, shader_glsl_compare, 0, 0},
492     {D3DSIO_ABS,  "abs",  "ABS", 1, 2, vshader_abs,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
493     {D3DSIO_EXP,  "exp",  "EX2", 1, 2, vshader_exp,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
494     {D3DSIO_LOG,  "log",  "LG2", 1, 2, vshader_log,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
495     {D3DSIO_EXPP, "expp", "EXP", 1, 2, vshader_expp, vshader_hw_map2gl, shader_glsl_expp, 0, 0},
496     {D3DSIO_LOGP, "logp", "LOG", 1, 2, vshader_logp, vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
497     {D3DSIO_LIT,  "lit",  "LIT", 1, 2, vshader_lit,  vshader_hw_map2gl, shader_glsl_lit, 0, 0},
498     {D3DSIO_DST,  "dst",  "DST", 1, 3, vshader_dst,  vshader_hw_map2gl, shader_glsl_dst, 0, 0},
499     {D3DSIO_LRP,  "lrp",  "LRP", 1, 4, vshader_lrp,  NULL,              shader_glsl_lrp, 0, 0},
500     {D3DSIO_FRC,  "frc",  "FRC", 1, 2, vshader_frc,  vshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
501     {D3DSIO_POW,  "pow",  "POW", 1, 3, vshader_pow,  NULL, shader_glsl_map2gl, 0, 0},
502     {D3DSIO_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     {D3DSIO_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     {D3DSIO_NRM,      "nrm",      NULL, 1, 2, vshader_nrm,    NULL, shader_glsl_map2gl, 0, 0},
518     {D3DSIO_SINCOS,   "sincos",   NULL, 1, 4, vshader_sincos2, NULL, shader_glsl_sincos, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
519     {D3DSIO_SINCOS,   "sincos",   NULL, 1, 2, vshader_sincos3, NULL, shader_glsl_sincos, D3DVS_VERSION(3,0), -1},
520
521     /* Matrix */
522     {D3DSIO_M4x4, "m4x4", "undefined", 1, 3, vshader_m4x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
523     {D3DSIO_M4x3, "m4x3", "undefined", 1, 3, vshader_m4x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
524     {D3DSIO_M3x4, "m3x4", "undefined", 1, 3, vshader_m3x4, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
525     {D3DSIO_M3x3, "m3x3", "undefined", 1, 3, vshader_m3x3, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
526     {D3DSIO_M3x2, "m3x2", "undefined", 1, 3, vshader_m3x2, vshader_hw_mnxn, shader_glsl_mnxn, 0, 0},
527
528     /* Declare registers */
529     {D3DSIO_DCL,      "dcl",      NULL,                0, 2, vshader_dcl,     NULL, NULL, 0, 0},
530
531     /* Constant definitions */
532     {D3DSIO_DEF,      "def",      NULL,                1, 5, vshader_def,     NULL, NULL, 0, 0},
533     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_defb,    NULL, NULL, 0, 0},
534     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi,    NULL, NULL, 0, 0},
535
536     /* Flow control - requires GLSL or software shaders */
537     {D3DSIO_REP ,     "rep",      NULL, 0, 1, vshader_rep,     NULL, shader_glsl_rep,    D3DVS_VERSION(2,0), -1},
538     {D3DSIO_ENDREP,   "endrep",   NULL, 0, 0, vshader_endrep,  NULL, shader_glsl_end,    D3DVS_VERSION(2,0), -1},
539     {D3DSIO_IF,       "if",       NULL, 0, 1, vshader_if,      NULL, shader_glsl_if,     D3DVS_VERSION(2,0), -1},
540     {D3DSIO_IFC,      "ifc",      NULL, 0, 2, vshader_ifc,     NULL, shader_glsl_ifc,    D3DVS_VERSION(2,1), -1},
541     {D3DSIO_ELSE,     "else",     NULL, 0, 0, vshader_else,    NULL, shader_glsl_else,   D3DVS_VERSION(2,0), -1},
542     {D3DSIO_ENDIF,    "endif",    NULL, 0, 0, vshader_endif,   NULL, shader_glsl_end,    D3DVS_VERSION(2,0), -1},
543     {D3DSIO_BREAK,    "break",    NULL, 0, 0, vshader_break,   NULL, shader_glsl_break,  D3DVS_VERSION(2,1), -1},
544     {D3DSIO_BREAKC,   "breakc",   NULL, 0, 2, vshader_breakc,  NULL, shader_glsl_breakc, D3DVS_VERSION(2,1), -1},
545     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp,  NULL, NULL, 0, 0},
546     {D3DSIO_CALL,     "call",     NULL, 0, 1, vshader_call,    NULL, shader_glsl_call,   D3DVS_VERSION(2,0), -1},
547     {D3DSIO_CALLNZ,   "callnz",   NULL, 0, 2, vshader_callnz,  NULL, shader_glsl_callnz, D3DVS_VERSION(2,0), -1},
548     {D3DSIO_LOOP,     "loop",     NULL, 0, 2, vshader_loop,    NULL, shader_glsl_loop,   D3DVS_VERSION(2,0), -1},
549     {D3DSIO_RET,      "ret",      NULL, 0, 0, vshader_ret,     NULL, NULL,               D3DVS_VERSION(2,0), -1},
550     {D3DSIO_ENDLOOP,  "endloop",  NULL, 0, 0, vshader_endloop, NULL, shader_glsl_end,    D3DVS_VERSION(2,0), -1},
551     {D3DSIO_LABEL,    "label",    NULL, 0, 1, vshader_label,   NULL, shader_glsl_label,  D3DVS_VERSION(2,0), -1},
552
553     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova,    NULL, shader_glsl_mov, 0, 0},
554     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL, 1, 3, vshader_setp,    NULL, NULL, 0, 0},
555     {D3DSIO_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 %#lx\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     DWORD usage_token = This->semantics_in[regnum].usage;
663     DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
664
665     /* FIXME: D3D8 shader: the semantics token is not the way to 
666      * determine color info, since it is just a fake map to shader inputs */
667     if (This->vertexDeclaration != NULL)
668         return FALSE; 
669     else
670         return usage == D3DDECLUSAGE_COLOR;
671 }
672
673 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
674     or GLSL and send it to the card */
675 static VOID IWineD3DVertexShaderImpl_GenerateShader(
676     IWineD3DVertexShader *iface,
677     shader_reg_maps* reg_maps,
678     CONST DWORD *pFunction) {
679
680     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
681     SHADER_BUFFER buffer;
682
683 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
684         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
685     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
686         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
687         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
688         This->fixupVertexBufferSize = PGMSIZE;
689         This->fixupVertexBuffer[0] = 0;
690     }
691     buffer.buffer = This->device->fixupVertexBuffer;
692 #else
693     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
694 #endif
695     buffer.bsize = 0;
696     buffer.lineNo = 0;
697
698     if (This->baseShader.shader_mode == SHADER_GLSL) {
699
700         /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
701         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
702
703         /* Base Declarations */
704         shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
705
706         /* Base Shader Body */
707         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
708
709         /* Unpack 3.0 outputs */
710         if (This->baseShader.hex_version >= D3DVS_VERSION(3,0))
711             vshader_glsl_output_unpack(&buffer, This->semantics_out);
712
713         /* Clamp the fog from 0 to 1 if it's used */
714         if (reg_maps->fog) {
715             This->usesFog = 1;
716             shader_addline(&buffer, "gl_FogFragCoord = clamp(gl_FogFragCoord, 0.0, 1.0);\n");
717         }
718         
719         /* Write the final position.
720          * Account for any inverted textures (render to texture case) by reversing the y coordinate
721          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices) */
722         shader_addline(&buffer, "gl_Position.y = gl_Position.y * gl_ProjectionMatrix[1][1];\n");
723
724         shader_addline(&buffer, "}\n\0");
725
726         TRACE("Compiling shader object %u\n", shader_obj);
727         GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
728         GL_EXTCALL(glCompileShaderARB(shader_obj));
729         print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
730
731         /* Store the shader object */
732         This->baseShader.prgId = shader_obj;
733
734     } else if (This->baseShader.shader_mode == SHADER_ARB) {
735
736         /*  Create the hw ARB shader */
737         shader_addline(&buffer, "!!ARBvp1.0\n");
738
739         /* Mesa supports only 95 constants */
740         if (GL_VEND(MESA) || GL_VEND(WINE))
741             This->baseShader.limits.constant_float = 
742                 min(95, This->baseShader.limits.constant_float);
743
744         /* Base Declarations */
745         shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
746         
747         /* We need the projection matrix to correctly render upside-down objects (render to texture) */
748         shader_addline(&buffer, "PARAM PROJECTION = state.matrix.projection.row[1];\n");
749
750         if (reg_maps->fog) {
751             This->usesFog = 1;
752             shader_addline(&buffer, "TEMP TMP_FOG;\n");
753         }
754
755         /* Base Shader Body */
756         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
757
758         /* Make sure the fog value is positive - values above 1.0 are ignored */
759         if (reg_maps->fog)
760             shader_addline(&buffer, "MAX result.fogcoord, TMP_FOG, 0.0;\n");
761
762         /* Write the final position.
763          * Account for any inverted textures (render to texture case) by reversing the y coordinate
764          *  (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices) */
765         shader_addline(&buffer, "MOV result.position, TMP_OUT;\n");
766         shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, PROJECTION.y;\n");
767         
768         shader_addline(&buffer, "END\n\0"); 
769
770         /* TODO: change to resource.glObjectHandle or something like that */
771         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
772
773         TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
774         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
775
776         TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
777         /* Create the program and check for errors */
778         GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
779             buffer.bsize, buffer.buffer));
780
781         if (glGetError() == GL_INVALID_OPERATION) {
782             GLint errPos;
783             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
784             FIXME("HW VertexShader Error at position %d: %s\n",
785                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
786             This->baseShader.prgId = -1;
787         }
788     }
789
790 #if 1 /* if were using the data buffer of device then we don't need to free it */
791   HeapFree(GetProcessHeap(), 0, buffer.buffer);
792 #endif
793 }
794
795 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
796   /**
797    * TODO: use the NV_vertex_program (or 1_1) extension
798    *  and specifics vendors (ARB_vertex_program??) variants for it
799    */
800   return TRUE;
801 }
802
803 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
804     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
805     DWORD opcode_token;   
806  
807     /** Vertex Shader Temporary Registers */
808     WINED3DSHADERVECTOR R[12];
809       /*D3DSHADERSCALAR A0;*/
810     WINED3DSHADERVECTOR A[1];
811     /** temporary Vector for modifier management */
812     WINED3DSHADERVECTOR d;
813     WINED3DSHADERVECTOR s[3];
814     /** parser datas */
815     const DWORD* pToken = This->baseShader.function;
816     const SHADER_OPCODE* curOpcode = NULL;
817     /** functions parameters */
818     WINED3DSHADERVECTOR* p[6];
819     WINED3DSHADERVECTOR* p_send[6];
820     DWORD i;
821
822     /** init temporary register */
823     memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
824
825     /* vshader_program_parse(vshader); */
826 #if 0 /* Must not be 1 in cvs */
827     TRACE("Input:\n");
828     TRACE_VSVECTOR(This->data->C[0]);
829     TRACE_VSVECTOR(This->data->C[1]);
830     TRACE_VSVECTOR(This->data->C[2]);
831     TRACE_VSVECTOR(This->data->C[3]);
832     TRACE_VSVECTOR(This->data->C[4]);
833     TRACE_VSVECTOR(This->data->C[5]);
834     TRACE_VSVECTOR(This->data->C[6]);
835     TRACE_VSVECTOR(This->data->C[7]);
836     TRACE_VSVECTOR(This->data->C[8]);
837     TRACE_VSVECTOR(This->data->C[64]);
838     TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
839     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
840     TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
841     TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
842     TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
843     TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
844     TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
845     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
846     TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
847 #endif
848
849     TRACE_VSVECTOR(vshader->data->C[64]);
850     /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
851
852     /* the first dword is the version tag */
853     /* TODO: parse it */
854
855     if (shader_is_vshader_version(*pToken)) { /** version */
856         ++pToken;
857     }
858     while (D3DVS_END() != *pToken) {
859         if (shader_is_comment(*pToken)) { /** comment */
860             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
861             ++pToken;
862             pToken += comment_len;
863             continue ;
864         }
865
866         opcode_token = *pToken++;
867         curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
868
869         if (NULL == curOpcode) {
870             FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
871             pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
872             /* return FALSE; */
873
874         } else {
875             if (curOpcode->num_params > 0) {
876                 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
877                 for (i = 0; i < curOpcode->num_params; ++i) {
878                     DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
879                     DWORD regtype = shader_get_regtype(pToken[i]);
880     
881                     switch (regtype) {
882                     case D3DSPR_TEMP:
883                         /* TRACE("p[%d]=R[%d]\n", i, reg); */
884                         p[i] = &R[reg];
885                         break;
886                     case D3DSPR_INPUT:
887                         /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
888                         p[i] = &input->V[reg];
889                         break;
890                     case D3DSPR_CONST:
891                         if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
892                             p[i] = &This->data->C[(DWORD) A[0].x + reg];
893                         } else {
894                             p[i] = &This->data->C[reg];
895                         }
896                         break;
897                     case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
898                         if (0 != reg) {
899                             ERR("cannot handle address registers != a0, forcing use of a0\n");
900                             reg = 0;
901                         }
902                         /* TRACE("p[%d]=A[%d]\n", i, reg); */
903                         p[i] = &A[reg];
904                         break;
905                     case D3DSPR_RASTOUT:
906                         switch (reg) {
907                         case D3DSRO_POSITION:
908                             p[i] = &output->oPos;
909                             break;
910                         case D3DSRO_FOG:
911                             p[i] = &output->oFog;
912                             break;
913                         case D3DSRO_POINT_SIZE:
914                             p[i] = &output->oPts;
915                             break;
916                         }
917                         break;
918                     case D3DSPR_ATTROUT:
919                         /* TRACE("p[%d]=oD[%d]\n", i, reg); */
920                         p[i] = &output->oD[reg];
921                         break;
922                     case D3DSPR_TEXCRDOUT:
923                         /* TRACE("p[%d]=oT[%d]\n", i, reg); */
924                         p[i] = &output->oT[reg];
925                         break;
926                     /* TODO Decls and defs */
927 #if 0
928                     case D3DSPR_DCL:
929                     case D3DSPR_DEF:
930 #endif
931                     default:
932                         break;
933                     }
934
935                     if (i > 0) { /* input reg */
936                         DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
937                         UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
938
939                         if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
940                             /* TRACE("p[%d] not swizzled\n", i); */
941                             p_send[i] = p[i];
942                         } else {
943                             DWORD swizzle_x = swizzle & 0x03;
944                             DWORD swizzle_y = (swizzle >> 2) & 0x03;
945                             DWORD swizzle_z = (swizzle >> 4) & 0x03;
946                             DWORD swizzle_w = (swizzle >> 6) & 0x03;
947                             /* TRACE("p[%d] swizzled\n", i); */
948                             float* tt = (float*) p[i];
949                             s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
950                             s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
951                             s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
952                             s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
953                             p_send[i] = &s[i];
954                         }
955                     } else { /* output reg */
956                         if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
957                             p_send[i] = p[i];
958                         } else {
959                             p_send[i] = &d; /* to be post-processed for modifiers management */
960                         }
961                     }
962                 }
963             }
964
965             switch (curOpcode->num_params) {
966             case 0:
967                 curOpcode->soft_fct();
968                 break;
969             case 1:
970                 curOpcode->soft_fct(p_send[0]);
971             break;
972             case 2:
973                 curOpcode->soft_fct(p_send[0], p_send[1]);
974                 break;
975             case 3:
976                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
977                 break;
978             case 4:
979                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
980                 break;
981             case 5:
982                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
983                 break;
984             case 6:
985                 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
986                 break;
987             default:
988                 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
989             }
990
991             /* check if output reg modifier post-process */
992             if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
993                 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
994                 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
995                 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
996                 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
997             }
998 #if 0
999             TRACE_VSVECTOR(output->oPos);
1000             TRACE_VSVECTOR(output->oD[0]);
1001             TRACE_VSVECTOR(output->oD[1]);
1002             TRACE_VSVECTOR(output->oT[0]);
1003             TRACE_VSVECTOR(output->oT[1]);
1004             TRACE_VSVECTOR(R[0]);
1005             TRACE_VSVECTOR(R[1]);
1006             TRACE_VSVECTOR(R[2]);
1007             TRACE_VSVECTOR(R[3]);
1008             TRACE_VSVECTOR(R[4]);
1009             TRACE_VSVECTOR(R[5]);
1010 #endif
1011
1012             /* to next opcode token */
1013             pToken += curOpcode->num_params;
1014         }
1015 #if 0
1016         TRACE("End of current instruction:\n");
1017         TRACE_VSVECTOR(output->oPos);
1018         TRACE_VSVECTOR(output->oD[0]);
1019         TRACE_VSVECTOR(output->oD[1]);
1020         TRACE_VSVECTOR(output->oT[0]);
1021         TRACE_VSVECTOR(output->oT[1]);
1022         TRACE_VSVECTOR(R[0]);
1023         TRACE_VSVECTOR(R[1]);
1024         TRACE_VSVECTOR(R[2]);
1025         TRACE_VSVECTOR(R[3]);
1026         TRACE_VSVECTOR(R[4]);
1027         TRACE_VSVECTOR(R[5]);
1028 #endif
1029     }
1030 #if 0 /* Must not be 1 in cvs */
1031     TRACE("Output:\n");
1032     TRACE_VSVECTOR(output->oPos);
1033     TRACE_VSVECTOR(output->oD[0]);
1034     TRACE_VSVECTOR(output->oD[1]);
1035     TRACE_VSVECTOR(output->oT[0]);
1036     TRACE_VSVECTOR(output->oT[1]);
1037 #endif
1038     return WINED3D_OK;
1039 }
1040
1041 /* *******************************************
1042    IWineD3DVertexShader IUnknown parts follow
1043    ******************************************* */
1044 static HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1045 {
1046     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1047     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1048     if (IsEqualGUID(riid, &IID_IUnknown) 
1049         || IsEqualGUID(riid, &IID_IWineD3DBase)
1050         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1051         || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1052         IUnknown_AddRef(iface);
1053         *ppobj = This;
1054         return S_OK;
1055     }
1056     *ppobj = NULL;
1057     return E_NOINTERFACE;
1058 }
1059
1060 static ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1061     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1062     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1063     return InterlockedIncrement(&This->ref);
1064 }
1065
1066 static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1067     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1068     ULONG ref;
1069     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1070     ref = InterlockedDecrement(&This->ref);
1071     if (ref == 0) {
1072         if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1073         if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
1074             /* If this shader is still attached to a program, GL will perform a lazy delete */
1075             TRACE("Deleting shader object %u\n", This->baseShader.prgId);
1076             GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
1077             checkGLcall("glDeleteObjectARB");
1078         }
1079         shader_delete_constant_list(&This->baseShader.constantsF);
1080         shader_delete_constant_list(&This->baseShader.constantsB);
1081         shader_delete_constant_list(&This->baseShader.constantsI);
1082         HeapFree(GetProcessHeap(), 0, This);
1083
1084     }
1085     return ref;
1086 }
1087
1088 /* *******************************************
1089    IWineD3DVertexShader IWineD3DVertexShader parts follow
1090    ******************************************* */
1091
1092 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1093     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1094     
1095     *parent = This->parent;
1096     IUnknown_AddRef(*parent);
1097     TRACE("(%p) : returning %p\n", This, *parent);
1098     return WINED3D_OK;
1099 }
1100
1101 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1102     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1103     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1104     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1105     TRACE("(%p) returning %p\n", This, *pDevice);
1106     return WINED3D_OK;
1107 }
1108
1109 static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1110     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1111     TRACE("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1112
1113     if (NULL == pData) {
1114         *pSizeOfData = This->baseShader.functionLength;
1115         return WINED3D_OK;
1116     }
1117     if (*pSizeOfData < This->baseShader.functionLength) {
1118         *pSizeOfData = This->baseShader.functionLength;
1119         return WINED3DERR_MOREDATA;
1120     }
1121     if (NULL == This->baseShader.function) { /* no function defined */
1122         TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1123         (*(DWORD **) pData) = NULL;
1124     } else {
1125         if(This->baseShader.functionLength == 0){
1126
1127         }
1128         TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1129         memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1130     }
1131     return WINED3D_OK;
1132 }
1133
1134 static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1135
1136     IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1137     HRESULT hr;
1138     shader_reg_maps reg_maps;
1139
1140     TRACE("(%p) : pFunction %p\n", iface, pFunction);
1141
1142     /* First pass: trace shader */
1143     shader_trace_init((IWineD3DBaseShader*) This, pFunction);
1144     vshader_set_limits(This);
1145
1146     /* Initialize immediate constant lists */
1147     list_init(&This->baseShader.constantsF);
1148     list_init(&This->baseShader.constantsB);
1149     list_init(&This->baseShader.constantsI);
1150
1151     /* Preload semantics for d3d8 shaders */
1152     if (This->vertexDeclaration) {
1153        IWineD3DVertexDeclarationImpl* vdecl = (IWineD3DVertexDeclarationImpl*) This->vertexDeclaration;
1154        int i;
1155        for (i = 0; i < vdecl->declarationWNumElements - 1; ++i) {
1156            WINED3DVERTEXELEMENT* element = vdecl->pDeclarationWine + i;
1157            vshader_set_input(This, element->Reg, element->Usage, element->UsageIndex);
1158        }
1159     }
1160
1161     /* Second pass: figure out registers used, semantics, etc.. */
1162     memset(&reg_maps, 0, sizeof(shader_reg_maps));
1163     hr = shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps,
1164        This->semantics_in, This->semantics_out, pFunction);
1165     if (hr != WINED3D_OK) return hr;
1166
1167     /* Generate HW shader in needed */
1168     This->baseShader.shader_mode = wined3d_settings.vs_selected_mode;
1169     if (NULL != pFunction && This->baseShader.shader_mode != SHADER_SW) 
1170         IWineD3DVertexShaderImpl_GenerateShader(iface, &reg_maps, pFunction);
1171
1172     /* copy the function ... because it will certainly be released by application */
1173     if (NULL != pFunction) {
1174         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1175         if (!This->baseShader.function) return E_OUTOFMEMORY;
1176         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1177     } else {
1178         This->baseShader.function = NULL;
1179     }
1180
1181     return WINED3D_OK;
1182 }
1183
1184 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1185 {
1186     /*** IUnknown methods ***/
1187     IWineD3DVertexShaderImpl_QueryInterface,
1188     IWineD3DVertexShaderImpl_AddRef,
1189     IWineD3DVertexShaderImpl_Release,
1190     /*** IWineD3DBase methods ***/
1191     IWineD3DVertexShaderImpl_GetParent,
1192     /*** IWineD3DBaseShader methods ***/
1193     IWineD3DVertexShaderImpl_SetFunction,
1194     /*** IWineD3DVertexShader methods ***/
1195     IWineD3DVertexShaderImpl_GetDevice,
1196     IWineD3DVertexShaderImpl_GetFunction
1197 };