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
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, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
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, 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);
754 sprintf(regstr, "R%lu", reg);
758 strcpy(regstr, "fragment.color.primary");
760 strcpy(regstr, "fragment.color.secondary");
765 sprintf(regstr, "C%lu", reg);
767 sprintf(regstr, "C[%lu]", reg);
769 case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
770 sprintf(regstr,"T%lu", reg);
772 case D3DSPR_COLOROUT:
774 sprintf(regstr, "result.color");
776 /* TODO: See GL_ARB_draw_buffers */
777 FIXME("Unsupported write to render target %lu\n", reg);
778 sprintf(regstr, "unsupported_register");
781 case D3DSPR_DEPTHOUT:
782 sprintf(regstr, "result.depth");
785 sprintf(regstr, "oD[%lu]", reg);
787 case D3DSPR_TEXCRDOUT:
788 sprintf(regstr, "oT[%lu]", reg);
791 FIXME("Unhandled register name Type(%ld)\n", regtype);
792 sprintf(regstr, "unrecognized_register");
797 inline static void get_write_mask(const DWORD output_reg, char *write_mask) {
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:
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]);
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,
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,
871 char constants[WINED3D_PSHADER_MAX_CONSTANTS]) {
873 /* Generate a line that does the input modifier computation and return the input register to use */
878 /* Assume a new line will be added */
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) {
887 sprintf(outregstr, "%s%s", regstr, swzstr);
891 sprintf(outregstr, "-%s%s", regstr, swzstr);
895 shader_addline(buffer, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg, regstr);
897 case D3DSPSM_BIASNEG:
898 shader_addline(buffer, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg, regstr);
901 shader_addline(buffer, "MAD T%c, %s, coefmul.x, -one.x;\n", 'A' + tmpreg, regstr);
903 case D3DSPSM_SIGNNEG:
904 shader_addline(buffer, "MAD T%c, %s, -coefmul.x, one.x;\n", 'A' + tmpreg, regstr);
907 shader_addline(buffer, "SUB T%c, one.x, %s;\n", 'A' + tmpreg, regstr);
910 shader_addline(buffer, "ADD T%c, %s, %s;\n", 'A' + tmpreg, regstr, regstr);
913 shader_addline(buffer, "ADD T%c, -%s, -%s;\n", 'A' + tmpreg, regstr, regstr);
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);
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);
924 sprintf(outregstr, "%s%s", regstr, swzstr);
928 /* Return modified or original register, with swizzle */
930 sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
933 void pshader_set_version(
934 IWineD3DPixelShaderImpl *This,
937 DWORD major = (version >> 8) & 0x0F;
938 DWORD minor = version & 0x0F;
940 This->baseShader.hex_version = version;
941 This->baseShader.version = major * 10 + minor;
942 TRACE("ps_%lu_%lu\n", major, minor);
944 This->baseShader.limits.attributes = 0;
945 This->baseShader.limits.address = 0;
947 switch (This->baseShader.version) {
951 case 13: This->baseShader.limits.temporary = 2;
952 This->baseShader.limits.constant_float = 8;
953 This->baseShader.limits.constant_int = 0;
954 This->baseShader.limits.constant_bool = 0;
955 This->baseShader.limits.texture = 4;
958 case 14: This->baseShader.limits.temporary = 6;
959 This->baseShader.limits.constant_float = 8;
960 This->baseShader.limits.constant_int = 0;
961 This->baseShader.limits.constant_bool = 0;
962 This->baseShader.limits.texture = 6;
965 /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */
966 case 20: This->baseShader.limits.temporary = 32;
967 This->baseShader.limits.constant_float = 32;
968 This->baseShader.limits.constant_int = 16;
969 This->baseShader.limits.constant_bool = 16;
970 This->baseShader.limits.texture = 8;
973 case 30: This->baseShader.limits.temporary = 32;
974 This->baseShader.limits.constant_float = 224;
975 This->baseShader.limits.constant_int = 16;
976 This->baseShader.limits.constant_bool = 16;
977 This->baseShader.limits.texture = 0;
980 default: This->baseShader.limits.temporary = 32;
981 This->baseShader.limits.constant_float = 8;
982 This->baseShader.limits.constant_int = 0;
983 This->baseShader.limits.constant_bool = 0;
984 This->baseShader.limits.texture = 8;
985 FIXME("Unrecognized pixel shader version %lx!\n", version);
989 /* Map the opcode 1-to-1 to the GL code */
990 /* FIXME: fix CMP/CND, get rid of this switch */
991 void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
993 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
994 CONST SHADER_OPCODE* curOpcode = arg->opcode;
995 SHADER_BUFFER* buffer = arg->buffer;
996 DWORD dst = arg->dst;
997 DWORD* src = arg->src;
1002 /* Output token related */
1003 char output_rname[256];
1004 char output_wmask[20];
1005 BOOL saturate = FALSE;
1006 BOOL centroid = FALSE;
1007 BOOL partialprecision = FALSE;
1010 strcpy(tmpLine, curOpcode->glname);
1012 /* Process modifiers */
1013 if (0 != (dst & D3DSP_DSTMOD_MASK)) {
1014 DWORD mask = dst & D3DSP_DSTMOD_MASK;
1016 saturate = mask & D3DSPDM_SATURATE;
1017 centroid = mask & D3DSPDM_MSAMPCENTROID;
1018 partialprecision = mask & D3DSPDM_PARTIALPRECISION;
1019 mask &= ~(D3DSPDM_MSAMPCENTROID | D3DSPDM_PARTIALPRECISION | D3DSPDM_SATURATE);
1022 FIXME("Unrecognized modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1025 FIXME("Unhandled modifier(0x%#lx)\n", mask >> D3DSP_DSTMOD_SHIFT);
1027 shift = (dst & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
1029 /* Generate input and output registers */
1030 if (curOpcode->num_params > 0) {
1031 char operands[4][100];
1033 /* Generate input register names (with modifiers) */
1034 for (i = 1; i < curOpcode->num_params; ++i)
1035 pshader_gen_input_modifier_line(buffer, src[i-1], i-1, operands[i], This->constants);
1037 /* Handle output register */
1038 get_register_name(dst, output_rname, This->constants);
1039 strcpy(operands[0], output_rname);
1040 get_write_mask(dst, output_wmask);
1041 strcat(operands[0], output_wmask);
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 pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
1073 void pshader_hw_tex(SHADER_OPCODE_ARG* arg) {
1075 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1076 DWORD dst = arg->dst;
1077 DWORD* src = arg->src;
1078 SHADER_BUFFER* buffer = arg->buffer;
1079 DWORD version = This->baseShader.version;
1083 DWORD reg_dest_code;
1084 DWORD reg_sampler_code;
1086 /* All versions have a destination register */
1087 reg_dest_code = dst & D3DSP_REGNUM_MASK;
1088 get_register_name(dst, reg_dest, This->constants);
1090 /* 1.0-1.3: Use destination register as coordinate source.
1091 2.0+: Use provided coordinate source register. */
1093 strcpy(reg_coord, reg_dest);
1095 pshader_gen_input_modifier_line(buffer, src[0], 0, reg_coord, This->constants);
1097 /* 1.0-1.4: Use destination register number as texture code.
1098 2.0+: Use provided sampler number as texure code. */
1100 reg_sampler_code = reg_dest_code;
1102 reg_sampler_code = src[1] & D3DSP_REGNUM_MASK;
1104 shader_addline(buffer, "TEX %s, %s, texture[%lu], 2D;\n",
1105 reg_dest, reg_coord, reg_sampler_code);
1108 void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) {
1110 IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1111 DWORD dst = arg->dst;
1112 DWORD* src = arg->src;
1113 SHADER_BUFFER* buffer = arg->buffer;
1114 DWORD version = This->baseShader.version;
1117 get_write_mask(dst, tmp);
1118 if (version != 14) {
1119 DWORD reg = dst & D3DSP_REGNUM_MASK;
1120 shader_addline(buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
1122 DWORD reg1 = dst & D3DSP_REGNUM_MASK;
1123 DWORD reg2 = src[0] & D3DSP_REGNUM_MASK;
1124 shader_addline(buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
1128 void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) {
1130 SHADER_BUFFER* buffer = arg->buffer;
1132 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1133 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1134 shader_addline(buffer, "MOV TMP.r, T%lu.a;\n", reg2);
1135 shader_addline(buffer, "MOV TMP.g, T%lu.r;\n", reg2);
1136 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1139 void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
1141 SHADER_BUFFER* buffer = arg->buffer;
1143 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1144 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1145 shader_addline(buffer, "MOV TMP.r, T%lu.g;\n", reg2);
1146 shader_addline(buffer, "MOV TMP.g, T%lu.b;\n", reg2);
1147 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1150 void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
1152 SHADER_BUFFER* buffer = arg->buffer;
1154 DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1155 DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1157 /* FIXME: Should apply the BUMPMAPENV matrix */
1158 shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
1159 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
1162 void pshader_hw_def(SHADER_OPCODE_ARG* arg) {
1164 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1165 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1166 SHADER_BUFFER* buffer = arg->buffer;
1168 shader_addline(buffer,
1169 "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
1170 *((float*) (arg->src + 0)),
1171 *((float*) (arg->src + 1)),
1172 *((float*) (arg->src + 2)),
1173 *((float*) (arg->src + 3)) );
1175 shader->constants[reg] = 1;
1178 void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1180 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1181 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1182 SHADER_BUFFER* buffer = arg->buffer;
1185 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1186 shader_addline(buffer, "DP3 TMP.x, T%lu, %s;\n", reg, src0_name);
1189 void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1191 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1192 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1193 SHADER_BUFFER* buffer = arg->buffer;
1196 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1197 shader_addline(buffer, "DP3 TMP.y, T%lu, %s;\n", reg, src0_name);
1198 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
1201 void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1203 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1204 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1205 SHADER_BUFFER* buffer = arg->buffer;
1206 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1209 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1210 shader_addline(buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state.current_row, reg, src0_name);
1211 current_state.texcoord_w[current_state.current_row++] = reg;
1214 void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1216 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1217 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1218 SHADER_BUFFER* buffer = arg->buffer;
1219 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1222 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1223 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1225 /* Cubemap textures will be more used than 3D ones. */
1226 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1227 current_state.current_row = 0;
1230 void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1232 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1233 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1234 SHADER_BUFFER* buffer = arg->buffer;
1235 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1238 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1239 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1241 /* Construct the eye-ray vector from w coordinates */
1242 shader_addline(buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[0]);
1243 shader_addline(buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state.texcoord_w[1]);
1244 shader_addline(buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
1246 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1247 shader_addline(buffer, "DP3 TMP.w, TMP, TMP2;\n");
1248 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1249 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
1251 /* Cubemap textures will be more used than 3D ones. */
1252 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1253 current_state.current_row = 0;
1256 void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1258 IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1259 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1260 DWORD reg3 = arg->src[1] & D3DSP_REGNUM_MASK;
1261 SHADER_PARSE_STATE current_state = shader->baseShader.parse_state;
1262 SHADER_BUFFER* buffer = arg->buffer;
1265 pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name, shader->constants);
1266 shader_addline(buffer, "DP3 TMP.z, T%lu, %s;\n", reg, src0_name);
1268 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1269 shader_addline(buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
1270 shader_addline(buffer, "MUL TMP, TMP.w, TMP;\n");
1271 shader_addline(buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
1273 /* Cubemap textures will be more used than 3D ones. */
1274 shader_addline(buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
1275 current_state.current_row = 0;
1278 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1279 or GLSL and send it to the card */
1280 inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
1281 IWineD3DPixelShader *iface,
1282 CONST DWORD *pFunction) {
1284 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1285 SHADER_BUFFER buffer;
1287 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1288 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1289 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1290 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1291 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1292 This->fixupVertexBufferSize = PGMSIZE;
1293 This->fixupVertexBuffer[0] = 0;
1295 buffer.buffer = This->device->fixupVertexBuffer;
1297 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1302 if (wined3d_settings.shader_mode == SHADER_GLSL) {
1304 /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
1305 GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
1307 /* Generate the bulk of the shader code */
1308 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1310 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
1311 if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1312 shader_addline(&buffer, "glFragColor = R0;\n");
1313 shader_addline(&buffer, "}\n\0");
1315 TRACE("Compiling shader object %u\n", shader_obj);
1316 GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
1317 GL_EXTCALL(glCompileShaderARB(shader_obj));
1318 print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
1320 /* Store the shader object */
1321 This->baseShader.prgId = shader_obj;
1323 } else if (wined3d_settings.shader_mode == SHADER_ARB) {
1324 /* Create the hw ARB shader */
1325 shader_addline(&buffer, "!!ARBfp1.0\n");
1327 shader_addline(&buffer, "TEMP TMP;\n"); /* Used in matrix ops */
1328 shader_addline(&buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
1329 shader_addline(&buffer, "TEMP TA;\n"); /* Used for modifiers */
1330 shader_addline(&buffer, "TEMP TB;\n"); /* Used for modifiers */
1331 shader_addline(&buffer, "TEMP TC;\n"); /* Used for modifiers */
1332 shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1333 shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1334 shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1336 /** Call the base shader generation routine to generate most
1337 of the pixel shader string for us */
1338 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1340 if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
1341 shader_addline(&buffer, "MOV result.color, R0;\n");
1342 shader_addline(&buffer, "END\n\0");
1344 /* TODO: change to resource.glObjectHandle or something like that */
1345 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1347 TRACE("Creating a hw pixel shader, prg=%d\n", This->baseShader.prgId);
1348 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->baseShader.prgId));
1350 TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
1351 /* Create the program and check for errors */
1352 GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1353 buffer.bsize, buffer.buffer));
1355 if (glGetError() == GL_INVALID_OPERATION) {
1357 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1358 FIXME("HW PixelShader Error at position %d: %s\n",
1359 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1360 This->baseShader.prgId = -1;
1364 #if 1 /* if were using the data buffer of device then we don't need to free it */
1365 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1369 HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
1370 IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
1371 const DWORD* pToken = pFunction;
1372 const SHADER_OPCODE *curOpcode = NULL;
1376 TRACE("(%p) : Parsing programme\n", This);
1378 if (NULL != pToken) {
1379 while (D3DPS_END() != *pToken) {
1380 if (shader_is_pshader_version(*pToken)) { /** version */
1381 pshader_set_version(This, *pToken);
1386 if (shader_is_comment(*pToken)) { /** comment */
1387 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1389 TRACE("//%s\n", (char*)pToken);
1390 pToken += comment_len;
1391 len += comment_len + 1;
1394 if (!This->baseShader.version) {
1395 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This);
1397 opcode_token = *pToken++;
1398 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1400 if (NULL == curOpcode) {
1403 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1404 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1405 pToken += tokens_read;
1409 if (curOpcode->opcode == D3DSIO_DCL) {
1410 DWORD usage = *pToken;
1411 DWORD param = *(pToken + 1);
1412 DWORD regtype = shader_get_regtype(param);
1414 /* Only print extended declaration for samplers or 3.0 input registers */
1415 if (regtype == D3DSPR_SAMPLER ||
1416 (This->baseShader.version >= 30 && regtype == D3DSPR_INPUT))
1417 shader_program_dump_decl_usage(usage, param);
1421 shader_dump_ins_modifiers(param);
1423 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1428 if (curOpcode->opcode == D3DSIO_DEF) {
1429 TRACE("def c%lu = ", *pToken & 0xFF);
1432 TRACE("%f ,", *(float *)pToken);
1435 TRACE("%f ,", *(float *)pToken);
1438 TRACE("%f ,", *(float *)pToken);
1441 TRACE("%f", *(float *)pToken);
1446 DWORD param, addr_token;
1449 /* Print out predication source token first - it follows
1450 * the destination token. */
1451 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1453 shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1457 TRACE("%s", curOpcode->name);
1458 if (curOpcode->num_params > 0) {
1460 /* Destination token */
1461 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1462 pToken, ¶m, &addr_token);
1463 pToken += tokens_read;
1466 shader_dump_ins_modifiers(param);
1468 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1470 /* Predication token - already printed out, just skip it */
1471 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1476 /* Other source tokens */
1477 for (i = 1; i < curOpcode->num_params; ++i) {
1479 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1480 pToken, ¶m, &addr_token);
1481 pToken += tokens_read;
1485 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1492 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1494 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1497 /* Generate HW shader in needed */
1498 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1499 TRACE("(%p) : Generating hardware program\n", This);
1501 IWineD3DPixelShaderImpl_GenerateShader(iface, pFunction);
1505 TRACE("(%p) : Copying the function\n", This);
1506 /* copy the function ... because it will certainly be released by application */
1507 if (NULL != pFunction) {
1508 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1509 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1511 This->baseShader.function = NULL;
1514 /* TODO: Some proper return values for failures */
1515 TRACE("(%p) : Returning WINED3D_OK\n", This);
1519 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
1521 /*** IUnknown methods ***/
1522 IWineD3DPixelShaderImpl_QueryInterface,
1523 IWineD3DPixelShaderImpl_AddRef,
1524 IWineD3DPixelShaderImpl_Release,
1525 /*** IWineD3DBase methods ***/
1526 IWineD3DPixelShaderImpl_GetParent,
1527 /*** IWineD3DBaseShader methods ***/
1528 IWineD3DPixelShaderImpl_SetFunction,
1529 /*** IWineD3DPixelShader methods ***/
1530 IWineD3DPixelShaderImpl_GetDevice,
1531 IWineD3DPixelShaderImpl_GetFunction