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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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)
40 # define TRACE_VSVECTOR(name)
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);
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;
72 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
73 ref = InterlockedDecrement(&This->ref);
75 HeapFree(GetProcessHeap(), 0, This);
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);
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);
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);
113 *pSizeOfData = This->baseShader.functionLength;
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;
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);
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) {
160 d->y = s0->y * s1->y;
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) {
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;
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) {
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);
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;
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;
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) {
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;
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) {
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));
405 void pshader_texcoord(WINED3DSHADERVECTOR* d) {
409 void pshader_texkill(WINED3DSHADERVECTOR* d) {
413 void pshader_tex(WINED3DSHADERVECTOR* d) {
416 void pshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
420 void pshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424 void pshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
428 void pshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
432 void pshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
436 void pshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
440 void pshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
444 void pshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
448 void pshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
452 void pshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
456 void pshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
460 void pshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
464 void pshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
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) {
473 void pshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
477 void pshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
481 void pshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
485 void pshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
489 void pshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
493 void pshader_texdepth(WINED3DSHADERVECTOR* d) {
497 void pshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
501 void pshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
505 void pshader_call(WINED3DSHADERVECTOR* d) {
509 void pshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
513 void pshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
517 void pshader_ret(void) {
521 void pshader_endloop(void) {
525 void pshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
529 void pshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
533 void pshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
537 void pshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
541 void pshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
545 void pshader_rep(WINED3DSHADERVECTOR* d) {
549 void pshader_endrep(void) {
553 void pshader_if(WINED3DSHADERVECTOR* d) {
557 void pshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
561 void pshader_else(void) {
565 void pshader_label(WINED3DSHADERVECTOR* d) {
569 void pshader_endif(void) {
573 void pshader_break(void) {
577 void pshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
581 void pshader_breakp(WINED3DSHADERVECTOR* d) {
585 void pshader_defb(WINED3DSHADERVECTOR* d) {
589 void pshader_defi(WINED3DSHADERVECTOR* d) {
593 void pshader_dp2add(WINED3DSHADERVECTOR* d) {
597 void pshader_dsx(WINED3DSHADERVECTOR* d) {
601 void pshader_dsy(WINED3DSHADERVECTOR* d) {
605 void pshader_texldd(WINED3DSHADERVECTOR* d) {
609 void pshader_setp(WINED3DSHADERVECTOR* d) {
613 void pshader_texldl(WINED3DSHADERVECTOR* d) {
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[] = {
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,
667 MUL vec.xyz, vec, tmp;
668 but I think this is better because it accounts for w properly.
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},
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},
713 {D3DSIO_TEXCOORD, "texcoord", "undefined", 1, pshader_texcoord, pshader_hw_texcoord, NULL, 0, D3DPS_VERSION(1,3)},
714 {D3DSIO_TEXCOORD, "texcrd", "undefined", 2, pshader_texcoord, pshader_hw_texcoord, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
715 {D3DSIO_TEXKILL, "texkill", "KIL", 1, pshader_texkill, pshader_hw_map2gl, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
716 {D3DSIO_TEX, "tex", "undefined", 1, pshader_tex, pshader_hw_tex, NULL, 0, D3DPS_VERSION(1,3)},
717 {D3DSIO_TEX, "texld", "undefined", 2, pshader_texld, pshader_hw_tex, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
718 {D3DSIO_TEX, "texld", "undefined", 3, pshader_texld, pshader_hw_tex, NULL, D3DPS_VERSION(2,0), -1},
719 {D3DSIO_TEXBEM, "texbem", "undefined", 2, pshader_texbem, pshader_hw_texbem, NULL, 0, D3DPS_VERSION(1,3)},
720 {D3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 2, pshader_texbeml, NULL, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
721 {D3DSIO_TEXREG2AR,"texreg2ar","undefined", 2, pshader_texreg2ar, pshader_hw_texreg2ar, NULL, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
722 {D3DSIO_TEXREG2GB,"texreg2gb","undefined", 2, pshader_texreg2gb, pshader_hw_texreg2gb, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
723 {D3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 2, pshader_texreg2rgb, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
724 {D3DSIO_TEXM3x2PAD, "texm3x2pad", "undefined", 2, pshader_texm3x2pad, pshader_hw_texm3x2pad, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
725 {D3DSIO_TEXM3x2TEX, "texm3x2tex", "undefined", 2, pshader_texm3x2tex, pshader_hw_texm3x2tex, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
726 {D3DSIO_TEXM3x3PAD, "texm3x3pad", "undefined", 2, pshader_texm3x3pad, pshader_hw_texm3x3pad, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
727 {D3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 2, pshader_texm3x3diff, NULL, NULL, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
728 {D3DSIO_TEXM3x3SPEC, "texm3x3spec", "undefined", 3, pshader_texm3x3spec, pshader_hw_texm3x3spec, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
729 {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe", "undefined", 2, pshader_texm3x3vspec, pshader_hw_texm3x3vspec, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
730 {D3DSIO_TEXM3x3TEX, "texm3x3tex", "undefined", 2, pshader_texm3x3tex, pshader_hw_texm3x3tex, NULL, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
731 {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 2, pshader_texdp3tex, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
732 {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 2, pshader_texm3x2depth, NULL, NULL, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
733 {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 2, pshader_texdp3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
734 {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 2, pshader_texm3x3, NULL, NULL, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
735 {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL, 1, pshader_texdepth, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
736 {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 3, pshader_bem, NULL, NULL, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
737 /* TODO: dp2add can be made out of multiple instuctions */
738 {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 2, pshader_dsx, NULL, NULL, 0, 0},
739 {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 2, pshader_dsy, NULL, NULL, 0, 0},
740 {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 2, pshader_texldd, NULL, NULL, 0, 0},
741 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, pshader_setp, NULL, NULL, 0, 0},
742 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, pshader_texldl, NULL, NULL, 0, 0},
743 {D3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, pshader_nop, NULL, NULL, 0, 0},
744 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
747 inline static void get_register_name(const DWORD param, char* regstr, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
748 static const char* rastout_reg_names[] = { "oC0", "oC1", "oC2", "oC3", "oDepth" };
750 DWORD reg = param & D3DSP_REGNUM_MASK;
751 DWORD regtype = shader_get_regtype(param);
755 sprintf(regstr, "R%lu", reg);
759 strcpy(regstr, "fragment.color.primary");
761 strcpy(regstr, "fragment.color.secondary");
766 sprintf(regstr, "C%lu", reg);
768 sprintf(regstr, "program.env[%lu]", reg);
770 case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
771 sprintf(regstr,"T%lu", reg);
774 sprintf(regstr, "%s", rastout_reg_names[reg]);
777 sprintf(regstr, "oD[%lu]", reg);
779 case D3DSPR_TEXCRDOUT:
780 sprintf(regstr, "oT[%lu]", reg);
783 FIXME("Unhandled register name Type(%ld)\n", regtype);
788 inline static void get_write_mask(const DWORD output_reg, char *write_mask) {
790 if ((output_reg & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
791 strcat(write_mask, ".");
792 if (output_reg & D3DSP_WRITEMASK_0) strcat(write_mask, "r");
793 if (output_reg & D3DSP_WRITEMASK_1) strcat(write_mask, "g");
794 if (output_reg & D3DSP_WRITEMASK_2) strcat(write_mask, "b");
795 if (output_reg & D3DSP_WRITEMASK_3) strcat(write_mask, "a");
799 inline static void get_input_register_swizzle(const DWORD instr, char *swzstring) {
800 static const char swizzle_reg_chars[] = "rgba";
801 DWORD swizzle = (instr & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
802 DWORD swizzle_x = swizzle & 0x03;
803 DWORD swizzle_y = (swizzle >> 2) & 0x03;
804 DWORD swizzle_z = (swizzle >> 4) & 0x03;
805 DWORD swizzle_w = (swizzle >> 6) & 0x03;
807 * swizzle bits fields:
811 if ((D3DSP_NOSWIZZLE >> D3DSP_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
812 if (swizzle_x == swizzle_y &&
813 swizzle_x == swizzle_z &&
814 swizzle_x == swizzle_w) {
815 sprintf(swzstring, ".%c", swizzle_reg_chars[swizzle_x]);
817 sprintf(swzstring, ".%c%c%c%c",
818 swizzle_reg_chars[swizzle_x],
819 swizzle_reg_chars[swizzle_y],
820 swizzle_reg_chars[swizzle_z],
821 swizzle_reg_chars[swizzle_w]);
826 static const char* shift_tab[] = {
827 "dummy", /* 0 (none) */
828 "coefmul.x", /* 1 (x2) */
829 "coefmul.y", /* 2 (x4) */
830 "coefmul.z", /* 3 (x8) */
831 "coefmul.w", /* 4 (x16) */
832 "dummy", /* 5 (x32) */
833 "dummy", /* 6 (x64) */
834 "dummy", /* 7 (x128) */
835 "dummy", /* 8 (d256) */
836 "dummy", /* 9 (d128) */
837 "dummy", /* 10 (d64) */
838 "dummy", /* 11 (d32) */
839 "coefdiv.w", /* 12 (d16) */
840 "coefdiv.z", /* 13 (d8) */
841 "coefdiv.y", /* 14 (d4) */
842 "coefdiv.x" /* 15 (d2) */
845 inline static void gen_output_modifier_line(int saturate, char *write_mask, int shift, char *regstr, char* line) {
846 /* Generate a line that does the output modifier computation */
847 sprintf(line, "MUL%s %s%s, %s, %s;", saturate ? "_SAT" : "", regstr, write_mask, regstr, shift_tab[shift]);
850 inline static int gen_input_modifier_line(const DWORD instr, int tmpreg, char *outregstr, char *line, char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
851 /* Generate a line that does the input modifier computation and return the input register to use */
852 static char regstr[256];
853 static char tmpline[256];
856 /* Assume a new line will be added */
859 /* Get register name */
860 get_register_name(instr, regstr, constants);
862 TRACE(" Register name %s\n", regstr);
863 switch (instr & D3DSP_SRCMOD_MASK) {
865 strcpy(outregstr, regstr);
869 sprintf(outregstr, "-%s", regstr);
873 sprintf(line, "ADD T%c, %s, -coefdiv.x;", 'A' + tmpreg, regstr);
875 case D3DSPSM_BIASNEG:
876 sprintf(line, "ADD T%c, -%s, coefdiv.x;", 'A' + tmpreg, regstr);
879 sprintf(line, "MAD T%c, %s, coefmul.x, -one.x;", 'A' + tmpreg, regstr);
881 case D3DSPSM_SIGNNEG:
882 sprintf(line, "MAD T%c, %s, -coefmul.x, one.x;", 'A' + tmpreg, regstr);
885 sprintf(line, "SUB T%c, one.x, %s;", 'A' + tmpreg, regstr);
888 sprintf(line, "ADD T%c, %s, %s;", 'A' + tmpreg, regstr, regstr);
891 sprintf(line, "ADD T%c, -%s, -%s;", 'A' + tmpreg, regstr, regstr);
894 sprintf(line, "RCP T%c, %s.z;", 'A' + tmpreg, regstr);
895 sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
896 strcat(line, "\n"); /* Hack */
897 strcat(line, tmpline);
900 sprintf(line, "RCP T%c, %s.w;", 'A' + tmpreg, regstr);
901 sprintf(tmpline, "MUL T%c, %s, T%c;", 'A' + tmpreg, regstr, 'A' + tmpreg);
902 strcat(line, "\n"); /* Hack */
903 strcat(line, tmpline);
906 strcpy(outregstr, regstr);
911 /* Substitute the register name */
912 sprintf(outregstr, "T%c", 'A' + tmpreg);
918 void pshader_set_version(
919 IWineD3DPixelShaderImpl *This,
922 DWORD major = (version >> 8) & 0x0F;
923 DWORD minor = version & 0x0F;
925 This->baseShader.hex_version = version;
926 This->baseShader.version = major * 10 + minor;
927 TRACE("ps_%lu_%lu\n", major, minor);
929 This->baseShader.limits.address = 0;
931 switch (This->baseShader.version) {
935 case 13: This->baseShader.limits.temporary = 2;
936 This->baseShader.limits.constant_float = 8;
937 This->baseShader.limits.constant_int = 0;
938 This->baseShader.limits.constant_bool = 0;
939 This->baseShader.limits.texture = 4;
942 case 14: This->baseShader.limits.temporary = 6;
943 This->baseShader.limits.constant_float = 8;
944 This->baseShader.limits.constant_int = 0;
945 This->baseShader.limits.constant_bool = 0;
946 This->baseShader.limits.texture = 6;
949 /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */
950 case 20: This->baseShader.limits.temporary = 32;
951 This->baseShader.limits.constant_float = 32;
952 This->baseShader.limits.constant_int = 16;
953 This->baseShader.limits.constant_bool = 16;
954 This->baseShader.limits.texture = 8;
957 case 30: This->baseShader.limits.temporary = 32;
958 This->baseShader.limits.constant_float = 224;
959 This->baseShader.limits.constant_int = 16;
960 This->baseShader.limits.constant_bool = 16;
961 This->baseShader.limits.texture = 0;
964 default: This->baseShader.limits.temporary = 32;
965 This->baseShader.limits.constant_float = 8;
966 This->baseShader.limits.constant_int = 0;
967 This->baseShader.limits.constant_bool = 0;
968 This->baseShader.limits.texture = 8;
969 FIXME("Unrecognized pixel shader version %lx!\n", version);
973 /* Map the opcode 1-to-1 to the GL code */
974 /* FIXME: fix CMP/CND, get rid of this switch */
975 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
977 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
978 CONST SHADER_OPCODE* curOpcode = arg->opcode;
979 SHADER_BUFFER* buffer = arg->buffer;
980 DWORD dst = arg->dst;
981 DWORD* src = arg->src;
986 /* Output token related */
987 char output_rname[256];
988 char output_wmask[20];
989 BOOL saturate = FALSE;
990 BOOL centroid = FALSE;
991 BOOL partialprecision = FALSE;
994 TRACE("Appending glname %s to tmpLine\n", curOpcode->glname);
995 strcpy(tmpLine, curOpcode->glname);
997 /* Process modifiers */
998 if (0 != (dst & D3DSP_DSTMOD_MASK)) {
999 DWORD mask = dst & D3DSP_DSTMOD_MASK;
1001 saturate = mask & D3DSPDM_SATURATE;
1002 centroid = mask & D3DSPDM_MSAMPCENTROID;
1003 partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1004 mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1007 FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1010 FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1012 shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1014 /* Generate input and output registers */
1015 if (curOpcode->num_params > 0) {
1017 char operands[4][100];
1021 /* Generate lines that handle input modifier computation */
1022 for (i = 1; i < curOpcode->num_params; ++i) {
1023 TRACE("(%p) : Param %u token %lx\n", This, i, src[i - 1]);
1024 if (gen_input_modifier_line(src[i - 1], i - 1, regs[i - 1], tmpOp, This->constants))
1025 shader_addline(buffer, tmpOp);
1028 /* Handle output register */
1029 get_register_name(dst, output_rname, This->constants);
1030 strcpy(operands[0], output_rname);
1031 get_write_mask(dst, output_wmask);
1032 strcat(operands[0], output_wmask);
1034 /* This function works because of side effects from gen_input_modifier_line */
1035 /* Handle input registers */
1036 for (i = 1; i < curOpcode->num_params; ++i) {
1037 TRACE("(%p) : Regs = %s\n", This, regs[i - 1]);
1038 strcpy(operands[i], regs[i - 1]);
1039 get_input_register_swizzle(src[i - 1], swzstring);
1040 strcat(operands[i], swzstring);
1043 switch(curOpcode->opcode) {
1045 sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""),
1046 operands[0], operands[1], operands[3], operands[2]);
1049 shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", operands[1]);
1050 sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""),
1051 operands[0], operands[2], operands[3]);
1055 if (saturate && (shift == 0))
1056 strcat(tmpLine, "_SAT");
1057 strcat(tmpLine, " ");
1058 strcat(tmpLine, operands[0]);
1059 for (i = 1; i < curOpcode->num_params; i++) {
1060 strcat(tmpLine, ", ");
1061 strcat(tmpLine, operands[i]);
1063 strcat(tmpLine,";\n");
1065 shader_addline(buffer, tmpLine);
1067 /* A shift requires another line. */
1069 gen_output_modifier_line(saturate, output_wmask, shift, output_rname, tmpLine);
1070 shader_addline(buffer, tmpLine);
1075 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1077 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1078 DWORD dst = arg->dst;
1079 DWORD* src = arg->src;
1080 SHADER_BUFFER* buffer = arg->buffer;
1081 DWORD version = This->baseShader.version;
1086 char reg_coord_swz[20] = "";
1087 DWORD reg_dest_code;
1088 DWORD reg_sampler_code;
1090 /* All versions have a destination register */
1091 reg_dest_code = dst & D3DSP_REGNUM_MASK;
1092 get_register_name(dst, reg_dest, This->constants);
1094 /* 1.0-1.3: Use destination register as coordinate source. No modifiers.
1095 1.4: Use provided coordinate source register. _dw, _dz, swizzle allowed.
1096 2.0+: Use provided coordinate source register. No modifiers.
1097 3.0+: Use provided coordinate source register. Swizzle allowed */
1099 strcpy(reg_coord, reg_dest);
1100 else if (version == 14) {
1101 if (gen_input_modifier_line(src[0], 0, reg_coord, tmpLine, This->constants))
1102 shader_addline(buffer, tmpLine);
1103 get_input_register_swizzle(src[0], reg_coord_swz);
1105 else if (version > 14 && version < 30)
1106 get_register_name(src[0], reg_coord, This->constants);
1107 else if (version >= 30) {
1108 get_input_register_swizzle(src[0], reg_coord_swz);
1109 get_register_name(src[0], reg_coord, This->constants);
1112 /* 1.0-1.4: Use destination register number as texture code.
1113 2.0+: Use provided sampler number as texure code. */
1115 reg_sampler_code = reg_dest_code;
1117 reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1119 shader_addline(buffer, "TEX %s, %s%s, texture[%lu], 2D;\n",
1120 reg_dest, reg_coord, reg_coord_swz, reg_sampler_code);
1123 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1125 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1126 DWORD dst = arg->dst;
1127 DWORD* src = arg->src;
1128 SHADER_BUFFER* buffer = arg->buffer;
1129 DWORD version = This->baseShader.version;
1132 get_write_mask(dst, tmp);
1133 if (version != 14) {
1134 DWORD reg = dst & D3DSP_REGNUM_MASK;
1135 shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1137 DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1138 DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1139 shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1143 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1145 SHADER_BUFFER* buffer = arg->buffer;
1147 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1148 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1149 shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1150 shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1151 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1154 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1156 SHADER_BUFFER* buffer = arg->buffer;
1158 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1159 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1160 shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1161 shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1162 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1165 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1167 SHADER_BUFFER* buffer = arg->buffer;
1169 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1170 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1172 /* FIXME: Should apply the BUMPMAPENV matrix */
1173 shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1174 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1177 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1179 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1180 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1181 SHADER_BUFFER* buffer = arg->buffer;
1183 shader_addline(buffer,
1184 "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1185 *((float*) (arg->src + 0)),
1186 *((float*) (arg->src + 1)),
1187 *((float*) (arg->src + 2)),
1188 *((float*) (arg->src + 3)) );
1190 shader->constants[reg] = 1;
1193 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1195 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1196 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1197 SHADER_BUFFER* buffer = arg->buffer;
1201 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1202 shader_addline(buffer, tmpLine);
1203 shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, buf);
1206 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1208 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1209 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1210 SHADER_BUFFER* buffer = arg->buffer;
1214 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1215 shader_addline(buffer, tmpLine);
1216 shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, buf);
1217 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1220 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1222 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1223 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1224 SHADER_BUFFER* buffer = arg->buffer;
1225 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1229 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1230 shader_addline(buffer, tmpLine);
1231 shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, buf);
1232 current_state.texcoord_w[current_state.current_row++] = reg;
1235 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1237 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1238 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1239 SHADER_BUFFER* buffer = arg->buffer;
1240 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1244 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1245 shader_addline(buffer, tmpLine);
1246 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1248 /* Cubemap textures will be more used than 3D ones. */
1249 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1250 current_state.current_row = 0;
1253 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1255 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1256 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1257 SHADER_BUFFER* buffer = arg->buffer;
1258 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1262 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1263 shader_addline(buffer, tmpLine);
1264 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1266 /* Construct the eye-ray vector from w coordinates */
1267 shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1268 shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1269 shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1271 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1272 shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1273 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1274 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1276 /* Cubemap textures will be more used than 3D ones. */
1277 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1278 current_state.current_row = 0;
1281 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1283 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1284 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1285 DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1286 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1287 SHADER_BUFFER* buffer = arg->buffer;
1291 if (gen_input_modifier_line(arg->src[0], 0, buf, tmpLine, shader->constants))
1292 shader_addline(buffer, tmpLine);
1293 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
1295 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1296 shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1297 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1298 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1300 /* Cubemap textures will be more used than 3D ones. */
1301 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1302 current_state.current_row = 0;
1305 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1306 or GLSL and send it to the card */
1307 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1308 IWineD3DPixelShader *iface,
1309 CONST DWORD *pFunction) {
1311 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1312 SHADER_BUFFER buffer;
1314 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1315 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1316 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1317 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1318 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1319 This->fixupVertexBufferSize = PGMSIZE;
1320 This->fixupVertexBuffer[0] = 0;
1322 buffer.buffer = This->device->fixupVertexBuffer;
1324 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1329 /* TODO: Optionally, generate the GLSL shader instead */
1330 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1331 /* Create the hw ARB shader */
1332 shader_addline(&buffer, "!!ARBfp1.0\n");
1334 shader_addline(&buffer, "TEMP TMP;\n"); /* Used in matrix ops */
1335 shader_addline(&buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
1336 shader_addline(&buffer, "TEMP TA;\n"); /* Used for modifiers */
1337 shader_addline(&buffer, "TEMP TB;\n"); /* Used for modifiers */
1338 shader_addline(&buffer, "TEMP TC;\n"); /* Used for modifiers */
1339 shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1340 shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1341 shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1343 /** Call the base shader generation routine to generate most
1344 of the pixel shader string for us */
1345 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1347 /*FIXME: This next line isn't valid for certain pixel shader versions */
1348 shader_addline(&buffer, "MOV result.color, R0;\n");
1349 shader_addline(&buffer, "END\n\0");
1351 /* TODO: change to resource.glObjectHandle or something like that */
1352 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1354 TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1355 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1357 TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1358 /* Create the program and check for errors */
1359 GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1360 buffer.bsize, buffer.buffer));
1362 if (glGetError() == GL_INVALID_OPERATION) {
1364 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1365 FIXME("HW PixelShader Error at position %d: %s\n",
1366 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1367 This->baseShader.prgId = -1;
1371 #if 1 /* if were using the data buffer of device then we don't need to free it */
1372 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1376 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1377 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1378 const DWORD* pToken = pFunction;
1379 const SHADER_OPCODE *curOpcode = NULL;
1383 TRACE("(%p) : Parsing programme\n", This);
1385 if (NULL != pToken) {
1386 while (D3DPS_END() != *pToken) {
1387 if (shader_is_pshader_version(*pToken)) { /** version */
1388 pshader_set_version(This, *pToken);
1393 if (shader_is_comment(*pToken)) { /** comment */
1394 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1396 TRACE("//%s\n", (char*)pToken);
1397 pToken += comment_len;
1398 len += comment_len + 1;
1401 if (!This->baseShader.version) {
1402 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1404 opcode_token = *pToken++;
1405 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1407 if (NULL == curOpcode) {
1410 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1411 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1412 pToken += tokens_read;
1416 if (curOpcode->opcode == D3DSIO_DCL) {
1417 DWORD usage = *pToken;
1418 DWORD param = *(pToken + 1);
1419 DWORD regtype = shader_get_regtype(param);
1421 /* Only print extended declaration for samplers or 3.0 input registers */
1422 if (regtype == D3DSPR_SAMPLER ||
1423 (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1424 shader_program_dump_decl_usage(usage, param);
1428 shader_dump_ins_modifiers(param);
1430 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1435 if (curOpcode->opcode == D3DSIO_DEF) {
1436 TRACE("def c%lu = ", *pToken & 0xFF);
1439 TRACE("%f ,", *(float *)pToken);
1442 TRACE("%f ,", *(float *)pToken);
1445 TRACE("%f ,", *(float *)pToken);
1448 TRACE("%f", *(float *)pToken);
1453 DWORD param, addr_token;
1456 TRACE("%s", curOpcode->name);
1457 if (curOpcode->num_params > 0) {
1459 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1460 pToken, ¶m, &addr_token);
1461 pToken += tokens_read;
1464 shader_dump_ins_modifiers(param);
1466 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1468 for (i = 1; i < curOpcode->num_params; ++i) {
1470 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1471 pToken, ¶m, &addr_token);
1472 pToken += tokens_read;
1476 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1483 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1485 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1488 /* Generate HW shader in needed */
1489 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1490 TRACE("(%p) : Generating hardware program\n", This);
1492 IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1496 TRACE("(%p) : Copying the function\n", This);
1497 /* copy the function ... because it will certainly be released by application */
1498 if (NULL != pFunction) {
1499 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1500 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1502 This->baseShader.function = NULL;
1505 /* TODO: Some proper return values for failures */
1506 TRACE("(%p) : Returning WINED3D_OK\n", This);
1510 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1512 /*** IUnknown methods ***/
1513 IWineD3DPixelShaderImpl_QueryInterface,
1514 IWineD3DPixelShaderImpl_AddRef,
1515 IWineD3DPixelShaderImpl_Release,
1516 /*** IWineD3DBase methods ***/
1517 IWineD3DPixelShaderImpl_GetParent,
1518 /*** IWineD3DBaseShader methods ***/
1519 IWineD3DPixelShaderImpl_SetFunction,
1520 /*** IWineD3DPixelShader methods ***/
1521 IWineD3DPixelShaderImpl_GetDevice,
1522 IWineD3DPixelShaderImpl_GetFunction