Update the address of the Free Software Foundation.
[wine.git] / dlls / wined3d / pixelshader.c
blobbe4fbb842b13d4b5c407fd402dc4099e639a145b
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) {
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, 2, 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.address = 0;
946 switch (This->baseShader.version) {
947 case 10:
948 case 11:
949 case 12:
950 case 13: This->baseShader.limits.temporary = 2;
951 This->baseShader.limits.constant_float = 8;
952 This->baseShader.limits.constant_int = 0;
953 This->baseShader.limits.constant_bool = 0;
954 This->baseShader.limits.texture = 4;
955 break;
957 case 14: This->baseShader.limits.temporary = 6;
958 This->baseShader.limits.constant_float = 8;
959 This->baseShader.limits.constant_int = 0;
960 This->baseShader.limits.constant_bool = 0;
961 This->baseShader.limits.texture = 6;
962 break;
964 /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */
965 case 20: This->baseShader.limits.temporary = 32;
966 This->baseShader.limits.constant_float = 32;
967 This->baseShader.limits.constant_int = 16;
968 This->baseShader.limits.constant_bool = 16;
969 This->baseShader.limits.texture = 8;
970 break;
972 case 30: This->baseShader.limits.temporary = 32;
973 This->baseShader.limits.constant_float = 224;
974 This->baseShader.limits.constant_int = 16;
975 This->baseShader.limits.constant_bool = 16;
976 This->baseShader.limits.texture = 0;
977 break;
979 default: This->baseShader.limits.temporary = 32;
980 This->baseShader.limits.constant_float = 8;
981 This->baseShader.limits.constant_int = 0;
982 This->baseShader.limits.constant_bool = 0;
983 This->baseShader.limits.texture = 8;
984 FIXME("Unrecognized pixel shader version %lx!\n", version);
988 /* Map the opcode 1-to-1 to the GL code */
989 /* FIXME: fix CMP/CND, get rid of this switch */
990 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
992 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
993 CONST SHADER_OPCODE* curOpcode = arg->opcode;
994 SHADER_BUFFER* buffer = arg->buffer;
995 DWORD dst = arg->dst;
996 DWORD* src = arg->src;
998 unsigned int i;
999 char tmpLine[256];
1001 /* Output token related */
1002 char output_rname[256];
1003 char output_wmask[20];
1004 BOOL saturate = FALSE;
1005 BOOL centroid = FALSE;
1006 BOOL partialprecision = FALSE;
1007 DWORD shift;
1009 strcpy(tmpLine, curOpcode->glname);
1011 /* Process modifiers */
1012 if (0 != (dst & D3DSP_DSTMOD_MASK)) {
1013 DWORD mask = dst & D3DSP_DSTMOD_MASK;
1015 saturate = mask & D3DSPDM_SATURATE;
1016 centroid = mask & D3DSPDM_MSAMPCENTROID;
1017 partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1018 mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1020 if (mask)
1021 FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1023 if (centroid)
1024 FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1026 shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1028 /* Generate input and output registers */
1029 if (curOpcode->num_params > 0) {
1030 char operands[4][100];
1032 /* Generate input register names (with modifiers) */
1033 for (i = 1; i < curOpcode->num_params; ++i)
1034 pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i], This->constants);
1036 /* Handle output register */
1037 get_register_name(dst, output_rname, This->constants);
1038 strcpy(operands[0], output_rname);
1039 get_write_mask(dst, output_wmask);
1040 strcat(operands[0], output_wmask);
1042 switch(curOpcode->opcode) {
1043 case D3DSIO_CMP:
1044 sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""),
1045 operands[0], operands[1], operands[3], operands[2]);
1046 break;
1047 case D3DSIO_CND:
1048 shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", operands[1]);
1049 sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""),
1050 operands[0], operands[2], operands[3]);
1051 break;
1053 default:
1054 if (saturate && (shift == 0))
1055 strcat(tmpLine, "_SAT");
1056 strcat(tmpLine, " ");
1057 strcat(tmpLine, operands[0]);
1058 for (i = 1; i < curOpcode->num_params; i++) {
1059 strcat(tmpLine, ", ");
1060 strcat(tmpLine, operands[i]);
1062 strcat(tmpLine,";\n");
1064 shader_addline(buffer, tmpLine);
1066 /* A shift requires another line. */
1067 if (shift != 0)
1068 pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
1072 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1074 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1075 DWORD dst = arg->dst;
1076 DWORD* src = arg->src;
1077 SHADER_BUFFER* buffer = arg->buffer;
1078 DWORD version = This->baseShader.version;
1080 char reg_dest[40];
1081 char reg_coord[40];
1082 DWORD reg_dest_code;
1083 DWORD reg_sampler_code;
1085 /* All versions have a destination register */
1086 reg_dest_code = dst & D3DSP_REGNUM_MASK;
1087 get_register_name(dst, reg_dest, This->constants);
1089 /* 1.0-1.3: Use destination register as coordinate source.
1090 2.0+: Use provided coordinate source register. */
1091 if (version < 14)
1092 strcpy(reg_coord, reg_dest);
1093 else
1094 pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord, This->constants);
1096 /* 1.0-1.4: Use destination register number as texture code.
1097 2.0+: Use provided sampler number as texure code. */
1098 if (version < 20)
1099 reg_sampler_code = reg_dest_code;
1100 else
1101 reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1103 shader_addline(buffer, "TEX %s, %s, texture[%lu], 2D;\n",
1104 reg_dest, reg_coord, reg_sampler_code);
1107 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1109 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1110 DWORD dst = arg->dst;
1111 DWORD* src = arg->src;
1112 SHADER_BUFFER* buffer = arg->buffer;
1113 DWORD version = This->baseShader.version;
1115 char tmp[20];
1116 get_write_mask(dst, tmp);
1117 if (version != 14) {
1118 DWORD reg = dst & D3DSP_REGNUM_MASK;
1119 shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1120 } else {
1121 DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1122 DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1123 shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1127 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1129 SHADER_BUFFER* buffer = arg->buffer;
1131 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1132 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1133 shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1134 shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1135 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1138 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1140 SHADER_BUFFER* buffer = arg->buffer;
1142 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1143 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1144 shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1145 shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1146 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1149 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1151 SHADER_BUFFER* buffer = arg->buffer;
1153 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1154 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1156 /* FIXME: Should apply the BUMPMAPENV matrix */
1157 shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1158 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1161 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1163 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1164 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1165 SHADER_BUFFER* buffer = arg->buffer;
1167 shader_addline(buffer,
1168 "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1169 *((float*) (arg->src + 0)),
1170 *((float*) (arg->src + 1)),
1171 *((float*) (arg->src + 2)),
1172 *((float*) (arg->src + 3)) );
1174 shader->constants[reg] = 1;
1177 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1179 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1180 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1181 SHADER_BUFFER* buffer = arg->buffer;
1182 char src0_name[50];
1184 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1185 shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, src0_name);
1188 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1190 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1191 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1192 SHADER_BUFFER* buffer = arg->buffer;
1193 char src0_name[50];
1195 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1196 shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, src0_name);
1197 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1200 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1202 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1203 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1204 SHADER_BUFFER* buffer = arg->buffer;
1205 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1206 char src0_name[50];
1208 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1209 shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, src0_name);
1210 current_state.texcoord_w[current_state.current_row++] = reg;
1213 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1215 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1216 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1217 SHADER_BUFFER* buffer = arg->buffer;
1218 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1219 char src0_name[50];
1221 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1222 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1224 /* Cubemap textures will be more used than 3D ones. */
1225 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1226 current_state.current_row = 0;
1229 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1231 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1232 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1233 SHADER_BUFFER* buffer = arg->buffer;
1234 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1235 char src0_name[50];
1237 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1238 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1240 /* Construct the eye-ray vector from w coordinates */
1241 shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1242 shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1243 shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1245 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1246 shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1247 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1248 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1250 /* Cubemap textures will be more used than 3D ones. */
1251 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1252 current_state.current_row = 0;
1255 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1257 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1258 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1259 DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1260 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1261 SHADER_BUFFER* buffer = arg->buffer;
1262 char src0_name[50];
1264 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1265 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1267 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1268 shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1269 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1270 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1272 /* Cubemap textures will be more used than 3D ones. */
1273 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1274 current_state.current_row = 0;
1277 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1278 or GLSL and send it to the card */
1279 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1280 IWineD3DPixelShader *iface,
1281 CONST DWORD *pFunction) {
1283 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1284 SHADER_BUFFER buffer;
1286 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1287 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1288 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1289 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1290 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1291 This->fixupVertexBufferSize = PGMSIZE;
1292 This->fixupVertexBuffer[0] = 0;
1294 buffer.buffer = This->device->fixupVertexBuffer;
1295 #else
1296 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1297 #endif
1298 buffer.bsize = 0;
1299 buffer.lineNo = 0;
1301 /* TODO: Optionally, generate the GLSL shader instead */
1302 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1303 /* Create the hw ARB shader */
1304 shader_addline(&buffer, "!!ARBfp1.0\n");
1306 shader_addline(&buffer, "TEMP TMP;\n"); /* Used in matrix ops */
1307 shader_addline(&buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
1308 shader_addline(&buffer, "TEMP TA;\n"); /* Used for modifiers */
1309 shader_addline(&buffer, "TEMP TB;\n"); /* Used for modifiers */
1310 shader_addline(&buffer, "TEMP TC;\n"); /* Used for modifiers */
1311 shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1312 shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1313 shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1315 /** Call the base shader generation routine to generate most
1316 of the pixel shader string for us */
1317 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1319 if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1320 shader_addline(&buffer, "MOV result.color, R0;\n");
1321 shader_addline(&buffer, "END\n\0");
1323 /* TODO: change to resource.glObjectHandle or something like that */
1324 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1326 TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1327 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1329 TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1330 /* Create the program and check for errors */
1331 GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1332 buffer.bsize, buffer.buffer));
1334 if (glGetError() == GL_INVALID_OPERATION) {
1335 GLint errPos;
1336 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1337 FIXME("HW PixelShader Error at position %d: %s\n",
1338 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1339 This->baseShader.prgId = -1;
1343 #if 1 /* if were using the data buffer of device then we don't need to free it */
1344 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1345 #endif
1348 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1349 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1350 const DWORD* pToken = pFunction;
1351 const SHADER_OPCODE *curOpcode = NULL;
1352 DWORD opcode_token;
1353 DWORD len = 0;
1354 DWORD i;
1355 TRACE("(%p) : Parsing programme\n", This);
1357 if (NULL != pToken) {
1358 while (D3DPS_END() != *pToken) {
1359 if (shader_is_pshader_version(*pToken)) { /** version */
1360 pshader_set_version(This, *pToken);
1361 ++pToken;
1362 ++len;
1363 continue;
1365 if (shader_is_comment(*pToken)) { /** comment */
1366 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1367 ++pToken;
1368 TRACE("//%s\n", (char*)pToken);
1369 pToken += comment_len;
1370 len += comment_len + 1;
1371 continue;
1373 if (!This->baseShader.version) {
1374 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1376 opcode_token = *pToken++;
1377 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1378 len++;
1379 if (NULL == curOpcode) {
1380 int tokens_read;
1382 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1383 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1384 pToken += tokens_read;
1385 len += tokens_read;
1387 } else {
1388 if (curOpcode->opcode == D3DSIO_DCL) {
1389 DWORD usage = *pToken;
1390 DWORD param = *(pToken + 1);
1391 DWORD regtype = shader_get_regtype(param);
1393 /* Only print extended declaration for samplers or 3.0 input registers */
1394 if (regtype == D3DSPR_SAMPLER ||
1395 (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1396 shader_program_dump_decl_usage(usage, param);
1397 else
1398 TRACE("dcl");
1400 shader_dump_ins_modifiers(param);
1401 TRACE(" ");
1402 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1403 pToken += 2;
1404 len += 2;
1406 } else
1407 if (curOpcode->opcode == D3DSIO_DEF) {
1408 TRACE("def c%lu = ", *pToken & 0xFF);
1409 ++pToken;
1410 ++len;
1411 TRACE("%f ,", *(float *)pToken);
1412 ++pToken;
1413 ++len;
1414 TRACE("%f ,", *(float *)pToken);
1415 ++pToken;
1416 ++len;
1417 TRACE("%f ,", *(float *)pToken);
1418 ++pToken;
1419 ++len;
1420 TRACE("%f", *(float *)pToken);
1421 ++pToken;
1422 ++len;
1423 } else {
1425 DWORD param, addr_token;
1426 int tokens_read;
1428 /* Print out predication source token first - it follows
1429 * the destination token. */
1430 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1431 TRACE("(");
1432 shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1433 TRACE(") ");
1436 TRACE("%s", curOpcode->name);
1437 if (curOpcode->num_params > 0) {
1439 /* Destination token */
1440 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1441 pToken, &param, &addr_token);
1442 pToken += tokens_read;
1443 len += tokens_read;
1445 shader_dump_ins_modifiers(param);
1446 TRACE(" ");
1447 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1449 /* Predication token - already printed out, just skip it */
1450 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1451 pToken++;
1452 len++;
1455 /* Other source tokens */
1456 for (i = 1; i < curOpcode->num_params; ++i) {
1458 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1459 pToken, &param, &addr_token);
1460 pToken += tokens_read;
1461 len += tokens_read;
1463 TRACE(", ");
1464 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1468 TRACE("\n");
1471 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1472 } else {
1473 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1476 /* Generate HW shader in needed */
1477 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1478 TRACE("(%p) : Generating hardware program\n", This);
1479 #if 1
1480 IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1481 #endif
1484 TRACE("(%p) : Copying the function\n", This);
1485 /* copy the function ... because it will certainly be released by application */
1486 if (NULL != pFunction) {
1487 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1488 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1489 } else {
1490 This->baseShader.function = NULL;
1493 /* TODO: Some proper return values for failures */
1494 TRACE("(%p) : Returning WINED3D_OK\n", This);
1495 return WINED3D_OK;
1498 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1500 /*** IUnknown methods ***/
1501 IWineD3DPixelShaderImpl_QueryInterface,
1502 IWineD3DPixelShaderImpl_AddRef,
1503 IWineD3DPixelShaderImpl_Release,
1504 /*** IWineD3DBase methods ***/
1505 IWineD3DPixelShaderImpl_GetParent,
1506 /*** IWineD3DBaseShader methods ***/
1507 IWineD3DPixelShaderImpl_SetFunction,
1508 /*** IWineD3DPixelShader methods ***/
1509 IWineD3DPixelShaderImpl_GetDevice,
1510 IWineD3DPixelShaderImpl_GetFunction