wined3d: Modify shader_dump_param() to take into account address token.
[wine] / dlls / wined3d / pixelshader.c
1 /*
2  * shaders implementation
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  * Copyright 2006 Ivan Gyurdiev
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25
26 #include <math.h>
27 #include <stdio.h>
28
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
32
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34
35 #if 0 /* Must not be 1 in cvs version */
36 # define PSTRACE(A) TRACE A
37 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
38 #else
39 # define PSTRACE(A)
40 # define TRACE_VSVECTOR(name)
41 #endif
42
43 #define GLNAME_REQUIRE_GLSL  ((const char *)1)
44 /* *******************************************
45    IWineD3DPixelShader IUnknown parts follow
46    ******************************************* */
47 HRESULT WINAPI IWineD3DPixelShaderImpl_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, LPVOID *ppobj)
48 {
49     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
50     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
51     if (IsEqualGUID(riid, &IID_IUnknown)
52         || IsEqualGUID(riid, &IID_IWineD3DBase)
53         || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
54         || IsEqualGUID(riid, &IID_IWineD3DPixelShader)) {
55         IUnknown_AddRef(iface);
56         *ppobj = This;
57         return S_OK;
58     }
59     *ppobj = NULL;
60     return E_NOINTERFACE;
61 }
62
63 ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) {
64     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
65     TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
66     return InterlockedIncrement(&This->ref);
67 }
68
69 ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
70     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
71     ULONG ref;
72     TRACE("(%p) : Releasing from %ld\n", This, This->ref);
73     ref = InterlockedDecrement(&This->ref);
74     if (ref == 0) {
75         HeapFree(GetProcessHeap(), 0, This);
76     }
77     return ref;
78 }
79
80 /* TODO: At the momeny the function parser is single pass, it achievs this 
81    by passing constants to a couple of functions where they are then modified.
82    At some point the parser need to be made two pass (So that GLSL can be used if it's required by the shader)
83    when happens constants should be worked out in the first pass to tidy up the second pass a bit.
84 */
85
86 /* *******************************************
87    IWineD3DPixelShader IWineD3DPixelShader parts follow
88    ******************************************* */
89
90 HRESULT WINAPI IWineD3DPixelShaderImpl_GetParent(IWineD3DPixelShader *iface, IUnknown** parent){
91     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
92
93     *parent = This->parent;
94     IUnknown_AddRef(*parent);
95     TRACE("(%p) : returning %p\n", This, *parent);
96     return WINED3D_OK;
97 }
98
99 HRESULT WINAPI IWineD3DPixelShaderImpl_GetDevice(IWineD3DPixelShader* iface, IWineD3DDevice **pDevice){
100     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
101     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
102     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
103     TRACE("(%p) returning %p\n", This, *pDevice);
104     return WINED3D_OK;
105 }
106
107
108 HRESULT WINAPI IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader* impl, VOID* pData, UINT* pSizeOfData) {
109   IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)impl;
110   FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
111
112   if (NULL == pData) {
113     *pSizeOfData = This->baseShader.functionLength;
114     return WINED3D_OK;
115   }
116   if (*pSizeOfData < This->baseShader.functionLength) {
117     *pSizeOfData = This->baseShader.functionLength;
118     return WINED3DERR_MOREDATA;
119   }
120   if (NULL == This->baseShader.function) { /* no function defined */
121     TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
122     (*(DWORD **) pData) = NULL;
123   } else {
124     if (This->baseShader.functionLength == 0) {
125
126     }
127     TRACE("(%p) : GetFunction copying to %p\n", This, pData);
128     memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
129   }
130   return WINED3D_OK;
131 }
132
133 /*******************************
134  * pshader functions software VM
135  */
136
137 void pshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
138     d->x = s0->x + s1->x;
139     d->y = s0->y + s1->y;
140     d->z = s0->z + s1->z;
141     d->w = s0->w + s1->w;
142     PSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
143                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
144 }
145
146 void pshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
147     d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
148     PSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
149                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
150 }
151
152 void pshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
153     d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
154     PSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
155         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
156 }
157
158 void pshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
159     d->x = 1.0f;
160     d->y = s0->y * s1->y;
161     d->z = s0->z;
162     d->w = s1->w;
163     PSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
164         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
165 }
166
167 void pshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
168     union {
169         float f;
170         DWORD d;
171     } tmp;
172
173     tmp.f = floorf(s0->w);
174     d->x  = powf(2.0f, tmp.f);
175     d->y  = s0->w - tmp.f;
176     tmp.f = powf(2.0f, s0->w);
177     tmp.d &= 0xFFFFFF00U;
178     d->z  = tmp.f;
179     d->w  = 1.0f;
180     PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
181                     s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
182 }
183
184 void pshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
185     float tmp_f = fabsf(s0->w);
186     d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
187     PSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
188                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
189 }
190
191 void pshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
192     d->x = s0->x * s1->x + s2->x;
193     d->y = s0->y * s1->y + s2->y;
194     d->z = s0->z * s1->z + s2->z;
195     d->w = s0->w * s1->w + s2->w;
196     PSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
197         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));
198 }
199
200 void pshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
201     d->x = (s0->x >= s1->x) ? s0->x : s1->x;
202     d->y = (s0->y >= s1->y) ? s0->y : s1->y;
203     d->z = (s0->z >= s1->z) ? s0->z : s1->z;
204     d->w = (s0->w >= s1->w) ? s0->w : s1->w;
205     PSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
206         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
207 }
208
209 void pshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
210     d->x = (s0->x < s1->x) ? s0->x : s1->x;
211     d->y = (s0->y < s1->y) ? s0->y : s1->y;
212     d->z = (s0->z < s1->z) ? s0->z : s1->z;
213     d->w = (s0->w < s1->w) ? s0->w : s1->w;
214     PSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
215         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
216 }
217
218 void pshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
219     d->x = s0->x;
220     d->y = s0->y;
221     d->z = s0->z;
222     d->w = s0->w;
223     PSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
224         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
225 }
226
227 void pshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
228     d->x = s0->x * s1->x;
229     d->y = s0->y * s1->y;
230     d->z = s0->z * s1->z;
231     d->w = s0->w * s1->w;
232     PSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
233         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
234 }
235
236 void pshader_nop(void) {
237     /* NOPPPP ahhh too easy ;) */
238     PSTRACE(("executing nop\n"));
239 }
240
241 void pshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
242     d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
243     PSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
244         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
245 }
246
247 void pshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
248     float tmp_f = fabsf(s0->w);
249     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);
250     PSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
251         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
252 }
253
254 void pshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
255     d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
256     d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
257     d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
258     d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
259     PSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
260         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
261 }
262
263 void pshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
264     d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
265     d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
266     d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
267     d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
268     PSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
269         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
270 }
271
272 void pshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
273     d->x = s0->x - s1->x;
274     d->y = s0->y - s1->y;
275     d->z = s0->z - s1->z;
276     d->w = s0->w - s1->w;
277     PSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
278         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
279 }
280
281 /**
282  * Version 1.1 specific
283  */
284
285 void pshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
286     d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
287     PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
288         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
289 }
290
291 void pshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
292     float tmp_f = fabsf(s0->w);
293     d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
294     PSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
295         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
296 }
297
298 void pshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
299     d->x = s0->x - floorf(s0->x);
300     d->y = s0->y - floorf(s0->y);
301     d->z = 0.0f;
302     d->w = 1.0f;
303     PSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
304         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
305 }
306
307 typedef FLOAT D3DMATRIX44[4][4];
308 typedef FLOAT D3DMATRIX43[4][3];
309 typedef FLOAT D3DMATRIX34[3][4];
310 typedef FLOAT D3DMATRIX33[3][3];
311 typedef FLOAT D3DMATRIX23[2][3];
312
313 void pshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
314     /*
315     * Buggy CODE: here only if cast not work for copy/paste
316     WINED3DSHADERVECTOR* mat2 = mat1 + 1;
317     WINED3DSHADERVECTOR* mat3 = mat1 + 2;
318     WINED3DSHADERVECTOR* mat4 = mat1 + 3;
319     d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
320     d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
321     d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
322     d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
323     */
324     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
325     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
326     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
327     d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
328     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));
329     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));
330     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));
331     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));
332 }
333
334 void pshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
335     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
336     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
337     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
338     d->w = 1.0f;
339     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));
340     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));
341     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));
342     PSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
343 }
344
345 void pshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
346     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
347     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
348     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
349     d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
350     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));
351     PSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
352     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));
353     PSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
354 }
355
356 void pshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
357     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
358     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
359     d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
360     d->w = 1.0f;
361     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));
362     PSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
363     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));
364     PSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
365 }
366
367 void pshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
368     FIXME("check\n");
369     d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
370     d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
371     d->z = 0.0f;
372     d->w = 1.0f;
373 }
374
375 /**
376  * Version 2.0 specific
377  */
378 void pshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
379     d->x = s0->x * (s1->x - s2->x) + s2->x;
380     d->y = s0->y * (s1->y - s2->y) + s2->y;
381     d->z = s0->z * (s1->z - s2->z) + s2->z;
382     d->w = s0->w * (s1->w - s2->w) + s2->w;
383 }
384
385 void pshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
386     d->x = s0->y * s1->z - s0->z * s1->y;
387     d->y = s0->z * s1->x - s0->x * s1->z;
388     d->z = s0->x * s1->y - s0->y * s1->x;
389     d->w = 0.9f; /* w is undefined, so set it to something safeish */
390
391     PSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
392                 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
393 }
394
395 void pshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
396     d->x = fabsf(s0->x);
397     d->y = fabsf(s0->y);
398     d->z = fabsf(s0->z);
399     d->w = fabsf(s0->w);
400     PSTRACE(("executing abs: s0=(%f, %f, %f, %f)  => d=(%f, %f, %f, %f)\n",
401                 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
402 }
403
404     /* Stubs */
405 void pshader_texcoord(WINED3DSHADERVECTOR* d) {
406     FIXME(" : Stub\n");
407 }
408
409 void pshader_texkill(WINED3DSHADERVECTOR* d) {
410     FIXME(" : Stub\n");
411 }
412
413 void pshader_tex(WINED3DSHADERVECTOR* d) {
414     FIXME(" : Stub\n");
415 }
416 void pshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
417     FIXME(" : Stub\n");
418 }
419
420 void pshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421     FIXME(" : Stub\n");
422 }
423
424 void pshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
425     FIXME(" : Stub\n");
426 }
427
428 void pshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
429     FIXME(" : Stub\n");
430 }
431
432 void pshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
433     FIXME(" : Stub\n");
434 }
435
436 void pshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
437     FIXME(" : Stub\n");
438 }
439
440 void pshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
441     FIXME(" : Stub\n");
442 }
443
444 void pshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
445     FIXME(" : Stub\n");
446 }
447
448 void pshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449     FIXME(" : Stub\n");
450 }
451
452 void pshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
453     FIXME(" : Stub\n");
454 }
455
456 void pshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
457     FIXME(" : Stub\n");
458 }
459
460 void pshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
461     FIXME(" : Stub\n");
462 }
463
464 void pshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
465     FIXME(" : Stub\n");
466 }
467
468 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
469 void pshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
470     FIXME(" : Stub\n");
471 }
472
473 void pshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
474     FIXME(" : Stub\n");
475 }
476
477 void pshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
478     FIXME(" : Stub\n");
479 }
480
481 void pshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
482     FIXME(" : Stub\n");
483 }
484
485 void pshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486     FIXME(" : Stub\n");
487 }
488
489 void pshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
490     FIXME(" : Stub\n");
491 }
492
493 void pshader_texdepth(WINED3DSHADERVECTOR* d) {
494     FIXME(" : Stub\n");
495 }
496
497 void pshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
498     FIXME(" : Stub\n");
499 }
500
501 void pshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
502     FIXME(" : Stub\n");
503 }
504
505 void pshader_call(WINED3DSHADERVECTOR* d) {
506     FIXME(" : Stub\n");
507 }
508
509 void pshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
510     FIXME(" : Stub\n");
511 }
512
513 void pshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514     FIXME(" : Stub\n");
515 }
516
517 void pshader_ret(void) {
518     FIXME(" : Stub\n");
519 }
520
521 void pshader_endloop(void) {
522     FIXME(" : Stub\n");
523 }
524
525 void pshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
526     FIXME(" : Stub\n");
527 }
528
529 void pshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
530     FIXME(" : Stub\n");
531 }
532
533 void pshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
534     FIXME(" : Stub\n");
535 }
536
537 void pshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
538     FIXME(" : Stub\n");
539 }
540
541 void pshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
542      FIXME(" : Stub\n");
543 }
544
545 void pshader_rep(WINED3DSHADERVECTOR* d) {
546     FIXME(" : Stub\n");
547 }
548
549 void pshader_endrep(void) {
550     FIXME(" : Stub\n");
551 }
552
553 void pshader_if(WINED3DSHADERVECTOR* d) {
554     FIXME(" : Stub\n");
555 }
556
557 void pshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
558     FIXME(" : Stub\n");
559 }
560
561 void pshader_else(void) {
562     FIXME(" : Stub\n");
563 }
564
565 void pshader_label(WINED3DSHADERVECTOR* d) {
566     FIXME(" : Stub\n");
567 }
568
569 void pshader_endif(void) {
570     FIXME(" : Stub\n");
571 }
572
573 void pshader_break(void) {
574     FIXME(" : Stub\n");
575 }
576
577 void pshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
578     FIXME(" : Stub\n");
579 }
580
581 void pshader_breakp(WINED3DSHADERVECTOR* d) {
582     FIXME(" : Stub\n");
583 }
584
585 void pshader_defb(WINED3DSHADERVECTOR* d) {
586     FIXME(" : Stub\n");
587 }
588
589 void pshader_defi(WINED3DSHADERVECTOR* d) {
590     FIXME(" : Stub\n");
591 }
592
593 void pshader_dp2add(WINED3DSHADERVECTOR* d) {
594     FIXME(" : Stub\n");
595 }
596
597 void pshader_dsx(WINED3DSHADERVECTOR* d) {
598     FIXME(" : Stub\n");
599 }
600
601 void pshader_dsy(WINED3DSHADERVECTOR* d) {
602     FIXME(" : Stub\n");
603 }
604
605 void pshader_texldd(WINED3DSHADERVECTOR* d) {
606     FIXME(" : Stub\n");
607 }
608
609 void pshader_setp(WINED3DSHADERVECTOR* d) {
610     FIXME(" : Stub\n");
611 }
612
613 void pshader_texldl(WINED3DSHADERVECTOR* d) {
614     FIXME(" : Stub\n");
615 }
616
617 /* Prototype */
618 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
619 void pshader_hw_tex(SHADER_OPCODE_ARG* arg);
620 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg);
621 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg);
622 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg);
623 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg);
624 void pshader_hw_def(SHADER_OPCODE_ARG* arg);
625 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg);
626 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg);
627 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg);
628 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg);
629 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg);
630 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg);
631
632 /**
633  * log, exp, frc, m*x* seems to be macros ins ... to see
634  */
635 CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
636
637     /* Arithmethic */
638     {D3DSIO_NOP,  "nop", "NOP", 0, pshader_nop, pshader_hw_map2gl, NULL, 0, 0},
639     {D3DSIO_MOV,  "mov", "MOV", 2, pshader_mov, pshader_hw_map2gl, NULL, 0, 0},
640     {D3DSIO_ADD,  "add", "ADD", 3, pshader_add, pshader_hw_map2gl, NULL, 0, 0},
641     {D3DSIO_SUB,  "sub", "SUB", 3, pshader_sub, pshader_hw_map2gl, NULL, 0, 0},
642     {D3DSIO_MAD,  "mad", "MAD", 4, pshader_mad, pshader_hw_map2gl, NULL, 0, 0},
643     {D3DSIO_MUL,  "mul", "MUL", 3, pshader_mul, pshader_hw_map2gl, NULL, 0, 0},
644     {D3DSIO_RCP,  "rcp", "RCP",  2, pshader_rcp, pshader_hw_map2gl, NULL, 0, 0},
645     {D3DSIO_RSQ,  "rsq",  "RSQ", 2, pshader_rsq, pshader_hw_map2gl, NULL, 0, 0},
646     {D3DSIO_DP3,  "dp3",  "DP3", 3, pshader_dp3, pshader_hw_map2gl, NULL, 0, 0},
647     {D3DSIO_DP4,  "dp4",  "DP4", 3, pshader_dp4, pshader_hw_map2gl, NULL, 0, 0},
648     {D3DSIO_MIN,  "min",  "MIN", 3, pshader_min, pshader_hw_map2gl, NULL, 0, 0},
649     {D3DSIO_MAX,  "max",  "MAX", 3, pshader_max, pshader_hw_map2gl, NULL, 0, 0},
650     {D3DSIO_SLT,  "slt",  "SLT", 3, pshader_slt, pshader_hw_map2gl, NULL, 0, 0},
651     {D3DSIO_SGE,  "sge",  "SGE", 3, pshader_sge, pshader_hw_map2gl, NULL, 0, 0},
652     {D3DSIO_ABS,  "abs",  "ABS", 2, pshader_abs, pshader_hw_map2gl, NULL, 0, 0},
653     {D3DSIO_EXP,  "exp",  "EX2", 2, pshader_exp, pshader_hw_map2gl, NULL, 0, 0},
654     {D3DSIO_LOG,  "log",  "LG2", 2, pshader_log, pshader_hw_map2gl, NULL, 0, 0},
655     {D3DSIO_EXPP, "expp", "EXP", 2, pshader_expp, pshader_hw_map2gl, NULL, 0, 0},
656     {D3DSIO_LOGP, "logp", "LOG", 2, pshader_logp, pshader_hw_map2gl, NULL, 0, 0},
657     {D3DSIO_DST,  "dst",  "DST", 3, pshader_dst, pshader_hw_map2gl, NULL, 0, 0},
658     {D3DSIO_LRP,  "lrp",  "LRP", 4, pshader_lrp, pshader_hw_map2gl, NULL, 0, 0},
659     {D3DSIO_FRC,  "frc",  "FRC", 2, pshader_frc, pshader_hw_map2gl, NULL, 0, 0},
660     {D3DSIO_CND,  "cnd",  GLNAME_REQUIRE_GLSL, 4, pshader_cnd, NULL, NULL, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
661     {D3DSIO_CMP,  "cmp",  GLNAME_REQUIRE_GLSL, 4, pshader_cmp, NULL, NULL, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
662     {D3DSIO_POW,  "pow",  "POW", 3, pshader_pow,  NULL, NULL, 0, 0},
663     {D3DSIO_CRS,  "crs",  "XPS", 3, pshader_crs,  NULL, NULL, 0, 0},
664     /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
665         DP3 tmp , vec, vec;
666         RSQ tmp, tmp.x;
667         MUL vec.xyz, vec, tmp;
668     but I think this is better because it accounts for w properly.
669         DP3 tmp , vec, vec;
670         RSQ tmp, tmp.x;
671         MUL vec, vec, tmp;
672
673     */
674     {D3DSIO_NRM,      "nrm",      NULL,   2, pshader_nrm,     NULL, NULL, 0, 0},
675     {D3DSIO_SINCOS,   "sincos",   NULL,   4, pshader_sincos2, NULL, NULL, D3DPS_VERSION(2,0), D3DPS_VERSION(2,0)},
676     {D3DSIO_SINCOS,   "sincos",   NULL,   2, pshader_sincos3, NULL, NULL, D3DPS_VERSION(3,0), -1},
677     /* TODO: dp2add can be made out of multiple instuctions */
678     {D3DSIO_DP2ADD,   "dp2add",   GLNAME_REQUIRE_GLSL,  2, pshader_dp2add,  NULL, NULL, 0, 0},
679
680     /* Matrix */
681     {D3DSIO_M4x4, "m4x4", "undefined", 3, pshader_m4x4, NULL, NULL, 0, 0},
682     {D3DSIO_M4x3, "m4x3", "undefined", 3, pshader_m4x3, NULL, NULL, 0, 0},
683     {D3DSIO_M3x4, "m3x4", "undefined", 3, pshader_m3x4, NULL, NULL, 0, 0},
684     {D3DSIO_M3x3, "m3x3", "undefined", 3, pshader_m3x3, NULL, NULL, 0, 0},
685     {D3DSIO_M3x2, "m3x2", "undefined", 3, pshader_m3x2, NULL, NULL, 0, 0},
686
687     /* Register declarations */
688     {D3DSIO_DCL,      "dcl",      NULL,   2, pshader_dcl,     NULL, NULL, 0, 0},
689
690     /* Flow control - requires GLSL or software shaders */
691     {D3DSIO_REP ,     "rep",      GLNAME_REQUIRE_GLSL,   1, pshader_rep,     NULL, NULL, 0, 0},
692     {D3DSIO_ENDREP,   "endrep",   GLNAME_REQUIRE_GLSL,   0, pshader_endrep,  NULL, NULL, 0, 0},
693     {D3DSIO_IF,       "if",       GLNAME_REQUIRE_GLSL,   1, pshader_if,      NULL, NULL, 0, 0},
694     {D3DSIO_IFC,      "ifc",      GLNAME_REQUIRE_GLSL,   2, pshader_ifc,     NULL, NULL, 0, 0},
695     {D3DSIO_ELSE,     "else",     GLNAME_REQUIRE_GLSL,   0, pshader_else,    NULL, NULL, 0, 0},
696     {D3DSIO_ENDIF,    "endif",    GLNAME_REQUIRE_GLSL,   0, pshader_endif,   NULL, NULL, 0, 0},
697     {D3DSIO_BREAK,    "break",    GLNAME_REQUIRE_GLSL,   0, pshader_break,   NULL, NULL, 0, 0},
698     {D3DSIO_BREAKC,   "breakc",   GLNAME_REQUIRE_GLSL,   2, pshader_breakc,  NULL, NULL, 0, 0},
699     {D3DSIO_BREAKP,   "breakp",   GLNAME_REQUIRE_GLSL,   1, pshader_breakp,  NULL, NULL, 0, 0},
700     {D3DSIO_CALL,     "call",     GLNAME_REQUIRE_GLSL,   1, pshader_call,    NULL, NULL, 0, 0},
701     {D3DSIO_CALLNZ,   "callnz",   GLNAME_REQUIRE_GLSL,   2, pshader_callnz,  NULL, NULL, 0, 0},
702     {D3DSIO_LOOP,     "loop",     GLNAME_REQUIRE_GLSL,   2, pshader_loop,    NULL, NULL, 0, 0},
703     {D3DSIO_RET,      "ret",      GLNAME_REQUIRE_GLSL,   0, pshader_ret,     NULL, NULL, 0, 0},
704     {D3DSIO_ENDLOOP,  "endloop",  GLNAME_REQUIRE_GLSL,   0, pshader_endloop, NULL, NULL, 0, 0},
705     {D3DSIO_LABEL,    "label",    GLNAME_REQUIRE_GLSL,   1, pshader_label,   NULL, NULL, 0, 0},
706
707     /* Constant definitions */
708     {D3DSIO_DEF,      "def",      "undefined",           5, pshader_def,     pshader_hw_def, NULL, 0, 0},
709     {D3DSIO_DEFB,     "defb",     GLNAME_REQUIRE_GLSL,   2, pshader_defb,    NULL, NULL, 0, 0},
710     {D3DSIO_DEFI,     "defi",     GLNAME_REQUIRE_GLSL,   2, pshader_defi,    NULL, NULL, 0, 0},
711
712     /* Texture */
713     {D3DSIO_TEXCOORD, "texcoord", "undefined",   1, pshader_texcoord,    pshader_hw_texcoord, NULL, 0, D3DPS_VERSION(1,3)},
714     {D3DSIO_TEXCOORD, "texcrd",   "undefined",   2, pshader_texcoord,    pshader_hw_texcoord, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
715     {D3DSIO_TEXKILL,  "texkill",  "KIL",         1, pshader_texkill,     pshader_hw_map2gl, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
716     {D3DSIO_TEX,      "tex",      "undefined",   1, pshader_tex,         pshader_hw_tex, NULL, 0, D3DPS_VERSION(1,3)},
717     {D3DSIO_TEX,      "texld",    "undefined",   2, pshader_texld,       pshader_hw_tex, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
718     {D3DSIO_TEX,      "texld",    "undefined",   3, pshader_texld,       pshader_hw_tex, NULL, D3DPS_VERSION(2,0), -1},
719     {D3DSIO_TEXBEM,   "texbem",   "undefined",   2, pshader_texbem,      pshader_hw_texbem, NULL, 0, D3DPS_VERSION(1,3)},
720     {D3DSIO_TEXBEML,  "texbeml",  GLNAME_REQUIRE_GLSL,   2, pshader_texbeml, NULL, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
721     {D3DSIO_TEXREG2AR,"texreg2ar","undefined",   2, pshader_texreg2ar,   pshader_hw_texreg2ar, NULL, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
722     {D3DSIO_TEXREG2GB,"texreg2gb","undefined",   2, pshader_texreg2gb,   pshader_hw_texreg2gb, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
723     {D3DSIO_TEXREG2RGB,   "texreg2rgb",   GLNAME_REQUIRE_GLSL,   2, pshader_texreg2rgb,  NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
724     {D3DSIO_TEXM3x2PAD,   "texm3x2pad",   "undefined",   2, pshader_texm3x2pad,   pshader_hw_texm3x2pad, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
725     {D3DSIO_TEXM3x2TEX,   "texm3x2tex",   "undefined",   2, pshader_texm3x2tex,   pshader_hw_texm3x2tex, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
726     {D3DSIO_TEXM3x3PAD,   "texm3x3pad",   "undefined",   2, pshader_texm3x3pad,   pshader_hw_texm3x3pad, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
727     {D3DSIO_TEXM3x3DIFF,  "texm3x3diff",  GLNAME_REQUIRE_GLSL,   2, pshader_texm3x3diff,  NULL, NULL, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
728     {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  "undefined",   3, pshader_texm3x3spec,  pshader_hw_texm3x3spec, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
729     {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe",  "undefined",   2, pshader_texm3x3vspec, pshader_hw_texm3x3vspec, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
730     {D3DSIO_TEXM3x3TEX,   "texm3x3tex",   "undefined",   2, pshader_texm3x3tex,   pshader_hw_texm3x3tex, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
731     {D3DSIO_TEXDP3TEX,    "texdp3tex",    GLNAME_REQUIRE_GLSL,   2, pshader_texdp3tex,   NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
732     {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL,   2, pshader_texm3x2depth, NULL, NULL, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
733     {D3DSIO_TEXDP3,   "texdp3",   GLNAME_REQUIRE_GLSL,  2, pshader_texdp3,   NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
734     {D3DSIO_TEXM3x3,  "texm3x3",  GLNAME_REQUIRE_GLSL,  2, pshader_texm3x3,  NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
735     {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL,  1, pshader_texdepth, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
736     {D3DSIO_BEM,      "bem",      GLNAME_REQUIRE_GLSL,  3, pshader_bem,      NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
737     /* TODO: dp2add can be made out of multiple instuctions */
738     {D3DSIO_DSX,      "dsx",      GLNAME_REQUIRE_GLSL,  2, pshader_dsx,     NULL, NULL, 0, 0},
739     {D3DSIO_DSY,      "dsy",      GLNAME_REQUIRE_GLSL,  2, pshader_dsy,     NULL, NULL, 0, 0},
740     {D3DSIO_TEXLDD,   "texldd",   GLNAME_REQUIRE_GLSL,  2, pshader_texldd,  NULL, NULL, 0, 0},
741     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL,  2, pshader_setp,    NULL, NULL, 0, 0},
742     {D3DSIO_TEXLDL,   "texdl",    GLNAME_REQUIRE_GLSL,  2, pshader_texldl,  NULL, NULL, 0, 0},
743     {D3DSIO_PHASE,    "phase",    GLNAME_REQUIRE_GLSL,  0, pshader_nop,     NULL, NULL, 0, 0},
744     {0,               NULL,       NULL,   0, NULL,            NULL, 0, 0}
745 };
746
747 inline static void get_register_name(const DWORD param, char* regstr, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
748     static const char* rastout_reg_names[] = { "oC0", "oC1", "oC2", "oC3", "oDepth" };
749
750     DWORD reg = param & D3DSP_REGNUM_MASK;
751     DWORD regtype = shader_get_regtype(param);
752
753     switch (regtype) {
754     case D3DSPR_TEMP:
755         sprintf(regstr, "R%lu", reg);
756     break;
757     case D3DSPR_INPUT:
758         if (reg==0) {
759             strcpy(regstr, "fragment.color.primary");
760         } else {
761             strcpy(regstr, "fragment.color.secondary");
762         }
763     break;
764     case D3DSPR_CONST:
765         if (constants[reg])
766             sprintf(regstr, "C%lu", reg);
767         else
768             sprintf(regstr, "program.env[%lu]", reg);
769     break;
770     case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
771         sprintf(regstr,"T%lu", reg);
772     break;
773     case D3DSPR_RASTOUT:
774         sprintf(regstr, "%s", rastout_reg_names[reg]);
775     break;
776     case D3DSPR_ATTROUT:
777         sprintf(regstr, "oD[%lu]", reg);
778     break;
779     case D3DSPR_TEXCRDOUT:
780         sprintf(regstr, "oT[%lu]", reg);
781     break;
782     default:
783         FIXME("Unhandled register name Type(%ld)\n", regtype);
784     break;
785     }
786 }
787
788 inline static void get_write_mask(const DWORD output_reg, char *write_mask) {
789     *write_mask = 0;
790     if ((output_reg & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
791         strcat(write_mask, ".");
792         if (output_reg & D3DSP_WRITEMASK_0) strcat(write_mask, "r");
793         if (output_reg & D3DSP_WRITEMASK_1) strcat(write_mask, "g");
794         if (output_reg & D3DSP_WRITEMASK_2) strcat(write_mask, "b");
795         if (output_reg & D3DSP_WRITEMASK_3) strcat(write_mask, "a");
796     }
797 }
798
799 inline static void get_input_register_swizzle(const DWORD instr, char *swzstring) {
800     static const char swizzle_reg_chars[] = "rgba";
801     DWORD swizzle = (instr & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
802     DWORD swizzle_x = swizzle & 0x03;
803     DWORD swizzle_y = (swizzle >> 2) & 0x03;
804     DWORD swizzle_z = (swizzle >> 4) & 0x03;
805     DWORD swizzle_w = (swizzle >> 6) & 0x03;
806     /**
807      * swizzle bits fields:
808      *  WWZZYYXX
809      */
810     *swzstring = 0;
811     if ((D3DSP_NOSWIZZLE >> D3DSP_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
812         if (swizzle_x == swizzle_y && 
813         swizzle_x == swizzle_z && 
814         swizzle_x == swizzle_w) {
815             sprintf(swzstring, ".%c", swizzle_reg_chars[swizzle_x]);
816         } else {
817             sprintf(swzstring, ".%c%c%c%c", 
818                 swizzle_reg_chars[swizzle_x], 
819                 swizzle_reg_chars[swizzle_y], 
820                 swizzle_reg_chars[swizzle_z], 
821                 swizzle_reg_chars[swizzle_w]);
822         }
823     }
824 }
825
826 static const char* shift_tab[] = {
827     "dummy",     /*  0 (none) */ 
828     "coefmul.x", /*  1 (x2)   */ 
829     "coefmul.y", /*  2 (x4)   */ 
830     "coefmul.z", /*  3 (x8)   */ 
831     "coefmul.w", /*  4 (x16)  */ 
832     "dummy",     /*  5 (x32)  */ 
833     "dummy",     /*  6 (x64)  */ 
834     "dummy",     /*  7 (x128) */ 
835     "dummy",     /*  8 (d256) */ 
836     "dummy",     /*  9 (d128) */ 
837     "dummy",     /* 10 (d64)  */ 
838     "dummy",     /* 11 (d32)  */ 
839     "coefdiv.w", /* 12 (d16)  */ 
840     "coefdiv.z", /* 13 (d8)   */ 
841     "coefdiv.y", /* 14 (d4)   */ 
842     "coefdiv.x"  /* 15 (d2)   */ 
843 };
844
845 inline static void gen_output_modifier_line(int saturate, char *write_mask, int shift, char *regstr, char* line) {
846     /* Generate a line that does the output modifier computation */
847     sprintf(line, "MUL%s %s%s, %s, %s;", saturate ? "_SAT" : "", regstr, write_mask, regstr, shift_tab[shift]);
848 }
849
850 inline static int gen_input_modifier_line(const DWORD instr, int tmpreg, char *outregstr, char *line, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
851     /* Generate a line that does the input modifier computation and return the input register to use */
852     static char regstr[256];
853     static char tmpline[256];
854     int insert_line;
855
856     /* Assume a new line will be added */
857     insert_line = 1;
858
859     /* Get register name */
860     get_register_name(instr, regstr, constants);
861
862     TRACE(" Register name %s\n", regstr);
863     switch (instr & D3DSP_SRCMOD_MASK) {
864     case D3DSPSM_NONE:
865         strcpy(outregstr, regstr);
866         insert_line = 0;
867         break;
868     case D3DSPSM_NEG:
869         sprintf(outregstr, "-%s", regstr);
870         insert_line = 0;
871         break;
872     case D3DSPSM_BIAS:
873         sprintf(line, "ADD T%c, %s, -coefdiv.x;", 'A' + tmpreg, regstr);
874         break;
875     case D3DSPSM_BIASNEG:
876         sprintf(line, "ADD T%c, -%s, coefdiv.x;", 'A' + tmpreg, regstr);
877         break;
878     case D3DSPSM_SIGN:
879         sprintf(line, "MAD T%c, %s, coefmul.x, -one.x;", 'A' + tmpreg, regstr);
880         break;
881     case D3DSPSM_SIGNNEG:
882         sprintf(line, "MAD T%c, %s, -coefmul.x, one.x;", 'A' + tmpreg, regstr);
883         break;
884     case D3DSPSM_COMP:
885         sprintf(line, "SUB T%c, one.x, %s;", 'A' + tmpreg, regstr);
886         break;
887     case D3DSPSM_X2:
888         sprintf(line, "ADD T%c, %s, %s;", 'A' + tmpreg, regstr, regstr);
889         break;
890     case D3DSPSM_X2NEG:
891         sprintf(line, "ADD T%c, -%s, -%s;", 'A' + tmpreg, regstr, regstr);
892         break;
893     case D3DSPSM_DZ:
894         sprintf(line, "RCP T%c, %s.z;", 'A' + tmpreg, regstr);
895         sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
896         strcat(line, "\n"); /* Hack */
897         strcat(line, tmpline);
898         break;
899     case D3DSPSM_DW:
900         sprintf(line, "RCP T%c, %s.w;", 'A' + tmpreg, regstr);
901         sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
902         strcat(line, "\n"); /* Hack */
903         strcat(line, tmpline);
904         break;
905     default:
906         strcpy(outregstr, regstr);
907         insert_line = 0;
908     }
909
910     if (insert_line) {
911         /* Substitute the register name */
912         sprintf(outregstr, "T%c", 'A' + tmpreg);
913     }
914
915     return insert_line;
916 }
917
918 void pshader_set_version(
919       IWineD3DPixelShaderImpl *This, 
920       DWORD version) {
921
922       DWORD major = (version >> 8) & 0x0F;
923       DWORD minor = version & 0x0F;
924
925       This->baseShader.hex_version = version;
926       This->baseShader.version = major * 10 + minor;
927       TRACE("ps_%lu_%lu\n", major, minor);
928
929       This->baseShader.limits.address = 0;
930
931       switch (This->baseShader.version) {
932           case 10:
933           case 11:
934           case 12:
935           case 13: This->baseShader.limits.temporary = 2;
936                    This->baseShader.limits.constant_float = 8;
937                    This->baseShader.limits.constant_int = 0;
938                    This->baseShader.limits.constant_bool = 0;
939                    This->baseShader.limits.texture = 4;
940                    break;
941
942           case 14: This->baseShader.limits.temporary = 6;
943                    This->baseShader.limits.constant_float = 8;
944                    This->baseShader.limits.constant_int = 0;
945                    This->baseShader.limits.constant_bool = 0;
946                    This->baseShader.limits.texture = 6;
947                    break;
948                
949           /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */ 
950           case 20: This->baseShader.limits.temporary = 32;
951                    This->baseShader.limits.constant_float = 32;
952                    This->baseShader.limits.constant_int = 16;
953                    This->baseShader.limits.constant_bool = 16;
954                    This->baseShader.limits.texture = 8;
955                    break;
956
957           case 30: This->baseShader.limits.temporary = 32;
958                    This->baseShader.limits.constant_float = 224;
959                    This->baseShader.limits.constant_int = 16;
960                    This->baseShader.limits.constant_bool = 16;
961                    This->baseShader.limits.texture = 0;
962                    break;
963
964           default: This->baseShader.limits.temporary = 32;
965                    This->baseShader.limits.constant_float = 8;
966                    This->baseShader.limits.constant_int = 0;
967                    This->baseShader.limits.constant_bool = 0;
968                    This->baseShader.limits.texture = 8;
969                    FIXME("Unrecognized pixel shader version %lx!\n", version);
970       }
971 }
972
973 /* Map the opcode 1-to-1 to the GL code */
974 /* FIXME: fix CMP/CND, get rid of this switch */
975 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
976
977      IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
978      CONST SHADER_OPCODE* curOpcode = arg->opcode;
979      SHADER_BUFFER* buffer = arg->buffer;
980      DWORD dst = arg->dst;
981      DWORD* src = arg->src;
982
983      unsigned int i;
984      char tmpLine[256];
985
986      /* Output token related */
987      char output_rname[256];
988      char output_wmask[20];
989      BOOL saturate = FALSE;
990      BOOL centroid = FALSE;
991      BOOL partialprecision = FALSE;
992      DWORD shift;
993
994      TRACE("Appending glname %s to tmpLine\n", curOpcode->glname);
995      strcpy(tmpLine, curOpcode->glname);
996
997      /* Process modifiers */
998      if (0 != (dst & D3DSP_DSTMOD_MASK)) {
999          DWORD mask = dst & D3DSP_DSTMOD_MASK;
1000
1001          saturate = mask & D3DSPDM_SATURATE;
1002          centroid = mask & D3DSPDM_MSAMPCENTROID;
1003          partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1004          mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1005
1006          if (mask)
1007             FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1008
1009          if (centroid)
1010              FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1011      }
1012      shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1013
1014       /* Generate input and output registers */
1015       if (curOpcode->num_params > 0) {
1016           char regs[5][50];
1017           char operands[4][100];
1018           char swzstring[20];
1019           char tmpOp[256];
1020
1021           /* Generate lines that handle input modifier computation */
1022           for (i = 1; i < curOpcode->num_params; ++i) {
1023               TRACE("(%p) : Param %u token %lx\n", This, i, src[i - 1]);
1024               if (gen_input_modifier_line(src[i - 1], i - 1, regs[i - 1], tmpOp, This->constants))
1025                   shader_addline(buffer, tmpOp);
1026           }
1027
1028           /* Handle output register */
1029           get_register_name(dst, output_rname, This->constants);
1030           strcpy(operands[0], output_rname);
1031           get_write_mask(dst, output_wmask);
1032           strcat(operands[0], output_wmask);
1033
1034           /* This function works because of side effects from  gen_input_modifier_line */
1035           /* Handle input registers */
1036           for (i = 1; i < curOpcode->num_params; ++i) {
1037               TRACE("(%p) : Regs = %s\n", This, regs[i - 1]);
1038               strcpy(operands[i], regs[i - 1]);
1039               get_input_register_swizzle(src[i - 1], swzstring);
1040               strcat(operands[i], swzstring);
1041           }
1042
1043           switch(curOpcode->opcode) {
1044               case D3DSIO_CMP:
1045                   sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""),
1046                       operands[0], operands[1], operands[3], operands[2]);
1047               break;
1048             case D3DSIO_CND:
1049                   shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", operands[1]);
1050                   sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""),
1051                       operands[0], operands[2], operands[3]);
1052               break;
1053
1054               default:
1055                   if (saturate && (shift == 0))
1056                       strcat(tmpLine, "_SAT");
1057                   strcat(tmpLine, " ");
1058                   strcat(tmpLine, operands[0]);
1059                   for (i = 1; i < curOpcode->num_params; i++) {
1060                       strcat(tmpLine, ", ");
1061                       strcat(tmpLine, operands[i]);
1062                   }
1063                   strcat(tmpLine,";\n");
1064           }
1065           shader_addline(buffer, tmpLine);
1066
1067           /* A shift requires another line. */
1068           if (shift != 0) {
1069               gen_output_modifier_line(saturate, output_wmask, shift, output_rname, tmpLine);
1070               shader_addline(buffer, tmpLine);
1071           }
1072       }
1073 }
1074
1075 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1076
1077     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1078     DWORD dst = arg->dst;
1079     DWORD* src = arg->src;
1080     SHADER_BUFFER* buffer = arg->buffer;
1081     DWORD version = This->baseShader.version;
1082    
1083     char tmpLine[256];
1084     char reg_dest[40];
1085     char reg_coord[40];
1086     char reg_coord_swz[20] = "";
1087     DWORD reg_dest_code;
1088     DWORD reg_sampler_code;
1089
1090     /* All versions have a destination register */
1091     reg_dest_code = dst & D3DSP_REGNUM_MASK;
1092     get_register_name(dst, reg_dest, This->constants);
1093
1094     /* 1.0-1.3: Use destination register as coordinate source. No modifiers.
1095        1.4: Use provided coordinate source register. _dw, _dz, swizzle allowed.
1096        2.0+: Use provided coordinate source register. No modifiers.
1097        3.0+: Use provided coordinate source register. Swizzle allowed */
1098    if (version < 14)
1099       strcpy(reg_coord, reg_dest);
1100    else if (version == 14) {
1101       if (gen_input_modifier_line(src[0], 0, reg_coord, tmpLine, This->constants))
1102          shader_addline(buffer, tmpLine);
1103       get_input_register_swizzle(src[0], reg_coord_swz);
1104    }
1105    else if (version > 14 && version < 30)
1106       get_register_name(src[0], reg_coord, This->constants);
1107    else if (version >= 30) {
1108       get_input_register_swizzle(src[0], reg_coord_swz);
1109       get_register_name(src[0], reg_coord, This->constants);
1110    }
1111
1112   /* 1.0-1.4: Use destination register number as texture code.
1113      2.0+: Use provided sampler number as texure code. */
1114   if (version < 20)
1115      reg_sampler_code = reg_dest_code;
1116   else 
1117      reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1118
1119   shader_addline(buffer, "TEX %s, %s%s, texture[%lu], 2D;\n",
1120       reg_dest, reg_coord, reg_coord_swz, reg_sampler_code);
1121 }
1122
1123 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1124
1125     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1126     DWORD dst = arg->dst;
1127     DWORD* src = arg->src;
1128     SHADER_BUFFER* buffer = arg->buffer;
1129     DWORD version = This->baseShader.version;
1130
1131     char tmp[20];
1132     get_write_mask(dst, tmp);
1133     if (version != 14) {
1134         DWORD reg = dst & D3DSP_REGNUM_MASK;
1135         shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1136     } else {
1137         DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1138         DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1139         shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1140    }
1141 }
1142
1143 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1144
1145      SHADER_BUFFER* buffer = arg->buffer;
1146  
1147      DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1148      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1149      shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1150      shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1151      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1152 }
1153
1154 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1155  
1156      SHADER_BUFFER* buffer = arg->buffer;
1157     
1158      DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1159      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1160      shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1161      shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1162      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1163 }
1164
1165 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1166
1167      SHADER_BUFFER* buffer = arg->buffer;
1168  
1169      DWORD reg1 = arg->dst  & D3DSP_REGNUM_MASK;
1170      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1171
1172      /* FIXME: Should apply the BUMPMAPENV matrix */
1173      shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1174      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1175 }
1176
1177 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1178     
1179     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1180     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1181     SHADER_BUFFER* buffer = arg->buffer;
1182     
1183     shader_addline(buffer, 
1184               "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1185               *((float*) (arg->src + 0)),
1186               *((float*) (arg->src + 1)),
1187               *((float*) (arg->src + 2)),
1188               *((float*) (arg->src + 3)) );
1189
1190     shader->constants[reg] = 1;
1191 }
1192
1193 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1194
1195     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1196     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1197     SHADER_BUFFER* buffer = arg->buffer;
1198     char tmpLine[256];
1199     char buf[50];
1200
1201     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1202         shader_addline(buffer, tmpLine);
1203     shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, buf);
1204 }
1205
1206 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1207
1208     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1209     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1210     SHADER_BUFFER* buffer = arg->buffer;
1211     char tmpLine[256];
1212     char buf[50];
1213
1214     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1215         shader_addline(buffer, tmpLine);
1216     shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, buf);
1217     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1218 }
1219
1220 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1221
1222     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1223     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1224     SHADER_BUFFER* buffer = arg->buffer;
1225     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1226     char tmpLine[256];
1227     char buf[50];
1228
1229     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1230         shader_addline(buffer, tmpLine);
1231     shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, buf);
1232     current_state.texcoord_w[current_state.current_row++] = reg;
1233 }
1234
1235 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1236
1237     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1238     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1239     SHADER_BUFFER* buffer = arg->buffer;
1240     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1241     char tmpLine[256];
1242     char buf[50];
1243
1244     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1245         shader_addline(buffer, tmpLine);
1246     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1247
1248     /* Cubemap textures will be more used than 3D ones. */
1249     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1250     current_state.current_row = 0;
1251 }
1252
1253 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1254
1255     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1256     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1257     SHADER_BUFFER* buffer = arg->buffer;
1258     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1259     char tmpLine[256];
1260     char buf[50];
1261
1262     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1263         shader_addline(buffer, tmpLine);
1264     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1265
1266     /* Construct the eye-ray vector from w coordinates */
1267     shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1268     shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1269     shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1270
1271     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1272     shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1273     shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1274     shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1275
1276     /* Cubemap textures will be more used than 3D ones. */
1277     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1278     current_state.current_row = 0;
1279 }
1280
1281 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1282
1283     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1284     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1285     DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1286     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1287     SHADER_BUFFER* buffer = arg->buffer;
1288     char tmpLine[256];
1289     char buf[50];
1290
1291     if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants)) 
1292         shader_addline(buffer, tmpLine);
1293     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1294
1295     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1296     shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1297     shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1298     shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1299
1300     /* Cubemap textures will be more used than 3D ones. */
1301     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1302     current_state.current_row = 0;
1303 }
1304
1305 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1306     or GLSL and send it to the card */
1307 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1308     IWineD3DPixelShader *iface,
1309     CONST DWORD *pFunction) {
1310
1311     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1312     SHADER_BUFFER buffer;
1313
1314 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1315         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1316     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1317         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1318         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1319         This->fixupVertexBufferSize = PGMSIZE;
1320         This->fixupVertexBuffer[0] = 0;
1321     }
1322     buffer.buffer = This->device->fixupVertexBuffer;
1323 #else
1324     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
1325 #endif
1326     buffer.bsize = 0;
1327     buffer.lineNo = 0;
1328
1329     /* TODO: Optionally, generate the GLSL shader instead */
1330     if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1331         /*  Create the hw ARB shader */
1332         shader_addline(&buffer, "!!ARBfp1.0\n");
1333
1334         shader_addline(&buffer, "TEMP TMP;\n");     /* Used in matrix ops */
1335         shader_addline(&buffer, "TEMP TMP2;\n");    /* Used in matrix ops */
1336         shader_addline(&buffer, "TEMP TA;\n");      /* Used for modifiers */
1337         shader_addline(&buffer, "TEMP TB;\n");      /* Used for modifiers */
1338         shader_addline(&buffer, "TEMP TC;\n");      /* Used for modifiers */
1339         shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1340         shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1341         shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1342
1343         /** Call the base shader generation routine to generate most 
1344             of the pixel shader string for us */
1345         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1346
1347         /*FIXME: This next line isn't valid for certain pixel shader versions */
1348         shader_addline(&buffer, "MOV result.color, R0;\n");
1349         shader_addline(&buffer, "END\n\0"); 
1350
1351         /* TODO: change to resource.glObjectHandle or something like that */
1352         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1353
1354         TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1355         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1356
1357         TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1358         /* Create the program and check for errors */
1359         GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1360             buffer.bsize, buffer.buffer));
1361
1362         if (glGetError() == GL_INVALID_OPERATION) {
1363             GLint errPos;
1364             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1365             FIXME("HW PixelShader Error at position %d: %s\n",
1366                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1367             This->baseShader.prgId = -1;
1368         }
1369     }
1370
1371 #if 1 /* if were using the data buffer of device then we don't need to free it */
1372   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1373 #endif
1374 }
1375
1376 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1377     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1378     const DWORD* pToken = pFunction;
1379     const SHADER_OPCODE *curOpcode = NULL;
1380     DWORD opcode_token;
1381     DWORD len = 0;
1382     DWORD i;
1383     TRACE("(%p) : Parsing programme\n", This);
1384
1385     if (NULL != pToken) {
1386         while (D3DPS_END() != *pToken) {
1387             if (shader_is_pshader_version(*pToken)) { /** version */
1388                 pshader_set_version(This, *pToken);
1389                 ++pToken;
1390                 ++len;
1391                 continue;
1392             }
1393             if (shader_is_comment(*pToken)) { /** comment */
1394                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1395                 ++pToken;
1396                 TRACE("//%s\n", (char*)pToken);
1397                 pToken += comment_len;
1398                 len += comment_len + 1;
1399                 continue;
1400             }
1401             if (!This->baseShader.version) {
1402                 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1403             }
1404             opcode_token = *pToken++;
1405             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1406             len++;
1407             if (NULL == curOpcode) {
1408                 int tokens_read;
1409
1410                 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1411                 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1412                 pToken += tokens_read;
1413                 len += tokens_read;
1414
1415             } else {
1416                 if (curOpcode->opcode == D3DSIO_DCL) {
1417                     DWORD usage = *pToken;
1418                     DWORD param = *(pToken + 1);
1419                     DWORD regtype = shader_get_regtype(param);
1420
1421                     /* Only print extended declaration for samplers or 3.0 input registers */
1422                     if (regtype == D3DSPR_SAMPLER ||
1423                         (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1424                          shader_program_dump_decl_usage(usage, param);
1425                     else
1426                          TRACE("dcl");
1427
1428                     shader_dump_ins_modifiers(param);
1429                     TRACE(" ");
1430                     shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1431                     pToken += 2;
1432                     len += 2;
1433
1434                 } else 
1435                     if (curOpcode->opcode == D3DSIO_DEF) {
1436                         TRACE("def c%lu = ", *pToken & 0xFF);
1437                         ++pToken;
1438                         ++len;
1439                         TRACE("%f ,", *(float *)pToken);
1440                         ++pToken;
1441                         ++len;
1442                         TRACE("%f ,", *(float *)pToken);
1443                         ++pToken;
1444                         ++len;
1445                         TRACE("%f ,", *(float *)pToken);
1446                         ++pToken;
1447                         ++len;
1448                         TRACE("%f", *(float *)pToken);
1449                         ++pToken;
1450                         ++len;
1451                 } else {
1452
1453                     DWORD param, addr_token;
1454                     int tokens_read;
1455
1456                     TRACE("%s", curOpcode->name);
1457                     if (curOpcode->num_params > 0) {
1458
1459                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1460                             pToken, &param, &addr_token);                       
1461                         pToken += tokens_read;
1462                         len += tokens_read;
1463
1464                         shader_dump_ins_modifiers(param);
1465                         TRACE(" ");
1466                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1467                          
1468                         for (i = 1; i < curOpcode->num_params; ++i) {
1469
1470                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1471                                pToken, &param, &addr_token);
1472                             pToken += tokens_read;
1473                             len += tokens_read;
1474
1475                             TRACE(", ");
1476                             shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1477                         }
1478                     }
1479                 }
1480                 TRACE("\n");
1481             }
1482         }
1483         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1484     } else {
1485         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1486     }
1487
1488     /* Generate HW shader in needed */
1489     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1490         TRACE("(%p) : Generating hardware program\n", This);
1491 #if 1
1492         IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1493 #endif
1494     }
1495
1496     TRACE("(%p) : Copying the function\n", This);
1497     /* copy the function ... because it will certainly be released by application */
1498     if (NULL != pFunction) {
1499         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1500         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1501     } else {
1502         This->baseShader.function = NULL;
1503     }
1504
1505     /* TODO: Some proper return values for failures */
1506     TRACE("(%p) : Returning WINED3D_OK\n", This);
1507     return WINED3D_OK;
1508 }
1509
1510 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1511 {
1512     /*** IUnknown methods ***/
1513     IWineD3DPixelShaderImpl_QueryInterface,
1514     IWineD3DPixelShaderImpl_AddRef,
1515     IWineD3DPixelShaderImpl_Release,
1516     /*** IWineD3DBase methods ***/
1517     IWineD3DPixelShaderImpl_GetParent,
1518     /*** IWineD3DBaseShader methods ***/
1519     IWineD3DPixelShaderImpl_SetFunction,
1520     /*** IWineD3DPixelShader methods ***/
1521     IWineD3DPixelShaderImpl_GetDevice,
1522     IWineD3DPixelShaderImpl_GetFunction
1523 };