rpcrt4: Add functions for generating and parsing the upper floors in endpoint-mapper...
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
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,  3, 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
749     DWORD reg = param & D3DSP_REGNUM_MASK;
750     DWORD regtype = shader_get_regtype(param);
751
752     switch (regtype) {
753     case D3DSPR_TEMP:
754         sprintf(regstr, "R%lu", reg);
755     break;
756     case D3DSPR_INPUT:
757         if (reg==0) {
758             strcpy(regstr, "fragment.color.primary");
759         } else {
760             strcpy(regstr, "fragment.color.secondary");
761         }
762     break;
763     case D3DSPR_CONST:
764         if (constants[reg])
765             sprintf(regstr, "C%lu", reg);
766         else
767             sprintf(regstr, "C[%lu]", reg);
768     break;
769     case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
770         sprintf(regstr,"T%lu", reg);
771     break;
772     case D3DSPR_COLOROUT:
773         if (reg == 0)
774             sprintf(regstr, "result.color");
775         else {
776             /* TODO: See GL_ARB_draw_buffers */
777             FIXME("Unsupported write to render target %lu\n", reg);
778             sprintf(regstr, "unsupported_register");
779         }
780     break;
781     case D3DSPR_DEPTHOUT:
782         sprintf(regstr, "result.depth");
783     break;
784     case D3DSPR_ATTROUT:
785         sprintf(regstr, "oD[%lu]", reg);
786     break;
787     case D3DSPR_TEXCRDOUT:
788         sprintf(regstr, "oT[%lu]", reg);
789     break;
790     default:
791         FIXME("Unhandled register name Type(%ld)\n", regtype);
792         sprintf(regstr, "unrecognized_register");
793     break;
794     }
795 }
796
797 inline static void get_write_mask(const DWORD output_reg, char *write_mask) {
798     *write_mask = 0;
799     if ((output_reg & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
800         strcat(write_mask, ".");
801         if (output_reg & D3DSP_WRITEMASK_0) strcat(write_mask, "r");
802         if (output_reg & D3DSP_WRITEMASK_1) strcat(write_mask, "g");
803         if (output_reg & D3DSP_WRITEMASK_2) strcat(write_mask, "b");
804         if (output_reg & D3DSP_WRITEMASK_3) strcat(write_mask, "a");
805     }
806 }
807
808 static void pshader_get_input_register_swizzle(const DWORD instr, char *swzstring) {
809     static const char swizzle_reg_chars[] = "rgba";
810     DWORD swizzle = (instr & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
811     DWORD swizzle_x = swizzle & 0x03;
812     DWORD swizzle_y = (swizzle >> 2) & 0x03;
813     DWORD swizzle_z = (swizzle >> 4) & 0x03;
814     DWORD swizzle_w = (swizzle >> 6) & 0x03;
815     /**
816      * swizzle bits fields:
817      *  WWZZYYXX
818      */
819     *swzstring = 0;
820     if ((D3DSP_NOSWIZZLE >> D3DSP_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
821         if (swizzle_x == swizzle_y && 
822         swizzle_x == swizzle_z && 
823         swizzle_x == swizzle_w) {
824             sprintf(swzstring, ".%c", swizzle_reg_chars[swizzle_x]);
825         } else {
826             sprintf(swzstring, ".%c%c%c%c", 
827                 swizzle_reg_chars[swizzle_x], 
828                 swizzle_reg_chars[swizzle_y], 
829                 swizzle_reg_chars[swizzle_z], 
830                 swizzle_reg_chars[swizzle_w]);
831         }
832     }
833 }
834
835 static const char* shift_tab[] = {
836     "dummy",     /*  0 (none) */ 
837     "coefmul.x", /*  1 (x2)   */ 
838     "coefmul.y", /*  2 (x4)   */ 
839     "coefmul.z", /*  3 (x8)   */ 
840     "coefmul.w", /*  4 (x16)  */ 
841     "dummy",     /*  5 (x32)  */ 
842     "dummy",     /*  6 (x64)  */ 
843     "dummy",     /*  7 (x128) */ 
844     "dummy",     /*  8 (d256) */ 
845     "dummy",     /*  9 (d128) */ 
846     "dummy",     /* 10 (d64)  */ 
847     "dummy",     /* 11 (d32)  */ 
848     "coefdiv.w", /* 12 (d16)  */ 
849     "coefdiv.z", /* 13 (d8)   */ 
850     "coefdiv.y", /* 14 (d4)   */ 
851     "coefdiv.x"  /* 15 (d2)   */ 
852 };
853
854 inline static void pshader_gen_output_modifier_line(
855     SHADER_BUFFER* buffer,
856     int saturate,
857     char *write_mask,
858     int shift,
859     char *regstr) {
860
861     /* Generate a line that does the output modifier computation */
862     shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", saturate ? "_SAT" : "",
863         regstr, write_mask, regstr, shift_tab[shift]);
864 }
865
866 static void pshader_gen_input_modifier_line (
867     SHADER_BUFFER* buffer,
868     const DWORD instr,
869     int tmpreg,
870     char *outregstr,
871     char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
872
873     /* Generate a line that does the input modifier computation and return the input register to use */
874     char regstr[256];
875     char swzstr[20];
876     int insert_line;
877
878     /* Assume a new line will be added */
879     insert_line = 1;
880
881     /* Get register name */
882     get_register_name(instr, regstr, constants);
883     pshader_get_input_register_swizzle(instr, swzstr);
884
885     switch (instr & D3DSP_SRCMOD_MASK) {
886     case D3DSPSM_NONE:
887         sprintf(outregstr, "%s%s", regstr, swzstr);
888         insert_line = 0;
889         break;
890     case D3DSPSM_NEG:
891         sprintf(outregstr, "-%s%s", regstr, swzstr);
892         insert_line = 0;
893         break;
894     case D3DSPSM_BIAS:
895         shader_addline(buffer, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg, regstr);
896         break;
897     case D3DSPSM_BIASNEG:
898         shader_addline(buffer, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg, regstr);
899         break;
900     case D3DSPSM_SIGN:
901         shader_addline(buffer, "MAD T%c, %s, coefmul.x, -one.x;\n", 'A' + tmpreg, regstr);
902         break;
903     case D3DSPSM_SIGNNEG:
904         shader_addline(buffer, "MAD T%c, %s, -coefmul.x, one.x;\n", 'A' + tmpreg, regstr);
905         break;
906     case D3DSPSM_COMP:
907         shader_addline(buffer, "SUB T%c, one.x, %s;\n", 'A' + tmpreg, regstr);
908         break;
909     case D3DSPSM_X2:
910         shader_addline(buffer, "ADD T%c, %s, %s;\n", 'A' + tmpreg, regstr, regstr);
911         break;
912     case D3DSPSM_X2NEG:
913         shader_addline(buffer, "ADD T%c, -%s, -%s;\n", 'A' + tmpreg, regstr, regstr);
914         break;
915     case D3DSPSM_DZ:
916         shader_addline(buffer, "RCP T%c, %s.z;\n", 'A' + tmpreg, regstr);
917         shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
918         break;
919     case D3DSPSM_DW:
920         shader_addline(buffer, "RCP T%c, %s.w;\n", 'A' + tmpreg, regstr);
921         shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
922         break;
923     default:
924         sprintf(outregstr, "%s%s", regstr, swzstr);
925         insert_line = 0;
926     }
927
928     /* Return modified or original register, with swizzle */
929     if (insert_line)
930         sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
931 }
932
933 void pshader_set_version(
934       IWineD3DPixelShaderImpl *This, 
935       DWORD version) {
936
937       DWORD major = (version >> 8) & 0x0F;
938       DWORD minor = version & 0x0F;
939
940       This->baseShader.hex_version = version;
941       This->baseShader.version = major * 10 + minor;
942       TRACE("ps_%lu_%lu\n", major, minor);
943
944       This->baseShader.limits.attributes = 0;
945       This->baseShader.limits.address = 0;
946
947       switch (This->baseShader.version) {
948           case 10:
949           case 11:
950           case 12:
951           case 13: This->baseShader.limits.temporary = 2;
952                    This->baseShader.limits.constant_float = 8;
953                    This->baseShader.limits.constant_int = 0;
954                    This->baseShader.limits.constant_bool = 0;
955                    This->baseShader.limits.texture = 4;
956                    break;
957
958           case 14: This->baseShader.limits.temporary = 6;
959                    This->baseShader.limits.constant_float = 8;
960                    This->baseShader.limits.constant_int = 0;
961                    This->baseShader.limits.constant_bool = 0;
962                    This->baseShader.limits.texture = 6;
963                    break;
964                
965           /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */ 
966           case 20: This->baseShader.limits.temporary = 32;
967                    This->baseShader.limits.constant_float = 32;
968                    This->baseShader.limits.constant_int = 16;
969                    This->baseShader.limits.constant_bool = 16;
970                    This->baseShader.limits.texture = 8;
971                    break;
972
973           case 30: This->baseShader.limits.temporary = 32;
974                    This->baseShader.limits.constant_float = 224;
975                    This->baseShader.limits.constant_int = 16;
976                    This->baseShader.limits.constant_bool = 16;
977                    This->baseShader.limits.texture = 0;
978                    break;
979
980           default: This->baseShader.limits.temporary = 32;
981                    This->baseShader.limits.constant_float = 8;
982                    This->baseShader.limits.constant_int = 0;
983                    This->baseShader.limits.constant_bool = 0;
984                    This->baseShader.limits.texture = 8;
985                    FIXME("Unrecognized pixel shader version %lx!\n", version);
986       }
987 }
988
989 /* Map the opcode 1-to-1 to the GL code */
990 /* FIXME: fix CMP/CND, get rid of this switch */
991 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
992
993      IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
994      CONST SHADER_OPCODE* curOpcode = arg->opcode;
995      SHADER_BUFFER* buffer = arg->buffer;
996      DWORD dst = arg->dst;
997      DWORD* src = arg->src;
998
999      unsigned int i;
1000      char tmpLine[256];
1001
1002      /* Output token related */
1003      char output_rname[256];
1004      char output_wmask[20];
1005      BOOL saturate = FALSE;
1006      BOOL centroid = FALSE;
1007      BOOL partialprecision = FALSE;
1008      DWORD shift;
1009
1010      strcpy(tmpLine, curOpcode->glname);
1011
1012      /* Process modifiers */
1013      if (0 != (dst & D3DSP_DSTMOD_MASK)) {
1014          DWORD mask = dst & D3DSP_DSTMOD_MASK;
1015
1016          saturate = mask & D3DSPDM_SATURATE;
1017          centroid = mask & D3DSPDM_MSAMPCENTROID;
1018          partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1019          mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1020
1021          if (mask)
1022             FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1023
1024          if (centroid)
1025              FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1026      }
1027      shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1028
1029       /* Generate input and output registers */
1030       if (curOpcode->num_params > 0) {
1031           char operands[4][100];
1032
1033           /* Generate input register names (with modifiers) */
1034           for (i = 1; i < curOpcode->num_params; ++i)
1035               pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i], This->constants);
1036
1037           /* Handle output register */
1038           get_register_name(dst, output_rname, This->constants);
1039           strcpy(operands[0], output_rname);
1040           get_write_mask(dst, output_wmask);
1041           strcat(operands[0], output_wmask);
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               pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
1070       }
1071 }
1072
1073 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1074
1075     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1076     DWORD dst = arg->dst;
1077     DWORD* src = arg->src;
1078     SHADER_BUFFER* buffer = arg->buffer;
1079     DWORD version = This->baseShader.version;
1080    
1081     char reg_dest[40];
1082     char reg_coord[40];
1083     DWORD reg_dest_code;
1084     DWORD reg_sampler_code;
1085
1086     /* All versions have a destination register */
1087     reg_dest_code = dst & D3DSP_REGNUM_MASK;
1088     get_register_name(dst, reg_dest, This->constants);
1089
1090     /* 1.0-1.3: Use destination register as coordinate source.
1091        2.0+: Use provided coordinate source register. */
1092    if (version < 14)
1093       strcpy(reg_coord, reg_dest);
1094    else
1095       pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord, This->constants);
1096
1097   /* 1.0-1.4: Use destination register number as texture code.
1098      2.0+: Use provided sampler number as texure code. */
1099   if (version < 20)
1100      reg_sampler_code = reg_dest_code;
1101   else 
1102      reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1103
1104   shader_addline(buffer, "TEX %s, %s, texture[%lu], 2D;\n",
1105       reg_dest, reg_coord, reg_sampler_code);
1106 }
1107
1108 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1109
1110     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1111     DWORD dst = arg->dst;
1112     DWORD* src = arg->src;
1113     SHADER_BUFFER* buffer = arg->buffer;
1114     DWORD version = This->baseShader.version;
1115
1116     char tmp[20];
1117     get_write_mask(dst, tmp);
1118     if (version != 14) {
1119         DWORD reg = dst & D3DSP_REGNUM_MASK;
1120         shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1121     } else {
1122         DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1123         DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1124         shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1125    }
1126 }
1127
1128 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1129
1130      SHADER_BUFFER* buffer = arg->buffer;
1131  
1132      DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1133      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1134      shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1135      shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1136      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1137 }
1138
1139 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1140  
1141      SHADER_BUFFER* buffer = arg->buffer;
1142     
1143      DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1144      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1145      shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1146      shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1147      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1148 }
1149
1150 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1151
1152      SHADER_BUFFER* buffer = arg->buffer;
1153  
1154      DWORD reg1 = arg->dst  & D3DSP_REGNUM_MASK;
1155      DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1156
1157      /* FIXME: Should apply the BUMPMAPENV matrix */
1158      shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1159      shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1160 }
1161
1162 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1163     
1164     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1165     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1166     SHADER_BUFFER* buffer = arg->buffer;
1167     
1168     shader_addline(buffer, 
1169               "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1170               *((float*) (arg->src + 0)),
1171               *((float*) (arg->src + 1)),
1172               *((float*) (arg->src + 2)),
1173               *((float*) (arg->src + 3)) );
1174
1175     shader->constants[reg] = 1;
1176 }
1177
1178 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1179
1180     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1181     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1182     SHADER_BUFFER* buffer = arg->buffer;
1183     char src0_name[50];
1184
1185     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1186     shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, src0_name);
1187 }
1188
1189 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1190
1191     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1192     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1193     SHADER_BUFFER* buffer = arg->buffer;
1194     char src0_name[50];
1195
1196     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1197     shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, src0_name);
1198     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1199 }
1200
1201 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1202
1203     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1204     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1205     SHADER_BUFFER* buffer = arg->buffer;
1206     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1207     char src0_name[50];
1208
1209     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1210     shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, src0_name);
1211     current_state.texcoord_w[current_state.current_row++] = reg;
1212 }
1213
1214 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1215
1216     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1217     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1218     SHADER_BUFFER* buffer = arg->buffer;
1219     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1220     char src0_name[50];
1221
1222     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1223     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1224
1225     /* Cubemap textures will be more used than 3D ones. */
1226     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1227     current_state.current_row = 0;
1228 }
1229
1230 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1231
1232     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1233     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1234     SHADER_BUFFER* buffer = arg->buffer;
1235     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1236     char src0_name[50];
1237
1238     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1239     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1240
1241     /* Construct the eye-ray vector from w coordinates */
1242     shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1243     shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1244     shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1245
1246     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1247     shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1248     shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1249     shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1250
1251     /* Cubemap textures will be more used than 3D ones. */
1252     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1253     current_state.current_row = 0;
1254 }
1255
1256 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1257
1258     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1259     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1260     DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1261     SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1262     SHADER_BUFFER* buffer = arg->buffer;
1263     char src0_name[50];
1264
1265     pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1266     shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1267
1268     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1269     shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1270     shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1271     shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1272
1273     /* Cubemap textures will be more used than 3D ones. */
1274     shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1275     current_state.current_row = 0;
1276 }
1277
1278 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1279     or GLSL and send it to the card */
1280 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1281     IWineD3DPixelShader *iface,
1282     CONST DWORD *pFunction) {
1283
1284     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1285     SHADER_BUFFER buffer;
1286
1287 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1288         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1289     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1290         HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1291         This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1292         This->fixupVertexBufferSize = PGMSIZE;
1293         This->fixupVertexBuffer[0] = 0;
1294     }
1295     buffer.buffer = This->device->fixupVertexBuffer;
1296 #else
1297     buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); 
1298 #endif
1299     buffer.bsize = 0;
1300     buffer.lineNo = 0;
1301
1302     if (wined3d_settings.shader_mode == SHADER_GLSL) {
1303
1304         /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
1305         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
1306
1307         /* Generate the bulk of the shader code */
1308         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1309
1310         /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
1311         if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1312             shader_addline(&buffer, "glFragColor = R0;\n");
1313         shader_addline(&buffer, "}\n\0");
1314
1315         TRACE("Compiling shader object %u\n", shader_obj);
1316         GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
1317         GL_EXTCALL(glCompileShaderARB(shader_obj));
1318         print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
1319
1320         /* Store the shader object */
1321         This->baseShader.prgId = shader_obj;
1322
1323     } else if (wined3d_settings.shader_mode == SHADER_ARB) {
1324         /*  Create the hw ARB shader */
1325         shader_addline(&buffer, "!!ARBfp1.0\n");
1326
1327         shader_addline(&buffer, "TEMP TMP;\n");     /* Used in matrix ops */
1328         shader_addline(&buffer, "TEMP TMP2;\n");    /* Used in matrix ops */
1329         shader_addline(&buffer, "TEMP TA;\n");      /* Used for modifiers */
1330         shader_addline(&buffer, "TEMP TB;\n");      /* Used for modifiers */
1331         shader_addline(&buffer, "TEMP TC;\n");      /* Used for modifiers */
1332         shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1333         shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1334         shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1335
1336         /** Call the base shader generation routine to generate most 
1337             of the pixel shader string for us */
1338         generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1339
1340         if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1341             shader_addline(&buffer, "MOV result.color, R0;\n");
1342         shader_addline(&buffer, "END\n\0"); 
1343
1344         /* TODO: change to resource.glObjectHandle or something like that */
1345         GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1346
1347         TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1348         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1349
1350         TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1351         /* Create the program and check for errors */
1352         GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1353             buffer.bsize, buffer.buffer));
1354
1355         if (glGetError() == GL_INVALID_OPERATION) {
1356             GLint errPos;
1357             glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1358             FIXME("HW PixelShader Error at position %d: %s\n",
1359                   errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1360             This->baseShader.prgId = -1;
1361         }
1362     }
1363
1364 #if 1 /* if were using the data buffer of device then we don't need to free it */
1365   HeapFree(GetProcessHeap(), 0, buffer.buffer);
1366 #endif
1367 }
1368
1369 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1370     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1371     const DWORD* pToken = pFunction;
1372     const SHADER_OPCODE *curOpcode = NULL;
1373     DWORD opcode_token;
1374     DWORD len = 0;
1375     DWORD i;
1376     TRACE("(%p) : Parsing programme\n", This);
1377
1378     if (NULL != pToken) {
1379         while (D3DPS_END() != *pToken) {
1380             if (shader_is_pshader_version(*pToken)) { /** version */
1381                 pshader_set_version(This, *pToken);
1382                 ++pToken;
1383                 ++len;
1384                 continue;
1385             }
1386             if (shader_is_comment(*pToken)) { /** comment */
1387                 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1388                 ++pToken;
1389                 TRACE("//%s\n", (char*)pToken);
1390                 pToken += comment_len;
1391                 len += comment_len + 1;
1392                 continue;
1393             }
1394             if (!This->baseShader.version) {
1395                 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1396             }
1397             opcode_token = *pToken++;
1398             curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1399             len++;
1400             if (NULL == curOpcode) {
1401                 int tokens_read;
1402
1403                 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1404                 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1405                 pToken += tokens_read;
1406                 len += tokens_read;
1407
1408             } else {
1409                 if (curOpcode->opcode == D3DSIO_DCL) {
1410                     DWORD usage = *pToken;
1411                     DWORD param = *(pToken + 1);
1412                     DWORD regtype = shader_get_regtype(param);
1413
1414                     /* Only print extended declaration for samplers or 3.0 input registers */
1415                     if (regtype == D3DSPR_SAMPLER ||
1416                         (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1417                          shader_program_dump_decl_usage(usage, param);
1418                     else
1419                          TRACE("dcl");
1420
1421                     shader_dump_ins_modifiers(param);
1422                     TRACE(" ");
1423                     shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1424                     pToken += 2;
1425                     len += 2;
1426
1427                 } else 
1428                     if (curOpcode->opcode == D3DSIO_DEF) {
1429                         TRACE("def c%lu = ", *pToken & 0xFF);
1430                         ++pToken;
1431                         ++len;
1432                         TRACE("%f ,", *(float *)pToken);
1433                         ++pToken;
1434                         ++len;
1435                         TRACE("%f ,", *(float *)pToken);
1436                         ++pToken;
1437                         ++len;
1438                         TRACE("%f ,", *(float *)pToken);
1439                         ++pToken;
1440                         ++len;
1441                         TRACE("%f", *(float *)pToken);
1442                         ++pToken;
1443                         ++len;
1444                 } else {
1445
1446                     DWORD param, addr_token;
1447                     int tokens_read;
1448
1449                     /* Print out predication source token first - it follows
1450                      * the destination token. */
1451                     if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1452                         TRACE("(");
1453                         shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1454                         TRACE(") ");
1455                     }
1456
1457                     TRACE("%s", curOpcode->name);
1458                     if (curOpcode->num_params > 0) {
1459
1460                         /* Destination token */
1461                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1462                             pToken, &param, &addr_token);                       
1463                         pToken += tokens_read;
1464                         len += tokens_read;
1465
1466                         shader_dump_ins_modifiers(param);
1467                         TRACE(" ");
1468                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1469
1470                         /* Predication token - already printed out, just skip it */
1471                         if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1472                             pToken++;
1473                             len++;
1474                         }
1475
1476                         /* Other source tokens */
1477                         for (i = 1; i < curOpcode->num_params; ++i) {
1478
1479                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1480                                pToken, &param, &addr_token);
1481                             pToken += tokens_read;
1482                             len += tokens_read;
1483
1484                             TRACE(", ");
1485                             shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1486                         }
1487                     }
1488                 }
1489                 TRACE("\n");
1490             }
1491         }
1492         This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1493     } else {
1494         This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1495     }
1496
1497     /* Generate HW shader in needed */
1498     if (NULL != pFunction  && wined3d_settings.vs_mode == VS_HW) {
1499         TRACE("(%p) : Generating hardware program\n", This);
1500 #if 1
1501         IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1502 #endif
1503     }
1504
1505     TRACE("(%p) : Copying the function\n", This);
1506     /* copy the function ... because it will certainly be released by application */
1507     if (NULL != pFunction) {
1508         This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1509         memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1510     } else {
1511         This->baseShader.function = NULL;
1512     }
1513
1514     /* TODO: Some proper return values for failures */
1515     TRACE("(%p) : Returning WINED3D_OK\n", This);
1516     return WINED3D_OK;
1517 }
1518
1519 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1520 {
1521     /*** IUnknown methods ***/
1522     IWineD3DPixelShaderImpl_QueryInterface,
1523     IWineD3DPixelShaderImpl_AddRef,
1524     IWineD3DPixelShaderImpl_Release,
1525     /*** IWineD3DBase methods ***/
1526     IWineD3DPixelShaderImpl_GetParent,
1527     /*** IWineD3DBaseShader methods ***/
1528     IWineD3DPixelShaderImpl_SetFunction,
1529     /*** IWineD3DPixelShader methods ***/
1530     IWineD3DPixelShaderImpl_GetDevice,
1531     IWineD3DPixelShaderImpl_GetFunction
1532 };