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