kernel32: FindFirstChangeNotification needs a static IO_STATUS_BLOCK.
[wine] / dlls / wined3d / pixelshader.c
1 /*
2  * shaders implementation
3  *
4  * Copyright 2005      Oliver Stieber
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <math.h>
24 #include <stdio.h>
25
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
29
30 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
31
32 #if 0 /* Must not be 1 in cvs version */
33 # define PSTRACE(A) TRACE A
34 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
35 #else
36 # define PSTRACE(A)
37 # define TRACE_VSVECTOR(name)
38 #endif
39
40 /* The maximum size of the program */
41 #define PGMSIZE 65535
42
43 #define REGMASK 0x00001FFF
44 typedef void (*shader_fct_t)();
45
46 typedef struct SHADER_OPCODE {
47     unsigned int  opcode;
48     const char*   name;
49     const char*   glname;
50     CONST UINT    num_params;
51     shader_fct_t  soft_fct;
52     DWORD         min_version;
53     DWORD         max_version;
54 } SHADER_OPCODE;
55
56 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
57 /* *******************************************
58    IWineD3DPixelShader IUnknown parts follow
59    ******************************************* */
60 HRESULT WINAPI IWineD3DPixelShaderImpl_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, LPVOID *ppobj)
61 {
62     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
63     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
64     if (IsEqualGUID(riid, &IID_IUnknown)
65         || IsEqualGUID(riid, &IID_IWineD3DPixelShader)) {
66         IUnknown_AddRef(iface);
67         *ppobj = This;
68         return D3D_OK;
69     }
70     return E_NOINTERFACE;
71 }
72
73 ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) {
74     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
75     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
76     return InterlockedIncrement(&This->ref);
77 }
78
79 ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
80     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
81     ULONG ref;
82     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
83     ref = InterlockedDecrement(&This->ref);
84     if (ref == 0) {
85         HeapFree(GetProcessHeap(), 0, This);
86     }
87     return ref;
88 }
89
90 /* TODO: At the momeny the function parser is single pass, it achievs this 
91    by passing constants to a couple of functions where they are then modified.
92    At some point the parser need to be made two pass (So that GLSL can be used if it's required by the shader)
93    when happens constants should be worked out in the first pass to tidy up the second pass a bit.
94 */
95
96 /* *******************************************
97    IWineD3DPixelShader IWineD3DPixelShader parts follow
98    ******************************************* */
99
100 HRESULT WINAPI IWineD3DPixelShaderImpl_GetParent(IWineD3DPixelShader *iface, IUnknown** parent){
101     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
102
103     *parent = This->parent;
104     IUnknown_AddRef(*parent);
105     TRACE("(%p) : returning %p\n", This, *parent);
106     return D3D_OK;
107 }
108
109 HRESULT WINAPI IWineD3DPixelShaderImpl_GetDevice(IWineD3DPixelShader* iface, IWineD3DDevice **pDevice){
110     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
111     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
112     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
113     TRACE("(%p) returning %p\n", This, *pDevice);
114     return D3D_OK;
115 }
116
117
118 HRESULT WINAPI IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader* impl, VOID* pData, UINT* pSizeOfData) {
119   IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)impl;
120   FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
121
122   if (NULL == pData) {
123     *pSizeOfData = This->functionLength;
124     return D3D_OK;
125   }
126   if (*pSizeOfData < This->functionLength) {
127     *pSizeOfData = This->functionLength;
128     return D3DERR_MOREDATA;
129   }
130   if (NULL == This->function) { /* no function defined */
131     TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
132     (*(DWORD **) pData) = NULL;
133   } else {
134     if (This->functionLength == 0) {
135
136     }
137     TRACE("(%p) : GetFunction copying to %p\n", This, pData);
138     memcpy(pData, This->function, This->functionLength);
139   }
140   return D3D_OK;
141 }
142
143 /*******************************
144  * pshader functions software VM
145  */
146
147 void pshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
148     d->x = s0->x + s1->x;
149     d->y = s0->y + s1->y;
150     d->z = s0->z + s1->z;
151     d->w = s0->w + s1->w;
152     PSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
153                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
154 }
155
156 void pshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
157     d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
158     PSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
159                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
160 }
161
162 void pshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
163     d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
164     PSTRACE(("executing dp4: 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 void pshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
169     d->x = 1.0f;
170     d->y = s0->y * s1->y;
171     d->z = s0->z;
172     d->w = s1->w;
173     PSTRACE(("executing dst: 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 void pshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
178     union {
179         float f;
180         DWORD d;
181     } tmp;
182
183     tmp.f = floorf(s0->w);
184     d->x  = powf(2.0f, tmp.f);
185     d->y  = s0->w - tmp.f;
186     tmp.f = powf(2.0f, s0->w);
187     tmp.d &= 0xFFFFFF00U;
188     d->z  = tmp.f;
189     d->w  = 1.0f;
190     PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
191                     s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
192 }
193
194 void pshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
195     d->x = 1.0f;
196     d->y = (0.0f < s0->x) ? s0->x : 0.0f;
197     d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
198     d->w = 1.0f;
199     PSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
200                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
201 }
202
203 void pshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
204     float tmp_f = fabsf(s0->w);
205     d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
206     PSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
207                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
208 }
209
210 void pshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
211     d->x = s0->x * s1->x + s2->x;
212     d->y = s0->y * s1->y + s2->y;
213     d->z = s0->z * s1->z + s2->z;
214     d->w = s0->w * s1->w + s2->w;
215     PSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
216         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));
217 }
218
219 void pshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
220     d->x = (s0->x >= s1->x) ? s0->x : s1->x;
221     d->y = (s0->y >= s1->y) ? s0->y : s1->y;
222     d->z = (s0->z >= s1->z) ? s0->z : s1->z;
223     d->w = (s0->w >= s1->w) ? s0->w : s1->w;
224     PSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
225         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
226 }
227
228 void pshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
229     d->x = (s0->x < s1->x) ? s0->x : s1->x;
230     d->y = (s0->y < s1->y) ? s0->y : s1->y;
231     d->z = (s0->z < s1->z) ? s0->z : s1->z;
232     d->w = (s0->w < s1->w) ? s0->w : s1->w;
233     PSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
234         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
235 }
236
237 void pshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
238     d->x = s0->x;
239     d->y = s0->y;
240     d->z = s0->z;
241     d->w = s0->w;
242     PSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
243         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
244 }
245
246 void pshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
247     d->x = s0->x * s1->x;
248     d->y = s0->y * s1->y;
249     d->z = s0->z * s1->z;
250     d->w = s0->w * s1->w;
251     PSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
252         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
253 }
254
255 void pshader_nop(void) {
256     /* NOPPPP ahhh too easy ;) */
257     PSTRACE(("executing nop\n"));
258 }
259
260 void pshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
261     d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
262     PSTRACE(("executing rcp: 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 void pshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
267     float tmp_f = fabsf(s0->w);
268     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);
269     PSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
270         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
271 }
272
273 void pshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
274     d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
275     d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
276     d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
277     d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
278     PSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
279         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
280 }
281
282 void pshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
283     d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
284     d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
285     d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
286     d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
287     PSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
288         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
289 }
290
291 void pshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
292     d->x = s0->x - s1->x;
293     d->y = s0->y - s1->y;
294     d->z = s0->z - s1->z;
295     d->w = s0->w - s1->w;
296     PSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
297         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
298 }
299
300 /**
301  * Version 1.1 specific
302  */
303
304 void pshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
305     d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
306     PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
307         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
308 }
309
310 void pshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
311     float tmp_f = fabsf(s0->w);
312     d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
313     PSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
314         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
315 }
316
317 void pshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
318     d->x = s0->x - floorf(s0->x);
319     d->y = s0->y - floorf(s0->y);
320     d->z = 0.0f;
321     d->w = 1.0f;
322     PSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
323         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
324 }
325
326 typedef FLOAT D3DMATRIX44[4][4];
327 typedef FLOAT D3DMATRIX43[4][3];
328 typedef FLOAT D3DMATRIX34[3][4];
329 typedef FLOAT D3DMATRIX33[3][3];
330 typedef FLOAT D3DMATRIX23[2][3];
331
332 void pshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
333     /*
334     * Buggy CODE: here only if cast not work for copy/paste
335     WINED3DSHADERVECTOR* mat2 = mat1 + 1;
336     WINED3DSHADERVECTOR* mat3 = mat1 + 2;
337     WINED3DSHADERVECTOR* mat4 = mat1 + 3;
338     d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
339     d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
340     d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
341     d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
342     */
343     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
344     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
345     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
346     d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
347     PSTRACE(("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));
348     PSTRACE(("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));
349     PSTRACE(("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));
350     PSTRACE(("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));
351 }
352
353 void pshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
354     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
355     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
356     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
357     d->w = 1.0f;
358     PSTRACE(("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));
359     PSTRACE(("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));
360     PSTRACE(("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));
361     PSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
362 }
363
364 void pshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
365     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
366     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
367     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
368     d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
369     PSTRACE(("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));
370     PSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
371     PSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
372     PSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
373 }
374
375 void pshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
376     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
377     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
378     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
379     d->w = 1.0f;
380     PSTRACE(("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));
381     PSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
382     PSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
383     PSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
384 }
385
386 void pshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
387     FIXME("check\n");
388     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
389     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
390     d->z = 0.0f;
391     d->w = 1.0f;
392 }
393
394 /**
395  * Version 2.0 specific
396  */
397 void pshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
398     d->x = s0->x * (s1->x - s2->x) + s2->x;
399     d->y = s0->y * (s1->y - s2->y) + s2->y;
400     d->z = s0->z * (s1->z - s2->z) + s2->z;
401     d->w = s0->w * (s1->w - s2->w) + s2->w;
402 }
403
404 void pshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
405     d->x = s0->y * s1->z - s0->z * s1->y;
406     d->y = s0->z * s1->x - s0->x * s1->z;
407     d->z = s0->x * s1->y - s0->y * s1->x;
408     d->w = 0.9f; /* w is undefined, so set it to something safeish */
409
410     PSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
411                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
412 }
413
414 void pshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
415     d->x = fabsf(s0->x);
416     d->y = fabsf(s0->y);
417     d->z = fabsf(s0->z);
418     d->w = fabsf(s0->w);
419     PSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
420                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
421 }
422
423     /* Stubs */
424 void pshader_texcoord(WINED3DSHADERVECTOR* d) {
425     FIXME(" : Stub\n");
426 }
427
428 void pshader_texkill(WINED3DSHADERVECTOR* d) {
429     FIXME(" : Stub\n");
430 }
431
432 void pshader_tex(WINED3DSHADERVECTOR* d) {
433     FIXME(" : Stub\n");
434 }
435 void pshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
436     FIXME(" : Stub\n");
437 }
438
439 void pshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
440     FIXME(" : Stub\n");
441 }
442
443 void pshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
444     FIXME(" : Stub\n");
445 }
446
447 void pshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
448     FIXME(" : Stub\n");
449 }
450
451 void pshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
452     FIXME(" : Stub\n");
453 }
454
455 void pshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
456     FIXME(" : Stub\n");
457 }
458
459 void pshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
460     FIXME(" : Stub\n");
461 }
462
463 void pshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
464     FIXME(" : Stub\n");
465 }
466
467 void pshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
468     FIXME(" : Stub\n");
469 }
470
471 void pshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
472     FIXME(" : Stub\n");
473 }
474
475 void pshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
476     FIXME(" : Stub\n");
477 }
478
479 void pshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
480     FIXME(" : Stub\n");
481 }
482
483 void pshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
484     FIXME(" : Stub\n");
485 }
486
487 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
488 void pshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
489     FIXME(" : Stub\n");
490 }
491
492 void pshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
493     FIXME(" : Stub\n");
494 }
495
496 void pshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
497     FIXME(" : Stub\n");
498 }
499
500 void pshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
501     FIXME(" : Stub\n");
502 }
503
504 void pshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
505     FIXME(" : Stub\n");
506 }
507
508 void pshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
509     FIXME(" : Stub\n");
510 }
511
512 void pshader_texdepth(WINED3DSHADERVECTOR* d) {
513     FIXME(" : Stub\n");
514 }
515
516 void pshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
517     FIXME(" : Stub\n");
518 }
519
520 void pshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
521     FIXME(" : Stub\n");
522 }
523
524 void pshader_call(WINED3DSHADERVECTOR* d) {
525     FIXME(" : Stub\n");
526 }
527
528 void pshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
529     FIXME(" : Stub\n");
530 }
531
532 void pshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
533     FIXME(" : Stub\n");
534 }
535
536 void pshader_ret(WINED3DSHADERVECTOR* d) {
537     FIXME(" : Stub\n");
538 }
539
540 void pshader_endloop(WINED3DSHADERVECTOR* d) {
541     FIXME(" : Stub\n");
542 }
543
544 void pshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
545     FIXME(" : Stub\n");
546 }
547
548 void pshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
549     FIXME(" : Stub\n");
550 }
551
552 void pshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
553     FIXME(" : Stub\n");
554 }
555
556 void pshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
557     FIXME(" : Stub\n");
558 }
559
560 void pshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
561     FIXME(" : Stub\n");
562 }
563
564 void pshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
565     FIXME(" : Stub\n");
566 }
567
568 void pshader_endrep(void) {
569     FIXME(" : Stub\n");
570 }
571
572 void pshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
573     FIXME(" : Stub\n");
574 }
575
576 void pshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
577     FIXME(" : Stub\n");
578 }
579
580 void pshader_else(WINED3DSHADERVECTOR* d) {
581     FIXME(" : Stub\n");
582 }
583
584 void pshader_label(WINED3DSHADERVECTOR* d) {
585     FIXME(" : Stub\n");
586 }
587
588 void pshader_endif(WINED3DSHADERVECTOR* d) {
589     FIXME(" : Stub\n");
590 }
591
592 void pshader_break(WINED3DSHADERVECTOR* d) {
593     FIXME(" : Stub\n");
594 }
595
596 void pshader_breakc(WINED3DSHADERVECTOR* d) {
597     FIXME(" : Stub\n");
598 }
599
600 void pshader_mova(WINED3DSHADERVECTOR* d) {
601     FIXME(" : Stub\n");
602 }
603
604 void pshader_defb(WINED3DSHADERVECTOR* d) {
605     FIXME(" : Stub\n");
606 }
607
608 void pshader_defi(WINED3DSHADERVECTOR* d) {
609     FIXME(" : Stub\n");
610 }
611
612 void pshader_dp2add(WINED3DSHADERVECTOR* d) {
613     FIXME(" : Stub\n");
614 }
615
616 void pshader_dsx(WINED3DSHADERVECTOR* d) {
617     FIXME(" : Stub\n");
618 }
619
620 void pshader_dsy(WINED3DSHADERVECTOR* d) {
621     FIXME(" : Stub\n");
622 }
623
624 void pshader_texldd(WINED3DSHADERVECTOR* d) {
625     FIXME(" : Stub\n");
626 }
627
628 void pshader_setp(WINED3DSHADERVECTOR* d) {
629     FIXME(" : Stub\n");
630 }
631
632 void pshader_texldl(WINED3DSHADERVECTOR* d) {
633     FIXME(" : Stub\n");
634 }
635
636 void pshader_breakp(WINED3DSHADERVECTOR* d) {
637     FIXME(" : Stub\n");
638 }
639 /**
640  * log, exp, frc, m*x* seems to be macros ins ... to see
641  */
642 static CONST SHADER_OPCODE pshader_ins [] = {
643     {D3DSIO_NOP,  "nop", "NOP", 0, pshader_nop, 0, 0},
644     {D3DSIO_MOV,  "mov", "MOV", 2, pshader_mov, 0, 0},
645     {D3DSIO_ADD,  "add", "ADD", 3, pshader_add, 0, 0},
646     {D3DSIO_SUB,  "sub", "SUB", 3, pshader_sub, 0, 0},
647     {D3DSIO_MAD,  "mad", "MAD", 4, pshader_mad, 0, 0},
648     {D3DSIO_MUL,  "mul", "MUL", 3, pshader_mul, 0, 0},
649     {D3DSIO_RCP,  "rcp", "RCP",  2, pshader_rcp, 0, 0},
650     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, pshader_rsq, 0, 0},
651     {D3DSIO_DP3,  "dp3",  "DP3", 3, pshader_dp3, 0, 0},
652     {D3DSIO_DP4,  "dp4",  "DP4", 3, pshader_dp4, 0, 0},
653     {D3DSIO_MIN,  "min",  "MIN", 3, pshader_min, 0, 0},
654     {D3DSIO_MAX,  "max",  "MAX", 3, pshader_max, 0, 0},
655     {D3DSIO_SLT,  "slt",  "SLT", 3, pshader_slt, 0, 0},
656     {D3DSIO_SGE,  "sge",  "SGE", 3, pshader_sge, 0, 0},
657     {D3DSIO_ABS,  "abs",  "ABS", 2, pshader_abs, 0, 0},
658     {D3DSIO_EXP,  "exp",  "EX2", 2, pshader_exp, 0, 0},
659     {D3DSIO_LOG,  "log",  "LG2", 2, pshader_log, 0, 0},
660     {D3DSIO_LIT,  "lit",  "LIT", 2, pshader_lit, 0, 0},
661     {D3DSIO_DST,  "dst",  "DST", 3, pshader_dst, 0, 0},
662     {D3DSIO_LRP,  "lrp",  "LRP", 4, pshader_lrp, 0, 0},
663     {D3DSIO_FRC,  "frc",  "FRC", 2, pshader_frc, 0, 0},
664     {D3DSIO_M4x4, "m4x4", "undefined", 3, pshader_m4x4, 0, 0},
665     {D3DSIO_M4x3, "m4x3", "undefined", 3, pshader_m4x3, 0, 0},
666     {D3DSIO_M3x4, "m3x4", "undefined", 3, pshader_m3x4, 0, 0},
667     {D3DSIO_M3x3, "m3x3", "undefined", 3, pshader_m3x3, 0, 0},
668     {D3DSIO_M3x2, "m3x2", "undefined", 3, pshader_m3x2, 0, 0},
669
670
671     /** FIXME: use direct access so add the others opcodes as stubs */
672     /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
673         They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
674     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, pshader_call,    0, 0},
675     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, pshader_callnz,  0, 0},
676     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, pshader_loop,    0, 0},
677     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, pshader_ret,     0, 0},
678     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, pshader_endloop, 0, 0},
679     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, pshader_label,   0, 0},
680     /* DCL is a specil operation */
681     {D3DSIO_DCL,      "dcl",      NULL,   1, pshader_dcl,     0, 0},
682     {D3DSIO_POW,      "pow",      "POW",  3, pshader_pow,     0, 0},
683     {D3DSIO_CRS,      "crs",      "XPS",  3, pshader_crs,     0, 0},
684     /* TODO: sng can possibly be performed as
685         RCP tmp, vec
686         MUL out, tmp, vec*/
687     {D3DSIO_SGN,      "sng",      NULL,   2, pshader_sng,     0, 0},
688     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
689         DP3 tmp , vec, vec;
690         RSQ tmp, tmp.x;
691         MUL vec.xyz, vec, tmp;
692     but I think this is better because it accounts for w properly.
693         DP3 tmp , vec, vec;
694         RSQ tmp, tmp.x;
695         MUL vec, vec, tmp;
696
697     */
698     {D3DSIO_NRM,      "nrm",      NULL,   2, pshader_nrm,     0, 0},
699     {D3DSIO_SINCOS,   "sincos",   NULL,   2, pshader_sincos,  0, 0},
700     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   2, pshader_rep,     0, 0},
701     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, pshader_endrep,  0, 0},
702     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   2, pshader_if,      0, 0},
703     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, pshader_ifc,     0, 0},
704     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   2, pshader_else,    0, 0},
705     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   2, pshader_endif,   0, 0},
706     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   2, pshader_break,   0, 0},
707     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, pshader_breakc,  0, 0},
708     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL,   2, pshader_mova,    0, 0},
709     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, pshader_defb,    0, 0},
710     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, pshader_defi,    0, 0},
711
712     {D3DSIO_TEXCOORD, "texcoord", "undefined",   1, pshader_texcoord,    0, D3DPS_VERSION(1,3)},
713     {D3DSIO_TEXCOORD, "texcrd",   "undefined",   2, pshader_texcoord,    D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
714     {D3DSIO_TEXKILL,  "texkill",  "KIL",   1, pshader_texkill,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
715     {D3DSIO_TEX,      "tex",      "undefined",   1, pshader_tex,         0, D3DPS_VERSION(1,3)},
716     {D3DSIO_TEX,      "texld",    GLNAME_REQUIRE_GLSL,   2, pshader_texld,       D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
717     {D3DSIO_TEXBEM,   "texbem",   "undefined",   2, pshader_texbem,      0, D3DPS_VERSION(1,3)},
718     {D3DSIO_TEXBEML,  "texbeml",  GLNAME_REQUIRE_GLSL,   2, pshader_texbeml,     D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
719     {D3DSIO_TEXREG2AR,"texreg2ar","undefined",   2, pshader_texreg2ar,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
720     {D3DSIO_TEXREG2GB,"texreg2gb","undefined",   2, pshader_texreg2gb,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
721     {D3DSIO_TEXM3x2PAD,   "texm3x2pad",   "undefined",   2, pshader_texm3x2pad,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
722     {D3DSIO_TEXM3x2TEX,   "texm3x2tex",   "undefined",   2, pshader_texm3x2tex,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
723     {D3DSIO_TEXM3x3DIFF,  "texm3x3diff",  GLNAME_REQUIRE_GLSL,   2, pshader_texm3x3diff,  D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
724     {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  "undefined",   3, pshader_texm3x3spec,  D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
725     {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe",  "undefined",   2, pshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
726     {D3DSIO_TEXM3x3TEX,   "texm3x3tex",   "undefined",   2, pshader_texm3x3tex,   D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
727     {D3DSIO_EXPP,     "expp",     "EXP", 2, pshader_expp, 0, 0},
728     {D3DSIO_LOGP,     "logp",     "LOG", 2, pshader_logp, 0, 0},
729     {D3DSIO_CND,      "cnd",      GLNAME_REQUIRE_GLSL,   4, pshader_cnd,         D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
730     /* def is a special operation */
731     {D3DSIO_DEF,      "def",      "undefined",   5, pshader_def,         0, 0},
732     {D3DSIO_TEXREG2RGB,   "texreg2rgb",   GLNAME_REQUIRE_GLSL,   2, pshader_texreg2rgb,  D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
733     {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL,   2, pshader_texdp3tex,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
734     {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL,   2, pshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
735     {D3DSIO_TEXDP3,       "texdp3", GLNAME_REQUIRE_GLSL,  2, pshader_texdp3,     D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
736     {D3DSIO_TEXM3x3,      "texm3x3", GLNAME_REQUIRE_GLSL, 2, pshader_texm3x3,    D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
737     {D3DSIO_TEXDEPTH,     "texdepth", GLNAME_REQUIRE_GLSL,1, pshader_texdepth,   D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
738     {D3DSIO_CMP,      "cmp",      GLNAME_REQUIRE_GLSL,   4, pshader_cmp,     D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
739     {D3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL,   3, pshader_bem,     D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
740     /* TODO: dp2add can be made out of multiple instuctions */
741     {D3DSIO_DP2ADD,   "dp2add",   GLNAME_REQUIRE_GLSL,   2, pshader_dp2add,  0, 0},
742     {D3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL,   2, pshader_dsx,     0, 0},
743     {D3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL,   2, pshader_dsy,     0, 0},
744     {D3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL,   2, pshader_texldd,  0, 0},
745     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,   2, pshader_setp,    0, 0},
746     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,   2, pshader_texldl,  0, 0},
747     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   2, pshader_breakp,  0, 0},
748     {D3DSIO_PHASE,    "phase",    GLNAME_REQUIRE_GLSL,   0, pshader_nop,     0, 0},
749     {0,               NULL,       NULL,   0, NULL,            0, 0}
750 };
751
752
753 inline static const SHADER_OPCODE* pshader_program_get_opcode(const DWORD code, const int version) {
754     DWORD i = 0;
755     DWORD hex_version = D3DPS_VERSION(version/10, version%10);
756     /** TODO: use dichotomic search */
757     while (NULL != pshader_ins[i].name) {
758         if (((code & D3DSI_OPCODE_MASK) == pshader_ins[i].opcode) &&
759             (((hex_version >= pshader_ins[i].min_version) && (hex_version <= pshader_ins[i].max_version)) ||
760             ((pshader_ins[i].min_version == 0) && (pshader_ins[i].max_version == 0)))) {
761             return &pshader_ins[i];
762         }
763         ++i;
764     }
765     FIXME("Unsupported opcode %lx(%ld) masked %lx version %d\n", code, code, code & D3DSI_OPCODE_MASK, version);
766     return NULL;
767 }
768
769 inline static BOOL pshader_is_version_token(DWORD token) {
770     return 0xFFFF0000 == (token & 0xFFFF0000);
771 }
772
773 inline static BOOL pshader_is_comment_token(DWORD token) {
774     return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
775 }
776
777
778 inline static void get_register_name(const DWORD param, char* regstr, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
779     static const char* rastout_reg_names[] = { "oC0", "oC1", "oC2", "oC3", "oDepth" };
780
781     DWORD reg = param & REGMASK;
782     DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
783
784     switch (regtype) {
785     case D3DSPR_TEMP:
786         sprintf(regstr, "R%lu", reg);
787     break;
788     case D3DSPR_INPUT:
789         if (reg==0) {
790             strcpy(regstr, "fragment.color.primary");
791         } else {
792             strcpy(regstr, "fragment.color.secondary");
793         }
794     break;
795     case D3DSPR_CONST:
796         if (constants[reg])
797             sprintf(regstr, "C%lu", reg);
798         else
799             sprintf(regstr, "program.env[%lu]", reg);
800     break;
801     case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
802         sprintf(regstr,"T%lu", reg);
803     break;
804     case D3DSPR_RASTOUT:
805         sprintf(regstr, "%s", rastout_reg_names[reg]);
806     break;
807     case D3DSPR_ATTROUT:
808         sprintf(regstr, "oD[%lu]", reg);
809     break;
810     case D3DSPR_TEXCRDOUT:
811         sprintf(regstr, "oT[%lu]", reg);
812     break;
813     default:
814         FIXME("Unhandled register name Type(%ld)\n", regtype);
815     break;
816     }
817 }
818
819 inline static void get_write_mask(const DWORD output_reg, char *write_mask) {
820     *write_mask = 0;
821     if ((output_reg & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
822         strcat(write_mask, ".");
823         if (output_reg & D3DSP_WRITEMASK_0) strcat(write_mask, "r");
824         if (output_reg & D3DSP_WRITEMASK_1) strcat(write_mask, "g");
825         if (output_reg & D3DSP_WRITEMASK_2) strcat(write_mask, "b");
826         if (output_reg & D3DSP_WRITEMASK_3) strcat(write_mask, "a");
827     }
828 }
829
830 inline static void get_input_register_swizzle(const DWORD instr, char *swzstring) {
831     static const char swizzle_reg_chars[] = "rgba";
832     DWORD swizzle = (instr & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
833     DWORD swizzle_x = swizzle & 0x03;
834     DWORD swizzle_y = (swizzle >> 2) & 0x03;
835     DWORD swizzle_z = (swizzle >> 4) & 0x03;
836     DWORD swizzle_w = (swizzle >> 6) & 0x03;
837     /**
838      * swizzle bits fields:
839      *  WWZZYYXX
840      */
841     *swzstring = 0;
842     if ((D3DSP_NOSWIZZLE >> D3DSP_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
843         if (swizzle_x == swizzle_y && 
844         swizzle_x == swizzle_z && 
845         swizzle_x == swizzle_w) {
846             sprintf(swzstring, ".%c", swizzle_reg_chars[swizzle_x]);
847         } else {
848             sprintf(swzstring, ".%c%c%c%c", 
849                 swizzle_reg_chars[swizzle_x], 
850                 swizzle_reg_chars[swizzle_y], 
851                 swizzle_reg_chars[swizzle_z], 
852                 swizzle_reg_chars[swizzle_w]);
853         }
854     }
855 }
856
857 inline static void addline(unsigned int *lineNum, char *pgm, unsigned int *pgmLength, char *line) {
858     int lineLen = strlen(line);
859     if(lineLen + *pgmLength > PGMSIZE - 1 /* - 1 to allow a NULL at the end */) {
860         ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, lineLen + *pgmLength);
861         return;
862     } else {
863         memcpy(pgm + *pgmLength, line, lineLen);
864     }
865
866     *pgmLength += lineLen;
867     ++(*lineNum);
868     TRACE("GL HW (%u, %u) : %s", *lineNum, *pgmLength, line);
869 }
870
871 static const char* shift_tab[] = {
872     "dummy",     /*  0 (none) */ 
873     "coefmul.x", /*  1 (x2)   */ 
874     "coefmul.y", /*  2 (x4)   */ 
875     "coefmul.z", /*  3 (x8)   */ 
876     "coefmul.w", /*  4 (x16)  */ 
877     "dummy",     /*  5 (x32)  */ 
878     "dummy",     /*  6 (x64)  */ 
879     "dummy",     /*  7 (x128) */ 
880     "dummy",     /*  8 (d256) */ 
881     "dummy",     /*  9 (d128) */ 
882     "dummy",     /* 10 (d64)  */ 
883     "dummy",     /* 11 (d32)  */ 
884     "coefdiv.w", /* 12 (d16)  */ 
885     "coefdiv.z", /* 13 (d8)   */ 
886     "coefdiv.y", /* 14 (d4)   */ 
887     "coefdiv.x"  /* 15 (d2)   */ 
888 };
889
890 inline static void gen_output_modifier_line(int saturate, char *write_mask, int shift, char *regstr, char* line) {
891     /* Generate a line that does the output modifier computation */
892     sprintf(line, "MUL%s %s%s, %s, %s;", saturate ? "_SAT" : "", regstr, write_mask, regstr, shift_tab[shift]);
893 }
894
895 inline static int gen_input_modifier_line(const DWORD instr, int tmpreg, char *outregstr, char *line, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
896     /* Generate a line that does the input modifier computation and return the input register to use */
897     static char regstr[256];
898     static char tmpline[256];
899     int insert_line;
900
901     /* Assume a new line will be added */
902     insert_line = 1;
903
904     /* Get register name */
905     get_register_name(instr, regstr, constants);
906
907     TRACE(" Register name %s\n", regstr);
908     switch (instr & D3DSP_SRCMOD_MASK) {
909     case D3DSPSM_NONE:
910         strcpy(outregstr, regstr);
911         insert_line = 0;
912         break;
913     case D3DSPSM_NEG:
914         sprintf(outregstr, "-%s", regstr);
915         insert_line = 0;
916         break;
917     case D3DSPSM_BIAS:
918         sprintf(line, "ADD T%c, %s, -coefdiv.x;", 'A' + tmpreg, regstr);
919         break;
920     case D3DSPSM_BIASNEG:
921         sprintf(line, "ADD T%c, -%s, coefdiv.x;", 'A' + tmpreg, regstr);
922         break;
923     case D3DSPSM_SIGN:
924         sprintf(line, "MAD T%c, %s, coefmul.x, -one.x;", 'A' + tmpreg, regstr);
925         break;
926     case D3DSPSM_SIGNNEG:
927         sprintf(line, "MAD T%c, %s, -coefmul.x, one.x;", 'A' + tmpreg, regstr);
928         break;
929     case D3DSPSM_COMP:
930         sprintf(line, "SUB T%c, one.x, %s;", 'A' + tmpreg, regstr);
931         break;
932     case D3DSPSM_X2:
933         sprintf(line, "ADD T%c, %s, %s;", 'A' + tmpreg, regstr, regstr);
934         break;
935     case D3DSPSM_X2NEG:
936         sprintf(line, "ADD T%c, -%s, -%s;", 'A' + tmpreg, regstr, regstr);
937         break;
938     case D3DSPSM_DZ:
939         sprintf(line, "RCP T%c, %s.z;", 'A' + tmpreg, regstr);
940         sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
941         strcat(line, "\n"); /* Hack */
942         strcat(line, tmpline);
943         break;
944     case D3DSPSM_DW:
945         sprintf(line, "RCP T%c, %s;", 'A' + tmpreg, regstr);
946         sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
947         strcat(line, "\n"); /* Hack */
948         strcat(line, tmpline);
949         break;
950     default:
951         strcpy(outregstr, regstr);
952         insert_line = 0;
953     }
954
955     if (insert_line) {
956         /* Substitute the register name */
957         sprintf(outregstr, "T%c", 'A' + tmpreg);
958     }
959
960     return insert_line;
961 }
962 /* NOTE: A description of how to parse tokens can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/graphics/hh/graphics/usermodedisplaydriver_shader_cc8e4e05-f5c3-4ec0-8853-8ce07c1551b2.xml.asp */
963 inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
964     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
965     const DWORD *pToken = pFunction;
966     const SHADER_OPCODE *curOpcode = NULL;
967     const DWORD *pInstr;
968     DWORD i;
969     unsigned lineNum = 0; /* The line number of the generated program (for loging)*/
970     char *pgmStr = NULL; /* A pointer to the program data generated by this function */
971     char  tmpLine[255];
972     DWORD nUseAddressRegister = 0;
973 #if 0 /* TODO: loop register (just another address register ) */
974     BOOL hasLoops = FALSE;
975 #endif
976
977     BOOL saturate; /* clamp to 0.0 -> 1.0*/
978     int row = 0; /* not sure, something to do with macros? */
979     DWORD tcw[2];
980     int version = 0; /* The version of the shader */
981
982     /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
983     unsigned int pgmLength = 0;
984
985 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
986         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
987     if (This->device->fixupVertexBufferSize < PGMSIZE) {
988         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
989         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
990         This->fixupVertexBufferSize = PGMSIZE;
991         This->fixupVertexBuffer[0] = 0;
992     }
993     pgmStr = This->device->fixupVertexBuffer;
994 #else
995     pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PGMSIZE); /* 64kb should be enough */
996 #endif
997
998
999     /* TODO: Think about using a first pass to work out what's required for the second pass. */
1000     for(i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; i++)
1001         This->constants[i] = 0;
1002
1003     if (NULL != pToken) {
1004         while (D3DPS_END() != *pToken) {
1005 #if 0 /* For pixel and vertex shader versions 2_0 and later, bits 24 through 27 specify the size in DWORDs of the instruction */
1006             if (version >= 2) {
1007                 instructionSize = pToken & SIZEBITS >> 27;
1008             }
1009 #endif
1010             if (pshader_is_version_token(*pToken)) { /** version */
1011                 int numTemps;
1012                 int numConstants;
1013
1014                 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1015                 version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1016
1017                 TRACE("found version token ps.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1018
1019                 /* Each release of pixel shaders has had different numbers of temp registers */
1020                 switch (version) {
1021                 case 10:
1022                 case 11:
1023                 case 12:
1024                 case 13:
1025                 case 14: numTemps=12;
1026                         numConstants=8;
1027                         strcpy(tmpLine, "!!ARBfp1.0\n");
1028                         break;
1029                 case 20: numTemps=12;
1030                         numConstants=8;
1031                         strcpy(tmpLine, "!!ARBfp2.0\n");
1032                         FIXME("No work done yet to support ps2.0 in hw\n");
1033                         break;
1034                 case 30: numTemps=32;
1035                         numConstants=8;
1036                         strcpy(tmpLine, "!!ARBfp3.0\n");
1037                         FIXME("No work done yet to support ps3.0 in hw\n");
1038                         break;
1039                 default:
1040                         numTemps=12;
1041                         numConstants=8;
1042                         strcpy(tmpLine, "!!ARBfp1.0\n");
1043                         FIXME("Unrecognized pixel shader version!\n");
1044                 }
1045                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1046
1047                 /* TODO: find out how many registers are really needed */
1048                 for(i = 0; i < 6; i++) {
1049                     sprintf(tmpLine, "TEMP T%lu;\n", i);
1050                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1051                 }
1052
1053                 for(i = 0; i < 6; i++) {
1054                     sprintf(tmpLine, "TEMP R%lu;\n", i);
1055                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1056                 }
1057
1058                 sprintf(tmpLine, "TEMP TMP;\n");
1059                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1060                 sprintf(tmpLine, "TEMP TMP2;\n");
1061                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1062                 sprintf(tmpLine, "TEMP TA;\n");
1063                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1064                 sprintf(tmpLine, "TEMP TB;\n");
1065                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1066                 sprintf(tmpLine, "TEMP TC;\n");
1067                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1068
1069                 strcpy(tmpLine, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1070                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1071                 strcpy(tmpLine, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1072                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1073                 strcpy(tmpLine, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1074                 addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1075
1076                 for(i = 0; i < 4; i++) {
1077                     sprintf(tmpLine, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
1078                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1079                 }
1080
1081                 ++pToken;
1082                 continue;
1083             }
1084
1085             if (pshader_is_comment_token(*pToken)) { /** comment */
1086                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1087                 ++pToken;
1088                 FIXME("#%s\n", (char*)pToken);
1089                 pToken += comment_len;
1090                 continue;
1091             }
1092 /* here */
1093 #if 0 /* Not sure what these are here for, they're not required for vshaders */
1094             code = *pToken;
1095 #endif
1096             pInstr = pToken;
1097             curOpcode = pshader_program_get_opcode(*pToken, version);
1098             ++pToken;
1099             if (NULL == curOpcode) {
1100                 /* unknown current opcode ... (shouldn't be any!) */
1101                 while (*pToken & 0x80000000) { /* TODO: Think of a sensible name for 0x80000000 */
1102                     FIXME("unrecognized opcode: %08lx\n", *pToken);
1103                     ++pToken;
1104                 }
1105             } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1106                 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1107                 FIXME("Token %s requires greater functionality than Fragment_Progarm_ARB supports\n", curOpcode->name);
1108                 pToken += curOpcode->num_params;
1109             } else {
1110                 TRACE("Found opcode %s %s\n", curOpcode->name, curOpcode->glname);
1111                 saturate = FALSE;
1112
1113                 /* Build opcode for GL vertex_program */
1114                 switch (curOpcode->opcode) {
1115                 case D3DSIO_NOP:
1116                 case D3DSIO_PHASE:
1117                     continue;
1118                 case D3DSIO_MOV:
1119                     /* Address registers must be loaded with the ARL instruction */
1120                     if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1121                         if (((*pToken) & REGMASK) < nUseAddressRegister) {
1122                             strcpy(tmpLine, "ARL");
1123                             break;
1124                         } else
1125                             FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & REGMASK));
1126                     }
1127                     /* fall through */
1128                 case D3DSIO_CND:
1129                 case D3DSIO_CMP:
1130                 case D3DSIO_ADD:
1131                 case D3DSIO_SUB:
1132                 case D3DSIO_MAD:
1133                 case D3DSIO_MUL:
1134                 case D3DSIO_RCP:
1135                 case D3DSIO_RSQ:
1136                 case D3DSIO_DP3:
1137                 case D3DSIO_DP4:
1138                 case D3DSIO_MIN:
1139                 case D3DSIO_MAX:
1140                 case D3DSIO_SLT:
1141                 case D3DSIO_SGE:
1142                 case D3DSIO_LIT:
1143                 case D3DSIO_DST:
1144                 case D3DSIO_FRC:
1145                 case D3DSIO_EXPP:
1146                 case D3DSIO_LOGP:
1147                 case D3DSIO_EXP:
1148                 case D3DSIO_LOG:
1149                 case D3DSIO_LRP:
1150                 case D3DSIO_TEXKILL:
1151                     TRACE("Appending glname %s to tmpLine\n", curOpcode->glname);
1152                     strcpy(tmpLine, curOpcode->glname);
1153                     break;
1154                 case D3DSIO_DEF:
1155                 {
1156                     DWORD reg = *pToken & REGMASK;
1157                     sprintf(tmpLine, "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1158                               *((const float *)(pToken + 1)),
1159                               *((const float *)(pToken + 2)),
1160                               *((const float *)(pToken + 3)),
1161                               *((const float *)(pToken + 4)) );
1162
1163                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1164
1165                     This->constants[reg] = 1;
1166                     pToken += 5;
1167                     continue;
1168                 }
1169                 break;
1170                 case D3DSIO_TEX:
1171                 {
1172                     char tmp[20];
1173                     get_write_mask(*pToken, tmp);
1174                     if (version != 14) {
1175                         DWORD reg = *pToken & REGMASK;
1176                         sprintf(tmpLine,"TEX T%lu%s, T%lu, texture[%lu], 2D;\n", reg, tmp, reg, reg);
1177                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1178                         ++pToken;
1179                     } else {
1180                         char reg[20];
1181                         DWORD reg1 = *pToken & REGMASK;
1182                         DWORD reg2 = *++pToken & REGMASK;
1183                         if (gen_input_modifier_line(*pToken, 0, reg, tmpLine, This->constants)) {
1184                             addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1185                         }
1186                         sprintf(tmpLine,"TEX R%lu%s, %s, texture[%lu], 2D;\n", reg1, tmp, reg, reg2);
1187                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1188                         ++pToken;
1189                     }
1190                     continue;
1191                 }
1192                 break;
1193                 case D3DSIO_TEXCOORD:
1194                 {
1195                     char tmp[20];
1196                     get_write_mask(*pToken, tmp);
1197                     if (version != 14) {
1198                         DWORD reg = *pToken & REGMASK;
1199                         sprintf(tmpLine, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1200                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1201                         ++pToken;
1202                     } else {
1203                         DWORD reg1 = *pToken & REGMASK;
1204                         DWORD reg2 = *++pToken & REGMASK;
1205                         sprintf(tmpLine, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1206                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1207                         ++pToken;
1208                     }
1209                     continue;
1210                 }
1211                 break;
1212                 case D3DSIO_TEXM3x2PAD:
1213                 {
1214                     DWORD reg = *pToken & REGMASK;
1215                     char buf[50];
1216                     if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
1217                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1218                     }
1219                     sprintf(tmpLine, "DP3 TMP.x, T%lu, %s;\n", reg, buf);
1220                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1221                     ++pToken;
1222                     continue;
1223                 }
1224                 break;
1225                 case D3DSIO_TEXM3x2TEX:
1226                 {
1227                     DWORD reg = *pToken & REGMASK;
1228                     char buf[50];
1229                     if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
1230                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1231                     }
1232                     sprintf(tmpLine, "DP3 TMP.y, T%lu, %s;\n", reg, buf);
1233                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1234                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1235                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1236                     ++pToken;
1237                     continue;
1238                 }
1239                 break;
1240                 case D3DSIO_TEXREG2AR:
1241                 {
1242                     DWORD reg1 = *pToken & REGMASK;
1243                     DWORD reg2 = *++pToken & REGMASK;
1244                     sprintf(tmpLine, "MOV TMP.r, T%lu.a;\n", reg2);
1245                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1246                     sprintf(tmpLine, "MOV TMP.g, T%lu.r;\n", reg2);
1247                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1248                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1249                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1250                     ++pToken;
1251                     continue;
1252                 }
1253                 break;
1254                 case D3DSIO_TEXREG2GB:
1255                 {
1256                     DWORD reg1 = *pToken & REGMASK;
1257                     DWORD reg2 = *++pToken & REGMASK;
1258                     sprintf(tmpLine, "MOV TMP.r, T%lu.g;\n", reg2);
1259                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1260                     sprintf(tmpLine, "MOV TMP.g, T%lu.b;\n", reg2);
1261                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1262                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1263                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1264                     ++pToken;
1265                     continue;
1266                 }
1267                 break;
1268                 case D3DSIO_TEXBEM:
1269                 {
1270                     DWORD reg1 = *pToken & REGMASK;
1271                     DWORD reg2 = *++pToken & REGMASK;
1272
1273                     /* FIXME: Should apply the BUMPMAPENV matrix */
1274                     sprintf(tmpLine, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1275                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1276                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1277                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1278                     ++pToken;
1279                     continue;
1280                 }
1281                 break;
1282                 case D3DSIO_TEXM3x3PAD:
1283                 {
1284                     DWORD reg = *pToken & REGMASK;
1285                     char buf[50];
1286                     if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
1287                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1288                     }
1289                     sprintf(tmpLine, "DP3 TMP.%c, T%lu, %s;\n", 'x'+row, reg, buf);
1290                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1291                     tcw[row++] = reg;
1292                     ++pToken;
1293                     continue;
1294                 }
1295                 break;
1296                 case D3DSIO_TEXM3x3TEX:
1297                 {
1298                     DWORD reg = *pToken & REGMASK;
1299                     char buf[50];
1300                     if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
1301                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1302                     }
1303
1304                     sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1305                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1306
1307                     /* Cubemap textures will be more used than 3D ones. */
1308                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1309                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1310                     row = 0;
1311                     ++pToken;
1312                     continue;
1313                 }
1314                 case D3DSIO_TEXM3x3VSPEC:
1315                 {
1316                     DWORD reg = *pToken & REGMASK;
1317                     char buf[50];
1318                     if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
1319                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1320                     }
1321                     sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1322                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1323
1324                     /* Construct the eye-ray vector from w coordinates */
1325                     sprintf(tmpLine, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", tcw[0]);
1326                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1327                     sprintf(tmpLine, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", tcw[1]);
1328                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1329                     sprintf(tmpLine, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1330                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1331
1332                     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1333                     sprintf(tmpLine, "DP3 TMP.w, TMP, TMP2;\n");
1334                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1335                     sprintf(tmpLine, "MUL TMP, TMP.w, TMP;\n");
1336                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1337                     sprintf(tmpLine, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1338                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1339
1340                     /* Cubemap textures will be more used than 3D ones. */
1341                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1342                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1343                     row = 0;
1344                     ++pToken;
1345                     continue;
1346                 }
1347                 break;
1348                 case D3DSIO_TEXM3x3SPEC:
1349                 {
1350                     DWORD reg = *pToken & REGMASK;
1351                     DWORD reg3 = *(pToken + 2) & REGMASK;
1352                     char buf[50];
1353                     if (gen_input_modifier_line(*(pToken + 1), 0, buf, tmpLine, This->constants)) {
1354                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1355                     }
1356                     sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1357                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1358
1359                     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1360                     sprintf(tmpLine, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1361                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1362
1363                     sprintf(tmpLine, "MUL TMP, TMP.w, TMP;\n");
1364                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1365                     sprintf(tmpLine, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1366                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1367
1368                     /* Cubemap textures will be more used than 3D ones. */
1369                     sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1370                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1371                     row = 0;
1372                     pToken += 3;
1373                     continue;
1374                 }
1375                 break;
1376
1377                 default:
1378                     if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1379                         FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1380                     } else {
1381                         FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1382                     }
1383                     pToken += curOpcode->num_params; /* maybe  + 1 */
1384                     continue;
1385                 }
1386
1387                 if (0 != (*pToken & D3DSP_DSTMOD_MASK)) {
1388                     DWORD mask = *pToken & D3DSP_DSTMOD_MASK;
1389                     switch (mask) {
1390                     case D3DSPDM_SATURATE: saturate = TRUE; break;
1391 #if 0 /* as yet unhandled modifiers */
1392                     case D3DSPDM_CENTROID: centroid = TRUE; break;
1393                     case D3DSPDM_PP: partialpresision = TRUE; break;
1394                     case D3DSPDM_X2: X2 = TRUE; break;
1395                     case D3DSPDM_X4: X4 = TRUE; break;
1396                     case D3DSPDM_X8: X8 = TRUE; break;
1397                     case D3DSPDM_D2: D2 = TRUE; break;
1398                     case D3DSPDM_D4: D4 = TRUE; break;
1399                     case D3DSPDM_D8: D8 = TRUE; break;
1400 #endif
1401                     default:
1402                         TRACE("_unhandled_modifier(0x%08lx)\n", mask);
1403                     }
1404                 }
1405
1406                 /* Generate input and output registers */
1407                 if (curOpcode->num_params > 0) {
1408                     char regs[5][50];
1409                     char operands[4][100];
1410                     char swzstring[20];
1411                     int saturate = 0;
1412                     char tmpOp[256];
1413                     TRACE("(%p): Opcode has %d params\n", This, curOpcode->num_params);
1414
1415                     /* Generate lines that handle input modifier computation */
1416                     for (i = 1; i < curOpcode->num_params; ++i) {
1417                         TRACE("(%p) : Param %ld token %lx\n", This, i, *(pToken + i));
1418                         if (gen_input_modifier_line(*(pToken + i), i - 1, regs[i - 1], tmpLine, This->constants)) {
1419                             addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1420                         }
1421                     }
1422
1423                     /* Handle saturation only when no shift is present in the output modifier */
1424                     if ((*pToken & D3DSPDM_SATURATE) && (0 == (*pToken & D3DSP_DSTSHIFT_MASK)))
1425                         saturate = 1;
1426
1427                     /* Handle output register */
1428                     get_register_name(*pToken, tmpOp, This->constants);
1429                     strcpy(operands[0], tmpOp);
1430                     get_write_mask(*pToken, tmpOp);
1431                     strcat(operands[0], tmpOp);
1432
1433                     /* This function works because of side effects from  gen_input_modifier_line */
1434                     /* Handle input registers */
1435                     for (i = 1; i < curOpcode->num_params; ++i) {
1436                         TRACE("(%p) : Regs = %s\n", This, regs[i - 1]);
1437                         strcpy(operands[i], regs[i - 1]);
1438                         get_input_register_swizzle(*(pToken + i), swzstring);
1439                         strcat(operands[i], swzstring);
1440                     }
1441
1442                     switch(curOpcode->opcode) {
1443                     case D3DSIO_CMP:
1444                         sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""), operands[0], operands[1], operands[3], operands[2]);
1445                     break;
1446                     case D3DSIO_CND:
1447                         sprintf(tmpLine, "ADD TMP, -%s, coefdiv.x;", operands[1]);
1448                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1449                         sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""), operands[0], operands[2], operands[3]);
1450                     break;
1451                     default:
1452                         if (saturate)
1453                             strcat(tmpLine, "_SAT");
1454                         strcat(tmpLine, " ");
1455                         strcat(tmpLine, operands[0]);
1456                         for (i = 1; i < curOpcode->num_params; i++) {
1457                             strcat(tmpLine, ", ");
1458                             strcat(tmpLine, operands[i]);
1459                         }
1460                         strcat(tmpLine,";\n");
1461                     }
1462                     addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1463                     pToken += curOpcode->num_params;
1464                 }
1465 #if 0           /* I Think this isn't needed because the code above generates the input / output registers. */
1466                 if (curOpcode->num_params > 0) {
1467                     DWORD param = *(pInstr + 1);
1468                     if (0 != (param & D3DSP_DSTSHIFT_MASK)) {
1469
1470                         /* Generate a line that handle the output modifier computation */
1471                         char regstr[100];
1472                         char write_mask[20];
1473                         DWORD shift = (param & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1474                         get_register_name(param, regstr, This->constants);
1475                         get_write_mask(param, write_mask);
1476                         gen_output_modifier_line(saturate, write_mask, shift, regstr, tmpLine);
1477                         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1478                     }
1479                 }
1480 #endif
1481             }
1482         }
1483         /* TODO: What about result.depth? */
1484         strcpy(tmpLine, "MOV result.color, R0;\n");
1485         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1486
1487         strcpy(tmpLine, "END\n");
1488         addline(&lineNum, pgmStr, &pgmLength, tmpLine);
1489     }
1490
1491     /* finally null terminate the pgmStr*/
1492     pgmStr[pgmLength] = 0;
1493     if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1494         /*  Create the hw shader */
1495
1496         /* pgmStr sometimes gets too long for a normal TRACE */
1497         TRACE("Generated program:\n");
1498         if (TRACE_ON(d3d_shader)) {
1499             fprintf(stderr, "%s\n", pgmStr);
1500         }
1501
1502         /* TODO: change to resource.glObjectHandel or something like that */
1503         GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1504
1505         TRACE("Creating a hw pixel shader, prg=%d\n", This->prgId);
1506         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->prgId));
1507
1508         TRACE("Created hw pixel shader, prg=%d\n", This->prgId);
1509         /* Create the program and check for errors */
1510         GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr), pgmStr));
1511         if (glGetError() == GL_INVALID_OPERATION) {
1512             GLint errPos;
1513             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1514             FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1515             This->prgId = -1;
1516         }
1517     }
1518 #if 1 /* if were using the data buffer of device then we don't need to free it */
1519     HeapFree(GetProcessHeap(), 0, pgmStr);
1520 #endif
1521 }
1522
1523 inline static void pshader_program_dump_ps_param(const DWORD param, int input) {
1524   static const char* rastout_reg_names[] = { "oC0", "oC1", "oC2", "oC3", "oDepth" };
1525   static const char swizzle_reg_chars[] = "rgba";
1526
1527    /* the unknown mask is for bits not yet accounted for by any other mask... */
1528 #define UNKNOWN_MASK 0xC000
1529
1530    /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
1531 #define EXTENDED_REG 0x1800
1532
1533   DWORD reg = param & D3DSP_REGNUM_MASK;
1534   DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
1535
1536   if (input) {
1537     if ( ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) ||
1538          ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_BIASNEG) ||
1539          ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_SIGNNEG) ||
1540          ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_X2NEG) )
1541       TRACE("-");
1542     else if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_COMP)
1543       TRACE("1-");
1544   }
1545
1546   switch (regtype /* << D3DSP_REGTYPE_SHIFT (I don't know why this was here)*/) {
1547   case D3DSPR_TEMP:
1548     TRACE("r%lu", reg);
1549     break;
1550   case D3DSPR_INPUT:
1551     TRACE("v%lu", reg);
1552     break;
1553   case D3DSPR_CONST:
1554     TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
1555     break;
1556
1557   case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
1558     TRACE("t%lu", reg);
1559     break;
1560   case D3DSPR_RASTOUT:
1561     TRACE("%s", rastout_reg_names[reg]);
1562     break;
1563   case D3DSPR_ATTROUT:
1564     TRACE("oD%lu", reg);
1565     break;
1566   case D3DSPR_TEXCRDOUT:
1567     TRACE("oT%lu", reg);
1568     break;
1569   case D3DSPR_CONSTINT:
1570     TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
1571     break;
1572   case D3DSPR_CONSTBOOL:
1573     TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
1574     break;
1575   case D3DSPR_LABEL:
1576     TRACE("l%lu", reg);
1577     break;
1578   case D3DSPR_LOOP:
1579     TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
1580     break;
1581   default:
1582     break;
1583   }
1584
1585     if (!input) {
1586         /** operand output */
1587         /**
1588             * for better debugging traces it's done into opcode dump code
1589             * @see pshader_program_dump_opcode
1590         if (0 != (param & D3DSP_DSTMOD_MASK)) {
1591             DWORD mask = param & D3DSP_DSTMOD_MASK;
1592             switch (mask) {
1593             case D3DSPDM_SATURATE: TRACE("_sat"); break;
1594             default:
1595             TRACE("_unhandled_modifier(0x%08lx)", mask);
1596             }
1597         }
1598         if (0 != (param & D3DSP_DSTSHIFT_MASK)) {
1599             DWORD shift = (param & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1600             if (shift > 0) {
1601         TRACE("_x%u", 1 << shift);
1602             }
1603         }
1604         */
1605         if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1606             TRACE(".");
1607             if (param & D3DSP_WRITEMASK_0) TRACE(".r");
1608             if (param & D3DSP_WRITEMASK_1) TRACE(".g");
1609             if (param & D3DSP_WRITEMASK_2) TRACE(".b");
1610             if (param & D3DSP_WRITEMASK_3) TRACE(".a");
1611         }
1612     } else {
1613         /** operand input */
1614         DWORD swizzle = (param & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
1615         DWORD swizzle_r = swizzle & 0x03;
1616         DWORD swizzle_g = (swizzle >> 2) & 0x03;
1617         DWORD swizzle_b = (swizzle >> 4) & 0x03;
1618         DWORD swizzle_a = (swizzle >> 6) & 0x03;
1619
1620         if (0 != (param & D3DSP_SRCMOD_MASK)) {
1621             DWORD mask = param & D3DSP_SRCMOD_MASK;
1622             /*TRACE("_modifier(0x%08lx) ", mask);*/
1623             switch (mask) {
1624                 case D3DSPSM_NONE:    break;
1625                 case D3DSPSM_NEG:     break;
1626                 case D3DSPSM_BIAS:    TRACE("_bias"); break;
1627                 case D3DSPSM_BIASNEG: TRACE("_bias"); break;
1628                 case D3DSPSM_SIGN:    TRACE("_bx2"); break;
1629                 case D3DSPSM_SIGNNEG: TRACE("_bx2"); break;
1630                 case D3DSPSM_COMP:    break;
1631                 case D3DSPSM_X2:      TRACE("_x2"); break;
1632                 case D3DSPSM_X2NEG:   TRACE("_x2"); break;
1633                 case D3DSPSM_DZ:      TRACE("_dz"); break;
1634                 case D3DSPSM_DW:      TRACE("_dw"); break;
1635                 default:
1636                     TRACE("_unknown(0x%08lx)", mask);
1637             }
1638         }
1639
1640         /**
1641         * swizzle bits fields:
1642         *  RRGGBBAA
1643         */
1644         if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
1645             if (swizzle_r == swizzle_g &&
1646                 swizzle_r == swizzle_b &&
1647                 swizzle_r == swizzle_a) {
1648                     TRACE(".%c", swizzle_reg_chars[swizzle_r]);
1649             } else {
1650                 TRACE(".%c%c%c%c",
1651                 swizzle_reg_chars[swizzle_r],
1652                 swizzle_reg_chars[swizzle_g],
1653                 swizzle_reg_chars[swizzle_b],
1654                 swizzle_reg_chars[swizzle_a]);
1655             }
1656         }
1657     }
1658 }
1659
1660 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1661     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1662     const DWORD* pToken = pFunction;
1663     const SHADER_OPCODE *curOpcode = NULL;
1664     DWORD len = 0;
1665     DWORD i;
1666     int version = 0;
1667     TRACE("(%p) : Parsing programme\n", This);
1668
1669     if (NULL != pToken) {
1670         while (D3DPS_END() != *pToken) {
1671             if (pshader_is_version_token(*pToken)) { /** version */
1672                 version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1673                 TRACE("ps_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1674                 ++pToken;
1675                 ++len;
1676                 continue;
1677             }
1678             if (pshader_is_comment_token(*pToken)) { /** comment */
1679                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1680                 ++pToken;
1681                 TRACE("//%s\n", (char*)pToken);
1682                 pToken += comment_len;
1683                 len += comment_len + 1;
1684                 continue;
1685             }
1686             if (!version) {
1687                 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1688             }
1689             curOpcode = pshader_program_get_opcode(*pToken, version);
1690             ++pToken;
1691             ++len;
1692             if (NULL == curOpcode) {
1693
1694                 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1695                 while (*pToken & 0x80000000) {
1696
1697                     /* unknown current opcode ... */
1698                     TRACE("unrecognized opcode: %08lx", *pToken);
1699                     ++pToken;
1700                     ++len;
1701                     TRACE("\n");
1702                 }
1703
1704             } else {
1705                 if (curOpcode->opcode == D3DSIO_DCL) {
1706                     TRACE("dcl_");
1707                     switch(*pToken & 0xFFFF) {
1708                         case D3DDECLUSAGE_POSITION:
1709                         TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
1710                         break;
1711                         case D3DDECLUSAGE_BLENDINDICES:
1712                         TRACE("%s ", "blend");
1713                         break;
1714                         case D3DDECLUSAGE_BLENDWEIGHT:
1715                         TRACE("%s ", "weight");
1716                         break;
1717                         case D3DDECLUSAGE_NORMAL:
1718                         TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
1719                         break;
1720                         case D3DDECLUSAGE_PSIZE:
1721                         TRACE("%s ", "psize");
1722                         break;
1723                         case D3DDECLUSAGE_COLOR:
1724                         if((*pToken & 0xF0000) >> 16 == 0)  {
1725                             TRACE("%s ", "color");
1726                         } else {
1727                             TRACE("%s%ld ", "specular", ((*pToken & 0xF0000) >> 16) - 1);
1728                         }
1729                         break;
1730                         case D3DDECLUSAGE_TEXCOORD:
1731                         TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
1732                         break;
1733                         case D3DDECLUSAGE_TANGENT:
1734                         TRACE("%s ", "tangent");
1735                         break;
1736                         case D3DDECLUSAGE_BINORMAL:
1737                         TRACE("%s ", "binormal");
1738                         break;
1739                         case D3DDECLUSAGE_TESSFACTOR:
1740                         TRACE("%s ", "tessfactor");
1741                         break;
1742                         case D3DDECLUSAGE_POSITIONT:
1743                         TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
1744                         break;
1745                         case D3DDECLUSAGE_FOG:
1746                         TRACE("%s ", "fog");
1747                         break;
1748                         case D3DDECLUSAGE_DEPTH:
1749                         TRACE("%s ", "depth");
1750                         break;
1751                         case D3DDECLUSAGE_SAMPLE:
1752                         TRACE("%s ", "sample");
1753                         break;
1754                         default:
1755                         FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1756                     }
1757                     ++pToken;
1758                     ++len;
1759                     pshader_program_dump_ps_param(*pToken, 0);
1760                     ++pToken;
1761                     ++len;
1762                 } else 
1763                     if (curOpcode->opcode == D3DSIO_DEF) {
1764                         TRACE("def c%lu = ", *pToken & 0xFF);
1765                         ++pToken;
1766                         ++len;
1767                         TRACE("%f ,", *(float *)pToken);
1768                         ++pToken;
1769                         ++len;
1770                         TRACE("%f ,", *(float *)pToken);
1771                         ++pToken;
1772                         ++len;
1773                         TRACE("%f ,", *(float *)pToken);
1774                         ++pToken;
1775                         ++len;
1776                         TRACE("%f", *(float *)pToken);
1777                         ++pToken;
1778                         ++len;
1779                 } else {
1780                     TRACE("%s ", curOpcode->name);
1781                     if (curOpcode->num_params > 0) {
1782                         pshader_program_dump_ps_param(*pToken, 0);
1783                         ++pToken;
1784                         ++len;
1785                         for (i = 1; i < curOpcode->num_params; ++i) {
1786                             TRACE(", ");
1787                             pshader_program_dump_ps_param(*pToken, 1);
1788                             ++pToken;
1789                             ++len;
1790                         }
1791                     }
1792                 }
1793                 TRACE("\n");
1794             }
1795         }
1796         This->functionLength = (len + 1) * sizeof(DWORD);
1797     } else {
1798         This->functionLength = 1; /* no Function defined use fixed function vertex processing */
1799     }
1800
1801     /* Generate HW shader in needed */
1802     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1803         TRACE("(%p) : Generating hardware program\n", This);
1804 #if 1
1805         IWineD3DPixelShaderImpl_GenerateProgramArbHW(iface, pFunction);
1806 #endif
1807     }
1808
1809     TRACE("(%p) : Copying the function\n", This);
1810     /* copy the function ... because it will certainly be released by application */
1811     if (NULL != pFunction) {
1812         This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
1813         memcpy((void *)This->function, pFunction, This->functionLength);
1814     } else {
1815         This->function = NULL;
1816     }
1817
1818     /* TODO: Some proper return values for failures */
1819     TRACE("(%p) : Returning D3D_OK\n", This);
1820     return D3D_OK;
1821 }
1822
1823 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1824 {
1825     /*** IUnknown methods ***/
1826     IWineD3DPixelShaderImpl_QueryInterface,
1827     IWineD3DPixelShaderImpl_AddRef,
1828     IWineD3DPixelShaderImpl_Release,
1829     /*** IWineD3DPixelShader methods ***/
1830     IWineD3DPixelShaderImpl_GetParent,
1831     IWineD3DPixelShaderImpl_GetDevice,
1832     IWineD3DPixelShaderImpl_GetFunction,
1833     /* not part of d3d */
1834     IWineD3DPixelShaderImpl_SetFunction
1835 };