wined3d: Add limits for ps_2_x.
[wine/multimedia.git] / dlls / wined3d / pixelshader.c
blob05e8c68d098c17adb0d256041735846f7e2ced34
1 /*
2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006 Ivan Gyurdiev
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.
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.
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
24 #include "config.h"
26 #include <math.h>
27 #include <stdio.h>
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
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
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)
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;
59 *ppobj = NULL;
60 return E_NOINTERFACE;
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);
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);
77 return ref;
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.
86 /* *******************************************
87 IWineD3DPixelShader IWineD3DPixelShader parts follow
88 ******************************************* */
90 HRESULT WINAPI IWineD3DPixelShaderImpl_GetParent(IWineD3DPixelShader *iface, IUnknown** parent){
91 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
93 *parent = This->parent;
94 IUnknown_AddRef(*parent);
95 TRACE("(%p) : returning %p\n", This, *parent);
96 return WINED3D_OK;
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;
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);
112 if (NULL == pData) {
113 *pSizeOfData = This->baseShader.functionLength;
114 return WINED3D_OK;
116 if (*pSizeOfData < This->baseShader.functionLength) {
117 *pSizeOfData = This->baseShader.functionLength;
118 return WINED3DERR_MOREDATA;
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) {
127 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
128 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
130 return WINED3D_OK;
133 /*******************************
134 * pshader functions software VM
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));
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));
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));
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));
167 void pshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
168 union {
169 float f;
170 DWORD d;
171 } tmp;
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));
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));
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));
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));
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));
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));
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));
236 void pshader_nop(void) {
237 /* NOPPPP ahhh too easy ;) */
238 PSTRACE(("executing nop\n"));
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));
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));
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));
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));
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));
282 * Version 1.1 specific
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));
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));
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));
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];
313 void pshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
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;
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));
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));
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));
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));
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;
376 * Version 2.0 specific
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;
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 */
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));
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));
404 /* Stubs */
405 void pshader_texcoord(WINED3DSHADERVECTOR* d) {
406 FIXME(" : Stub\n");
409 void pshader_texkill(WINED3DSHADERVECTOR* d) {
410 FIXME(" : Stub\n");
413 void pshader_tex(WINED3DSHADERVECTOR* d) {
414 FIXME(" : Stub\n");
416 void pshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
417 FIXME(" : Stub\n");
420 void pshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421 FIXME(" : Stub\n");
424 void pshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
425 FIXME(" : Stub\n");
428 void pshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
429 FIXME(" : Stub\n");
432 void pshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
433 FIXME(" : Stub\n");
436 void pshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
437 FIXME(" : Stub\n");
440 void pshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
441 FIXME(" : Stub\n");
444 void pshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
445 FIXME(" : Stub\n");
448 void pshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449 FIXME(" : Stub\n");
452 void pshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
453 FIXME(" : Stub\n");
456 void pshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
457 FIXME(" : Stub\n");
460 void pshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
461 FIXME(" : Stub\n");
464 void pshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
465 FIXME(" : Stub\n");
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");
473 void pshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
474 FIXME(" : Stub\n");
477 void pshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
478 FIXME(" : Stub\n");
481 void pshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
482 FIXME(" : Stub\n");
485 void pshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486 FIXME(" : Stub\n");
489 void pshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
490 FIXME(" : Stub\n");
493 void pshader_texdepth(WINED3DSHADERVECTOR* d) {
494 FIXME(" : Stub\n");
497 void pshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
498 FIXME(" : Stub\n");
501 void pshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
502 FIXME(" : Stub\n");
505 void pshader_call(WINED3DSHADERVECTOR* d) {
506 FIXME(" : Stub\n");
509 void pshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
510 FIXME(" : Stub\n");
513 void pshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514 FIXME(" : Stub\n");
517 void pshader_ret(void) {
518 FIXME(" : Stub\n");
521 void pshader_endloop(void) {
522 FIXME(" : Stub\n");
525 void pshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
526 FIXME(" : Stub\n");
529 void pshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
530 FIXME(" : Stub\n");
533 void pshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
534 FIXME(" : Stub\n");
537 void pshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
538 FIXME(" : Stub\n");
541 void pshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
542 FIXME(" : Stub\n");
545 void pshader_rep(WINED3DSHADERVECTOR* d) {
546 FIXME(" : Stub\n");
549 void pshader_endrep(void) {
550 FIXME(" : Stub\n");
553 void pshader_if(WINED3DSHADERVECTOR* d) {
554 FIXME(" : Stub\n");
557 void pshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
558 FIXME(" : Stub\n");
561 void pshader_else(void) {
562 FIXME(" : Stub\n");
565 void pshader_label(WINED3DSHADERVECTOR* d) {
566 FIXME(" : Stub\n");
569 void pshader_endif(void) {
570 FIXME(" : Stub\n");
573 void pshader_break(void) {
574 FIXME(" : Stub\n");
577 void pshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
578 FIXME(" : Stub\n");
581 void pshader_breakp(WINED3DSHADERVECTOR* d) {
582 FIXME(" : Stub\n");
585 void pshader_defb(WINED3DSHADERVECTOR* d) {
586 FIXME(" : Stub\n");
589 void pshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
590 FIXME(" : Stub\n");
593 void pshader_dp2add(WINED3DSHADERVECTOR* d) {
594 FIXME(" : Stub\n");
597 void pshader_dsx(WINED3DSHADERVECTOR* d) {
598 FIXME(" : Stub\n");
601 void pshader_dsy(WINED3DSHADERVECTOR* d) {
602 FIXME(" : Stub\n");
605 void pshader_texldd(WINED3DSHADERVECTOR* d) {
606 FIXME(" : Stub\n");
609 void pshader_setp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
610 FIXME(" : Stub\n");
613 void pshader_texldl(WINED3DSHADERVECTOR* d) {
614 FIXME(" : Stub\n");
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);
633 * log, exp, frc, m*x* seems to be macros ins ... to see
635 CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
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;
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},
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},
687 /* Register declarations */
688 {D3DSIO_DCL, "dcl", NULL, 2, pshader_dcl, NULL, NULL, 0, 0},
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},
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, 5, pshader_defi, NULL, NULL, 0, 0},
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}
747 inline static void get_register_name(const DWORD param, char* regstr, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
749 DWORD reg = param & D3DSP_REGNUM_MASK;
750 DWORD regtype = shader_get_regtype(param);
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");
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");
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;
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");
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;
816 * swizzle bits fields:
817 * WWZZYYXX
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]);
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) */
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) {
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]);
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]) {
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;
878 /* Assume a new line will be added */
879 insert_line = 1;
881 /* Get register name */
882 get_register_name(instr, regstr, constants);
883 pshader_get_input_register_swizzle(instr, swzstr);
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;
928 /* Return modified or original register, with swizzle */
929 if (insert_line)
930 sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
933 void pshader_set_version(
934 IWineD3DPixelShaderImpl *This,
935 DWORD version) {
937 DWORD major = (version >> 8) & 0x0F;
938 DWORD minor = version & 0x0F;
940 This->baseShader.hex_version = version;
941 This->baseShader.version = major * 10 + minor;
942 TRACE("ps_%lu_%lu\n", major, minor);
944 This->baseShader.limits.attributes = 0;
945 This->baseShader.limits.address = 0;
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;
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;
965 /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */
966 case 20:
967 case 21: This->baseShader.limits.temporary = 32;
968 This->baseShader.limits.constant_float = 32;
969 This->baseShader.limits.constant_int = 16;
970 This->baseShader.limits.constant_bool = 16;
971 This->baseShader.limits.texture = 8;
972 break;
974 case 30: This->baseShader.limits.temporary = 32;
975 This->baseShader.limits.constant_float = 224;
976 This->baseShader.limits.constant_int = 16;
977 This->baseShader.limits.constant_bool = 16;
978 This->baseShader.limits.texture = 0;
979 break;
981 default: This->baseShader.limits.temporary = 32;
982 This->baseShader.limits.constant_float = 8;
983 This->baseShader.limits.constant_int = 0;
984 This->baseShader.limits.constant_bool = 0;
985 This->baseShader.limits.texture = 8;
986 FIXME("Unrecognized pixel shader version %lx!\n", version);
990 /* Map the opcode 1-to-1 to the GL code */
991 /* FIXME: fix CMP/CND, get rid of this switch */
992 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
994 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
995 CONST SHADER_OPCODE* curOpcode = arg->opcode;
996 SHADER_BUFFER* buffer = arg->buffer;
997 DWORD dst = arg->dst;
998 DWORD* src = arg->src;
1000 unsigned int i;
1001 char tmpLine[256];
1003 /* Output token related */
1004 char output_rname[256];
1005 char output_wmask[20];
1006 BOOL saturate = FALSE;
1007 BOOL centroid = FALSE;
1008 BOOL partialprecision = FALSE;
1009 DWORD shift;
1011 strcpy(tmpLine, curOpcode->glname);
1013 /* Process modifiers */
1014 if (0 != (dst & D3DSP_DSTMOD_MASK)) {
1015 DWORD mask = dst & D3DSP_DSTMOD_MASK;
1017 saturate = mask & D3DSPDM_SATURATE;
1018 centroid = mask & D3DSPDM_MSAMPCENTROID;
1019 partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1020 mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1022 if (mask)
1023 FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1025 if (centroid)
1026 FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1028 shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1030 /* Generate input and output registers */
1031 if (curOpcode->num_params > 0) {
1032 char operands[4][100];
1034 /* Generate input register names (with modifiers) */
1035 for (i = 1; i < curOpcode->num_params; ++i)
1036 pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i], This->constants);
1038 /* Handle output register */
1039 get_register_name(dst, output_rname, This->constants);
1040 strcpy(operands[0], output_rname);
1041 get_write_mask(dst, output_wmask);
1042 strcat(operands[0], output_wmask);
1044 switch(curOpcode->opcode) {
1045 case D3DSIO_CMP:
1046 sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""),
1047 operands[0], operands[1], operands[3], operands[2]);
1048 break;
1049 case D3DSIO_CND:
1050 shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", operands[1]);
1051 sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""),
1052 operands[0], operands[2], operands[3]);
1053 break;
1055 default:
1056 if (saturate && (shift == 0))
1057 strcat(tmpLine, "_SAT");
1058 strcat(tmpLine, " ");
1059 strcat(tmpLine, operands[0]);
1060 for (i = 1; i < curOpcode->num_params; i++) {
1061 strcat(tmpLine, ", ");
1062 strcat(tmpLine, operands[i]);
1064 strcat(tmpLine,";\n");
1066 shader_addline(buffer, tmpLine);
1068 /* A shift requires another line. */
1069 if (shift != 0)
1070 pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
1074 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1076 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1077 DWORD dst = arg->dst;
1078 DWORD* src = arg->src;
1079 SHADER_BUFFER* buffer = arg->buffer;
1080 DWORD version = This->baseShader.version;
1082 char reg_dest[40];
1083 char reg_coord[40];
1084 DWORD reg_dest_code;
1085 DWORD reg_sampler_code;
1087 /* All versions have a destination register */
1088 reg_dest_code = dst & D3DSP_REGNUM_MASK;
1089 get_register_name(dst, reg_dest, This->constants);
1091 /* 1.0-1.3: Use destination register as coordinate source.
1092 2.0+: Use provided coordinate source register. */
1093 if (version < 14)
1094 strcpy(reg_coord, reg_dest);
1095 else
1096 pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord, This->constants);
1098 /* 1.0-1.4: Use destination register number as texture code.
1099 2.0+: Use provided sampler number as texure code. */
1100 if (version < 20)
1101 reg_sampler_code = reg_dest_code;
1102 else
1103 reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1105 shader_addline(buffer, "TEX %s, %s, texture[%lu], 2D;\n",
1106 reg_dest, reg_coord, reg_sampler_code);
1109 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1111 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1112 DWORD dst = arg->dst;
1113 DWORD* src = arg->src;
1114 SHADER_BUFFER* buffer = arg->buffer;
1115 DWORD version = This->baseShader.version;
1117 char tmp[20];
1118 get_write_mask(dst, tmp);
1119 if (version != 14) {
1120 DWORD reg = dst & D3DSP_REGNUM_MASK;
1121 shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1122 } else {
1123 DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1124 DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1125 shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1129 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1131 SHADER_BUFFER* buffer = arg->buffer;
1133 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1134 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1135 shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1136 shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1137 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1140 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1142 SHADER_BUFFER* buffer = arg->buffer;
1144 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1145 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1146 shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1147 shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1148 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1151 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1153 SHADER_BUFFER* buffer = arg->buffer;
1155 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1156 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1158 /* FIXME: Should apply the BUMPMAPENV matrix */
1159 shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1160 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1163 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1165 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1166 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1167 SHADER_BUFFER* buffer = arg->buffer;
1169 shader_addline(buffer,
1170 "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1171 *((float*) (arg->src + 0)),
1172 *((float*) (arg->src + 1)),
1173 *((float*) (arg->src + 2)),
1174 *((float*) (arg->src + 3)) );
1176 shader->constants[reg] = 1;
1179 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1181 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1182 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1183 SHADER_BUFFER* buffer = arg->buffer;
1184 char src0_name[50];
1186 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1187 shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, src0_name);
1190 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1192 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1193 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1194 SHADER_BUFFER* buffer = arg->buffer;
1195 char src0_name[50];
1197 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1198 shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, src0_name);
1199 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1202 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1204 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1205 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1206 SHADER_BUFFER* buffer = arg->buffer;
1207 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1208 char src0_name[50];
1210 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1211 shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, src0_name);
1212 current_state.texcoord_w[current_state.current_row++] = reg;
1215 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1217 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1218 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1219 SHADER_BUFFER* buffer = arg->buffer;
1220 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1221 char src0_name[50];
1223 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1224 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1226 /* Cubemap textures will be more used than 3D ones. */
1227 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1228 current_state.current_row = 0;
1231 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1233 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1234 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1235 SHADER_BUFFER* buffer = arg->buffer;
1236 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1237 char src0_name[50];
1239 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1240 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1242 /* Construct the eye-ray vector from w coordinates */
1243 shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1244 shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1245 shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1247 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1248 shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1249 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1250 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1252 /* Cubemap textures will be more used than 3D ones. */
1253 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1254 current_state.current_row = 0;
1257 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1259 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1260 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1261 DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1262 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1263 SHADER_BUFFER* buffer = arg->buffer;
1264 char src0_name[50];
1266 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1267 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1269 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1270 shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1271 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1272 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1274 /* Cubemap textures will be more used than 3D ones. */
1275 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1276 current_state.current_row = 0;
1279 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1280 or GLSL and send it to the card */
1281 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1282 IWineD3DPixelShader *iface,
1283 CONST DWORD *pFunction) {
1285 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1286 SHADER_BUFFER buffer;
1288 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1289 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1290 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1291 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1292 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1293 This->fixupVertexBufferSize = PGMSIZE;
1294 This->fixupVertexBuffer[0] = 0;
1296 buffer.buffer = This->device->fixupVertexBuffer;
1297 #else
1298 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1299 #endif
1300 buffer.bsize = 0;
1301 buffer.lineNo = 0;
1303 if (wined3d_settings.shader_mode == SHADER_GLSL) {
1305 /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
1306 GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
1308 /* Generate the bulk of the shader code */
1309 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1311 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
1312 if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1313 shader_addline(&buffer, "glFragColor = R0;\n");
1314 shader_addline(&buffer, "}\n\0");
1316 TRACE("Compiling shader object %u\n", shader_obj);
1317 GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
1318 GL_EXTCALL(glCompileShaderARB(shader_obj));
1319 print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
1321 /* Store the shader object */
1322 This->baseShader.prgId = shader_obj;
1324 } else if (wined3d_settings.shader_mode == SHADER_ARB) {
1325 /* Create the hw ARB shader */
1326 shader_addline(&buffer, "!!ARBfp1.0\n");
1328 shader_addline(&buffer, "TEMP TMP;\n"); /* Used in matrix ops */
1329 shader_addline(&buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
1330 shader_addline(&buffer, "TEMP TA;\n"); /* Used for modifiers */
1331 shader_addline(&buffer, "TEMP TB;\n"); /* Used for modifiers */
1332 shader_addline(&buffer, "TEMP TC;\n"); /* Used for modifiers */
1333 shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1334 shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1335 shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1337 /** Call the base shader generation routine to generate most
1338 of the pixel shader string for us */
1339 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1341 if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1342 shader_addline(&buffer, "MOV result.color, R0;\n");
1343 shader_addline(&buffer, "END\n\0");
1345 /* TODO: change to resource.glObjectHandle or something like that */
1346 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1348 TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1349 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1351 TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1352 /* Create the program and check for errors */
1353 GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1354 buffer.bsize, buffer.buffer));
1356 if (glGetError() == GL_INVALID_OPERATION) {
1357 GLint errPos;
1358 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1359 FIXME("HW PixelShader Error at position %d: %s\n",
1360 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1361 This->baseShader.prgId = -1;
1365 #if 1 /* if were using the data buffer of device then we don't need to free it */
1366 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1367 #endif
1370 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1371 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1372 const DWORD* pToken = pFunction;
1373 const SHADER_OPCODE *curOpcode = NULL;
1374 DWORD opcode_token;
1375 DWORD len = 0;
1376 DWORD i;
1377 TRACE("(%p) : Parsing programme\n", This);
1379 if (NULL != pToken) {
1380 while (D3DPS_END() != *pToken) {
1381 if (shader_is_pshader_version(*pToken)) { /** version */
1382 pshader_set_version(This, *pToken);
1383 ++pToken;
1384 ++len;
1385 continue;
1387 if (shader_is_comment(*pToken)) { /** comment */
1388 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1389 ++pToken;
1390 TRACE("//%s\n", (char*)pToken);
1391 pToken += comment_len;
1392 len += comment_len + 1;
1393 continue;
1395 if (!This->baseShader.version) {
1396 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1398 opcode_token = *pToken++;
1399 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1400 len++;
1401 if (NULL == curOpcode) {
1402 int tokens_read;
1404 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1405 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1406 pToken += tokens_read;
1407 len += tokens_read;
1409 } else {
1410 if (curOpcode->opcode == D3DSIO_DCL) {
1411 DWORD usage = *pToken;
1412 DWORD param = *(pToken + 1);
1413 DWORD regtype = shader_get_regtype(param);
1415 /* Only print extended declaration for samplers or 3.0 input registers */
1416 if (regtype == D3DSPR_SAMPLER ||
1417 (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1418 shader_program_dump_decl_usage(usage, param);
1419 else
1420 TRACE("dcl");
1422 shader_dump_ins_modifiers(param);
1423 TRACE(" ");
1424 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1425 pToken += 2;
1426 len += 2;
1428 } else if (curOpcode->opcode == D3DSIO_DEF) {
1430 unsigned int offset = shader_get_float_offset(*pToken);
1432 TRACE("def c%u = %f, %f, %f, %f", offset,
1433 *(float *)(pToken + 1),
1434 *(float *)(pToken + 2),
1435 *(float *)(pToken + 3),
1436 *(float *)(pToken + 4));
1438 pToken += 5;
1439 len += 5;
1441 } else if (curOpcode->opcode == D3DSIO_DEFI) {
1443 TRACE("defi i%lu = %ld, %ld, %ld, %ld", *pToken & D3DSP_REGNUM_MASK,
1444 (long) *(pToken + 1),
1445 (long) *(pToken + 2),
1446 (long) *(pToken + 3),
1447 (long) *(pToken + 4));
1449 pToken += 5;
1450 len += 5;
1452 } else if (curOpcode->opcode == D3DSIO_DEFB) {
1454 TRACE("defb b%lu = %s", *pToken & D3DSP_REGNUM_MASK,
1455 *(pToken + 1)? "true": "false");
1457 pToken += 2;
1458 len += 2;
1460 } else {
1462 DWORD param, addr_token;
1463 int tokens_read;
1465 /* Print out predication source token first - it follows
1466 * the destination token. */
1467 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1468 TRACE("(");
1469 shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1470 TRACE(") ");
1473 TRACE("%s", curOpcode->name);
1474 if (curOpcode->num_params > 0) {
1476 /* Destination token */
1477 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1478 pToken, &param, &addr_token);
1479 pToken += tokens_read;
1480 len += tokens_read;
1482 shader_dump_ins_modifiers(param);
1483 TRACE(" ");
1484 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1486 /* Predication token - already printed out, just skip it */
1487 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1488 pToken++;
1489 len++;
1492 /* Other source tokens */
1493 for (i = 1; i < curOpcode->num_params; ++i) {
1495 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1496 pToken, &param, &addr_token);
1497 pToken += tokens_read;
1498 len += tokens_read;
1500 TRACE(", ");
1501 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1505 TRACE("\n");
1508 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1509 } else {
1510 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1513 /* Generate HW shader in needed */
1514 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1515 TRACE("(%p) : Generating hardware program\n", This);
1516 #if 1
1517 IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1518 #endif
1521 TRACE("(%p) : Copying the function\n", This);
1522 /* copy the function ... because it will certainly be released by application */
1523 if (NULL != pFunction) {
1524 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1525 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1526 } else {
1527 This->baseShader.function = NULL;
1530 /* TODO: Some proper return values for failures */
1531 TRACE("(%p) : Returning WINED3D_OK\n", This);
1532 return WINED3D_OK;
1535 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1537 /*** IUnknown methods ***/
1538 IWineD3DPixelShaderImpl_QueryInterface,
1539 IWineD3DPixelShaderImpl_AddRef,
1540 IWineD3DPixelShaderImpl_Release,
1541 /*** IWineD3DBase methods ***/
1542 IWineD3DPixelShaderImpl_GetParent,
1543 /*** IWineD3DBaseShader methods ***/
1544 IWineD3DPixelShaderImpl_SetFunction,
1545 /*** IWineD3DPixelShader methods ***/
1546 IWineD3DPixelShaderImpl_GetDevice,
1547 IWineD3DPixelShaderImpl_GetFunction