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 static 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 static 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 static 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
);
76 if (wined3d_settings
.shader_mode
== SHADER_GLSL
&& This
->baseShader
.prgId
!= 0) {
77 /* If this shader is still attached to a program, GL will perform a lazy delete */
78 TRACE("Deleting shader object %u\n", This
->baseShader
.prgId
);
79 GL_EXTCALL(glDeleteObjectARB(This
->baseShader
.prgId
));
80 checkGLcall("glDeleteObjectARB");
86 /* TODO: At the momeny the function parser is single pass, it achievs this
87 by passing constants to a couple of functions where they are then modified.
88 At some point the parser need to be made two pass (So that GLSL can be used if it's required by the shader)
89 when happens constants should be worked out in the first pass to tidy up the second pass a bit.
92 /* *******************************************
93 IWineD3DPixelShader IWineD3DPixelShader parts follow
94 ******************************************* */
96 static HRESULT WINAPI
IWineD3DPixelShaderImpl_GetParent(IWineD3DPixelShader
*iface
, IUnknown
** parent
){
97 IWineD3DPixelShaderImpl
*This
= (IWineD3DPixelShaderImpl
*)iface
;
99 *parent
= This
->parent
;
100 IUnknown_AddRef(*parent
);
101 TRACE("(%p) : returning %p\n", This
, *parent
);
105 static HRESULT WINAPI
IWineD3DPixelShaderImpl_GetDevice(IWineD3DPixelShader
* iface
, IWineD3DDevice
**pDevice
){
106 IWineD3DPixelShaderImpl
*This
= (IWineD3DPixelShaderImpl
*)iface
;
107 IWineD3DDevice_AddRef((IWineD3DDevice
*)This
->wineD3DDevice
);
108 *pDevice
= (IWineD3DDevice
*)This
->wineD3DDevice
;
109 TRACE("(%p) returning %p\n", This
, *pDevice
);
114 static HRESULT WINAPI
IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader
* impl
, VOID
* pData
, UINT
* pSizeOfData
) {
115 IWineD3DPixelShaderImpl
*This
= (IWineD3DPixelShaderImpl
*)impl
;
116 TRACE("(%p) : pData(%p), pSizeOfData(%p)\n", This
, pData
, pSizeOfData
);
119 *pSizeOfData
= This
->baseShader
.functionLength
;
122 if (*pSizeOfData
< This
->baseShader
.functionLength
) {
123 *pSizeOfData
= This
->baseShader
.functionLength
;
124 return WINED3DERR_MOREDATA
;
126 if (NULL
== This
->baseShader
.function
) { /* no function defined */
127 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This
, pData
);
128 (*(DWORD
**) pData
) = NULL
;
130 if (This
->baseShader
.functionLength
== 0) {
133 TRACE("(%p) : GetFunction copying to %p\n", This
, pData
);
134 memcpy(pData
, This
->baseShader
.function
, This
->baseShader
.functionLength
);
139 /*******************************
140 * pshader functions software VM
143 static void pshader_add(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
144 d
->x
= s0
->x
+ s1
->x
;
145 d
->y
= s0
->y
+ s1
->y
;
146 d
->z
= s0
->z
+ s1
->z
;
147 d
->w
= s0
->w
+ s1
->w
;
148 PSTRACE(("executing add: 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 static void pshader_dp3(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
;
154 PSTRACE(("executing dp3: 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 static void pshader_dp4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
159 d
->x
= d
->y
= d
->z
= d
->w
= s0
->x
* s1
->x
+ s0
->y
* s1
->y
+ s0
->z
* s1
->z
+ s0
->w
* s1
->w
;
160 PSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
161 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
164 static void pshader_dst(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
166 d
->y
= s0
->y
* s1
->y
;
169 PSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
170 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
173 static void pshader_expp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
179 tmp
.f
= floorf(s0
->w
);
180 d
->x
= powf(2.0f
, tmp
.f
);
181 d
->y
= s0
->w
- tmp
.f
;
182 tmp
.f
= powf(2.0f
, s0
->w
);
183 tmp
.d
&= 0xFFFFFF00U
;
186 PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
187 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
190 static void pshader_logp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
191 float tmp_f
= fabsf(s0
->w
);
192 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
193 PSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
194 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
197 static void pshader_mad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
198 d
->x
= s0
->x
* s1
->x
+ s2
->x
;
199 d
->y
= s0
->y
* s1
->y
+ s2
->y
;
200 d
->z
= s0
->z
* s1
->z
+ s2
->z
;
201 d
->w
= s0
->w
* s1
->w
+ s2
->w
;
202 PSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
203 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
));
206 static void pshader_max(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
207 d
->x
= (s0
->x
>= s1
->x
) ? s0
->x
: s1
->x
;
208 d
->y
= (s0
->y
>= s1
->y
) ? s0
->y
: s1
->y
;
209 d
->z
= (s0
->z
>= s1
->z
) ? s0
->z
: s1
->z
;
210 d
->w
= (s0
->w
>= s1
->w
) ? s0
->w
: s1
->w
;
211 PSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
212 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
215 static void pshader_min(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
216 d
->x
= (s0
->x
< s1
->x
) ? s0
->x
: s1
->x
;
217 d
->y
= (s0
->y
< s1
->y
) ? s0
->y
: s1
->y
;
218 d
->z
= (s0
->z
< s1
->z
) ? s0
->z
: s1
->z
;
219 d
->w
= (s0
->w
< s1
->w
) ? s0
->w
: s1
->w
;
220 PSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
221 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
224 static void pshader_mov(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
229 PSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
230 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
233 static void pshader_mul(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
234 d
->x
= s0
->x
* s1
->x
;
235 d
->y
= s0
->y
* s1
->y
;
236 d
->z
= s0
->z
* s1
->z
;
237 d
->w
= s0
->w
* s1
->w
;
238 PSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
239 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
242 static void pshader_nop(void) {
243 /* NOPPPP ahhh too easy ;) */
244 PSTRACE(("executing nop\n"));
247 static void pshader_rcp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
248 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
== s0
->w
) ? HUGE_VAL
: 1.0f
/ s0
->w
;
249 PSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
250 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
253 static void pshader_rsq(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
254 float tmp_f
= fabsf(s0
->w
);
255 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
);
256 PSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
257 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
260 static void pshader_sge(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
261 d
->x
= (s0
->x
>= s1
->x
) ? 1.0f
: 0.0f
;
262 d
->y
= (s0
->y
>= s1
->y
) ? 1.0f
: 0.0f
;
263 d
->z
= (s0
->z
>= s1
->z
) ? 1.0f
: 0.0f
;
264 d
->w
= (s0
->w
>= s1
->w
) ? 1.0f
: 0.0f
;
265 PSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
266 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
269 static void pshader_slt(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
270 d
->x
= (s0
->x
< s1
->x
) ? 1.0f
: 0.0f
;
271 d
->y
= (s0
->y
< s1
->y
) ? 1.0f
: 0.0f
;
272 d
->z
= (s0
->z
< s1
->z
) ? 1.0f
: 0.0f
;
273 d
->w
= (s0
->w
< s1
->w
) ? 1.0f
: 0.0f
;
274 PSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
275 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
278 static void pshader_sub(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
279 d
->x
= s0
->x
- s1
->x
;
280 d
->y
= s0
->y
- s1
->y
;
281 d
->z
= s0
->z
- s1
->z
;
282 d
->w
= s0
->w
- s1
->w
;
283 PSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
284 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
288 * Version 1.1 specific
291 static void pshader_exp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
292 d
->x
= d
->y
= d
->z
= d
->w
= powf(2.0f
, s0
->w
);
293 PSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
294 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
297 static void pshader_log(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
298 float tmp_f
= fabsf(s0
->w
);
299 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
300 PSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
301 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
304 static void pshader_frc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
305 d
->x
= s0
->x
- floorf(s0
->x
);
306 d
->y
= s0
->y
- floorf(s0
->y
);
309 PSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
310 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
313 typedef FLOAT D3DMATRIX44
[4][4];
314 typedef FLOAT D3DMATRIX43
[4][3];
315 typedef FLOAT D3DMATRIX34
[3][4];
316 typedef FLOAT D3DMATRIX33
[3][3];
317 typedef FLOAT D3DMATRIX23
[2][3];
319 static void pshader_m4x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat
) {
321 * Buggy CODE: here only if cast not work for copy/paste
322 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
323 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
324 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
325 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
326 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
327 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
328 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
330 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
331 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
332 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
333 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
+ mat
[3][3] * s0
->w
;
334 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
));
335 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
));
336 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
));
337 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
));
340 static void pshader_m4x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX34 mat
) {
341 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
342 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
343 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
345 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
));
346 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
));
347 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
));
348 PSTRACE(("executing m4x3(4): (%f) (%f) \n", s0
->w
, d
->w
));
351 static void pshader_m3x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX43 mat
) {
352 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
353 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
354 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
355 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
;
356 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
));
357 PSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
358 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
));
359 PSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat
[3][0], mat
[3][1], mat
[3][2], s0
->w
, d
->w
));
362 static void pshader_m3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX33 mat
) {
363 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
364 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
365 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
367 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
));
368 PSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
369 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
));
370 PSTRACE(("executing m3x3(4): (%f) \n", d
->w
));
373 static void pshader_m3x2(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX23 mat
) {
375 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
376 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
382 * Version 2.0 specific
384 static void pshader_lrp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
385 d
->x
= s0
->x
* (s1
->x
- s2
->x
) + s2
->x
;
386 d
->y
= s0
->y
* (s1
->y
- s2
->y
) + s2
->y
;
387 d
->z
= s0
->z
* (s1
->z
- s2
->z
) + s2
->z
;
388 d
->w
= s0
->w
* (s1
->w
- s2
->w
) + s2
->w
;
391 static void pshader_crs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
392 d
->x
= s0
->y
* s1
->z
- s0
->z
* s1
->y
;
393 d
->y
= s0
->z
* s1
->x
- s0
->x
* s1
->z
;
394 d
->z
= s0
->x
* s1
->y
- s0
->y
* s1
->x
;
395 d
->w
= 0.9f
; /* w is undefined, so set it to something safeish */
397 PSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
398 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
401 static void pshader_abs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
406 PSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
407 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
411 static void pshader_texcoord(WINED3DSHADERVECTOR
* d
) {
415 static void pshader_texkill(WINED3DSHADERVECTOR
* d
) {
419 static void pshader_tex(WINED3DSHADERVECTOR
* d
) {
422 static void pshader_texld(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
426 static void pshader_texbem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
430 static void pshader_texbeml(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
434 static void pshader_texreg2ar(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
438 static void pshader_texreg2gb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
442 static void pshader_texm3x2pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
446 static void pshader_texm3x2tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
450 static void pshader_texm3x3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
454 static void pshader_texm3x3pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
458 static void pshader_texm3x3diff(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
462 static void pshader_texm3x3spec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
466 static void pshader_texm3x3vspec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
470 static void pshader_cnd(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
474 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
475 static void pshader_def(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
, WINED3DSHADERVECTOR
* s3
) {
479 static void pshader_texreg2rgb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
483 static void pshader_texdp3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
487 static void pshader_texm3x2depth(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
491 static void pshader_texdp3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
495 static void pshader_texm3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
499 static void pshader_texdepth(WINED3DSHADERVECTOR
* d
) {
503 static void pshader_cmp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
507 static void pshader_bem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
511 static void pshader_call(WINED3DSHADERVECTOR
* d
) {
515 static void pshader_callnz(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
519 static void pshader_loop(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
523 static void pshader_ret(void) {
527 static void pshader_endloop(void) {
531 static void pshader_dcl(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
535 static void pshader_pow(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
539 static void pshader_nrm(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
543 static void pshader_sincos3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
547 static void pshader_sincos2(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
551 static void pshader_rep(WINED3DSHADERVECTOR
* d
) {
555 static void pshader_endrep(void) {
559 static void pshader_if(WINED3DSHADERVECTOR
* d
) {
563 static void pshader_ifc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
567 static void pshader_else(void) {
571 static void pshader_label(WINED3DSHADERVECTOR
* d
) {
575 static void pshader_endif(void) {
579 static void pshader_break(void) {
583 static void pshader_breakc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
587 static void pshader_breakp(WINED3DSHADERVECTOR
* d
) {
591 static void pshader_defb(WINED3DSHADERVECTOR
* d
) {
595 static void pshader_defi(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
, WINED3DSHADERVECTOR
* s3
) {
599 static void pshader_dp2add(WINED3DSHADERVECTOR
* d
) {
603 static void pshader_dsx(WINED3DSHADERVECTOR
* d
) {
607 static void pshader_dsy(WINED3DSHADERVECTOR
* d
) {
611 static void pshader_texldd(WINED3DSHADERVECTOR
* d
) {
615 static void pshader_setp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
619 static void pshader_texldl(WINED3DSHADERVECTOR
* d
) {
624 static void pshader_hw_cnd(SHADER_OPCODE_ARG
* arg
);
625 static void pshader_hw_cmp(SHADER_OPCODE_ARG
* arg
);
626 static void pshader_hw_map2gl(SHADER_OPCODE_ARG
* arg
);
627 static void pshader_hw_tex(SHADER_OPCODE_ARG
* arg
);
628 static void pshader_hw_texcoord(SHADER_OPCODE_ARG
* arg
);
629 static void pshader_hw_texreg2ar(SHADER_OPCODE_ARG
* arg
);
630 static void pshader_hw_texreg2gb(SHADER_OPCODE_ARG
* arg
);
631 static void pshader_hw_texbem(SHADER_OPCODE_ARG
* arg
);
632 static void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG
* arg
);
633 static void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG
* arg
);
634 static void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG
* arg
);
635 static void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG
* arg
);
636 static void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG
* arg
);
637 static void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG
* arg
);
640 * log, exp, frc, m*x* seems to be macros ins ... to see
642 CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins
[] = {
645 {D3DSIO_NOP
, "nop", "NOP", 0, pshader_nop
, pshader_hw_map2gl
, NULL
, 0, 0},
646 {D3DSIO_MOV
, "mov", "MOV", 2, pshader_mov
, pshader_hw_map2gl
, shader_glsl_mov
, 0, 0},
647 {D3DSIO_ADD
, "add", "ADD", 3, pshader_add
, pshader_hw_map2gl
, shader_glsl_arith
, 0, 0},
648 {D3DSIO_SUB
, "sub", "SUB", 3, pshader_sub
, pshader_hw_map2gl
, shader_glsl_arith
, 0, 0},
649 {D3DSIO_MAD
, "mad", "MAD", 4, pshader_mad
, pshader_hw_map2gl
, shader_glsl_mad
, 0, 0},
650 {D3DSIO_MUL
, "mul", "MUL", 3, pshader_mul
, pshader_hw_map2gl
, shader_glsl_arith
, 0, 0},
651 {D3DSIO_RCP
, "rcp", "RCP", 2, pshader_rcp
, pshader_hw_map2gl
, shader_glsl_rcp
, 0, 0},
652 {D3DSIO_RSQ
, "rsq", "RSQ", 2, pshader_rsq
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
653 {D3DSIO_DP3
, "dp3", "DP3", 3, pshader_dp3
, pshader_hw_map2gl
, shader_glsl_dot
, 0, 0},
654 {D3DSIO_DP4
, "dp4", "DP4", 3, pshader_dp4
, pshader_hw_map2gl
, shader_glsl_dot
, 0, 0},
655 {D3DSIO_MIN
, "min", "MIN", 3, pshader_min
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
656 {D3DSIO_MAX
, "max", "MAX", 3, pshader_max
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
657 {D3DSIO_SLT
, "slt", "SLT", 3, pshader_slt
, pshader_hw_map2gl
, shader_glsl_compare
, 0, 0},
658 {D3DSIO_SGE
, "sge", "SGE", 3, pshader_sge
, pshader_hw_map2gl
, shader_glsl_compare
, 0, 0},
659 {D3DSIO_ABS
, "abs", "ABS", 2, pshader_abs
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
660 {D3DSIO_EXP
, "exp", "EX2", 2, pshader_exp
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
661 {D3DSIO_LOG
, "log", "LG2", 2, pshader_log
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
662 {D3DSIO_EXPP
, "expp", "EXP", 2, pshader_expp
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
663 {D3DSIO_LOGP
, "logp", "LOG", 2, pshader_logp
, pshader_hw_map2gl
, NULL
, 0, 0},
664 {D3DSIO_DST
, "dst", "DST", 3, pshader_dst
, pshader_hw_map2gl
, NULL
, 0, 0},
665 {D3DSIO_LRP
, "lrp", "LRP", 4, pshader_lrp
, pshader_hw_map2gl
, shader_glsl_lrp
, 0, 0},
666 {D3DSIO_FRC
, "frc", "FRC", 2, pshader_frc
, pshader_hw_map2gl
, shader_glsl_map2gl
, 0, 0},
667 {D3DSIO_CND
, "cnd", NULL
, 4, pshader_cnd
, pshader_hw_cnd
, shader_glsl_cnd
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
668 {D3DSIO_CMP
, "cmp", NULL
, 4, pshader_cmp
, pshader_hw_cmp
, shader_glsl_cmp
, D3DPS_VERSION(1,2), D3DPS_VERSION(3,0)},
669 {D3DSIO_POW
, "pow", "POW", 3, pshader_pow
, NULL
, shader_glsl_map2gl
, 0, 0},
670 {D3DSIO_CRS
, "crs", "XPS", 3, pshader_crs
, NULL
, shader_glsl_map2gl
, 0, 0},
671 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
674 MUL vec.xyz, vec, tmp;
675 but I think this is better because it accounts for w properly.
681 {D3DSIO_NRM
, "nrm", NULL
, 2, pshader_nrm
, NULL
, shader_glsl_map2gl
, 0, 0},
682 {D3DSIO_SINCOS
, "sincos", NULL
, 4, pshader_sincos2
, NULL
, NULL
, D3DPS_VERSION(2,0), D3DPS_VERSION(2,0)},
683 {D3DSIO_SINCOS
, "sincos", NULL
, 2, pshader_sincos3
, NULL
, NULL
, D3DPS_VERSION(3,0), -1},
684 /* TODO: dp2add can be made out of multiple instuctions */
685 {D3DSIO_DP2ADD
, "dp2add", GLNAME_REQUIRE_GLSL
, 2, pshader_dp2add
, NULL
, NULL
, 0, 0},
688 {D3DSIO_M4x4
, "m4x4", "undefined", 3, pshader_m4x4
, NULL
, shader_glsl_mnxn
, 0, 0},
689 {D3DSIO_M4x3
, "m4x3", "undefined", 3, pshader_m4x3
, NULL
, shader_glsl_mnxn
, 0, 0},
690 {D3DSIO_M3x4
, "m3x4", "undefined", 3, pshader_m3x4
, NULL
, shader_glsl_mnxn
, 0, 0},
691 {D3DSIO_M3x3
, "m3x3", "undefined", 3, pshader_m3x3
, NULL
, shader_glsl_mnxn
, 0, 0},
692 {D3DSIO_M3x2
, "m3x2", "undefined", 3, pshader_m3x2
, NULL
, shader_glsl_mnxn
, 0, 0},
694 /* Register declarations */
695 {D3DSIO_DCL
, "dcl", NULL
, 2, pshader_dcl
, NULL
, NULL
, 0, 0},
697 /* Flow control - requires GLSL or software shaders */
698 {D3DSIO_REP
, "rep", GLNAME_REQUIRE_GLSL
, 1, pshader_rep
, NULL
, NULL
, 0, 0},
699 {D3DSIO_ENDREP
, "endrep", GLNAME_REQUIRE_GLSL
, 0, pshader_endrep
, NULL
, NULL
, 0, 0},
700 {D3DSIO_IF
, "if", GLNAME_REQUIRE_GLSL
, 1, pshader_if
, NULL
, NULL
, 0, 0},
701 {D3DSIO_IFC
, "ifc", GLNAME_REQUIRE_GLSL
, 2, pshader_ifc
, NULL
, NULL
, 0, 0},
702 {D3DSIO_ELSE
, "else", GLNAME_REQUIRE_GLSL
, 0, pshader_else
, NULL
, NULL
, 0, 0},
703 {D3DSIO_ENDIF
, "endif", GLNAME_REQUIRE_GLSL
, 0, pshader_endif
, NULL
, NULL
, 0, 0},
704 {D3DSIO_BREAK
, "break", GLNAME_REQUIRE_GLSL
, 0, pshader_break
, NULL
, NULL
, 0, 0},
705 {D3DSIO_BREAKC
, "breakc", GLNAME_REQUIRE_GLSL
, 2, pshader_breakc
, NULL
, NULL
, 0, 0},
706 {D3DSIO_BREAKP
, "breakp", GLNAME_REQUIRE_GLSL
, 1, pshader_breakp
, NULL
, NULL
, 0, 0},
707 {D3DSIO_CALL
, "call", GLNAME_REQUIRE_GLSL
, 1, pshader_call
, NULL
, NULL
, 0, 0},
708 {D3DSIO_CALLNZ
, "callnz", GLNAME_REQUIRE_GLSL
, 2, pshader_callnz
, NULL
, NULL
, 0, 0},
709 {D3DSIO_LOOP
, "loop", GLNAME_REQUIRE_GLSL
, 2, pshader_loop
, NULL
, NULL
, 0, 0},
710 {D3DSIO_RET
, "ret", GLNAME_REQUIRE_GLSL
, 0, pshader_ret
, NULL
, NULL
, 0, 0},
711 {D3DSIO_ENDLOOP
, "endloop", GLNAME_REQUIRE_GLSL
, 0, pshader_endloop
, NULL
, NULL
, 0, 0},
712 {D3DSIO_LABEL
, "label", GLNAME_REQUIRE_GLSL
, 1, pshader_label
, NULL
, NULL
, 0, 0},
714 /* Constant definitions */
715 {D3DSIO_DEF
, "def", "undefined", 5, pshader_def
, shader_hw_def
, shader_glsl_def
, 0, 0},
716 {D3DSIO_DEFB
, "defb", GLNAME_REQUIRE_GLSL
, 2, pshader_defb
, NULL
, NULL
, 0, 0},
717 {D3DSIO_DEFI
, "defi", GLNAME_REQUIRE_GLSL
, 5, pshader_defi
, NULL
, NULL
, 0, 0},
720 {D3DSIO_TEXCOORD
, "texcoord", "undefined", 1, pshader_texcoord
, pshader_hw_texcoord
, pshader_glsl_texcoord
, 0, D3DPS_VERSION(1,3)},
721 {D3DSIO_TEXCOORD
, "texcrd", "undefined", 2, pshader_texcoord
, pshader_hw_texcoord
, pshader_glsl_texcoord
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
722 {D3DSIO_TEXKILL
, "texkill", "KIL", 1, pshader_texkill
, pshader_hw_map2gl
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
723 {D3DSIO_TEX
, "tex", "undefined", 1, pshader_tex
, pshader_hw_tex
, pshader_glsl_tex
, 0, D3DPS_VERSION(1,3)},
724 {D3DSIO_TEX
, "texld", "undefined", 2, pshader_texld
, pshader_hw_tex
, pshader_glsl_tex
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
725 {D3DSIO_TEX
, "texld", "undefined", 3, pshader_texld
, pshader_hw_tex
, pshader_glsl_tex
, D3DPS_VERSION(2,0), -1},
726 {D3DSIO_TEXBEM
, "texbem", "undefined", 2, pshader_texbem
, pshader_hw_texbem
, NULL
, 0, D3DPS_VERSION(1,3)},
727 {D3DSIO_TEXBEML
, "texbeml", GLNAME_REQUIRE_GLSL
, 2, pshader_texbeml
, NULL
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
728 {D3DSIO_TEXREG2AR
,"texreg2ar","undefined", 2, pshader_texreg2ar
, pshader_hw_texreg2ar
, NULL
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
729 {D3DSIO_TEXREG2GB
,"texreg2gb","undefined", 2, pshader_texreg2gb
, pshader_hw_texreg2gb
, NULL
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
730 {D3DSIO_TEXREG2RGB
, "texreg2rgb", GLNAME_REQUIRE_GLSL
, 2, pshader_texreg2rgb
, NULL
, NULL
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
731 {D3DSIO_TEXM3x2PAD
, "texm3x2pad", "undefined", 2, pshader_texm3x2pad
, pshader_hw_texm3x2pad
, pshader_glsl_texm3x2pad
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
732 {D3DSIO_TEXM3x2TEX
, "texm3x2tex", "undefined", 2, pshader_texm3x2tex
, pshader_hw_texm3x2tex
, pshader_glsl_texm3x2tex
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
733 {D3DSIO_TEXM3x3PAD
, "texm3x3pad", "undefined", 2, pshader_texm3x3pad
, pshader_hw_texm3x3pad
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
734 {D3DSIO_TEXM3x3DIFF
, "texm3x3diff", GLNAME_REQUIRE_GLSL
, 2, pshader_texm3x3diff
, NULL
, NULL
, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
735 {D3DSIO_TEXM3x3SPEC
, "texm3x3spec", "undefined", 3, pshader_texm3x3spec
, pshader_hw_texm3x3spec
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
736 {D3DSIO_TEXM3x3VSPEC
, "texm3x3vspe", "undefined", 2, pshader_texm3x3vspec
, pshader_hw_texm3x3vspec
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
737 {D3DSIO_TEXM3x3TEX
, "texm3x3tex", "undefined", 2, pshader_texm3x3tex
, pshader_hw_texm3x3tex
, NULL
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
738 {D3DSIO_TEXDP3TEX
, "texdp3tex", GLNAME_REQUIRE_GLSL
, 2, pshader_texdp3tex
, NULL
, NULL
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
739 {D3DSIO_TEXM3x2DEPTH
, "texm3x2depth", GLNAME_REQUIRE_GLSL
, 2, pshader_texm3x2depth
, NULL
, NULL
, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
740 {D3DSIO_TEXDP3
, "texdp3", GLNAME_REQUIRE_GLSL
, 2, pshader_texdp3
, NULL
, NULL
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
741 {D3DSIO_TEXM3x3
, "texm3x3", GLNAME_REQUIRE_GLSL
, 2, pshader_texm3x3
, NULL
, NULL
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
742 {D3DSIO_TEXDEPTH
, "texdepth", GLNAME_REQUIRE_GLSL
, 1, pshader_texdepth
, NULL
, NULL
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
743 {D3DSIO_BEM
, "bem", GLNAME_REQUIRE_GLSL
, 3, pshader_bem
, NULL
, NULL
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
744 /* TODO: dp2add can be made out of multiple instuctions */
745 {D3DSIO_DSX
, "dsx", GLNAME_REQUIRE_GLSL
, 2, pshader_dsx
, NULL
, NULL
, 0, 0},
746 {D3DSIO_DSY
, "dsy", GLNAME_REQUIRE_GLSL
, 2, pshader_dsy
, NULL
, NULL
, 0, 0},
747 {D3DSIO_TEXLDD
, "texldd", GLNAME_REQUIRE_GLSL
, 2, pshader_texldd
, NULL
, NULL
, 0, 0},
748 {D3DSIO_SETP
, "setp", GLNAME_REQUIRE_GLSL
, 3, pshader_setp
, NULL
, NULL
, 0, 0},
749 {D3DSIO_TEXLDL
, "texdl", GLNAME_REQUIRE_GLSL
, 2, pshader_texldl
, NULL
, NULL
, 0, 0},
750 {D3DSIO_PHASE
, "phase", GLNAME_REQUIRE_GLSL
, 0, pshader_nop
, NULL
, NULL
, 0, 0},
751 {0, NULL
, NULL
, 0, NULL
, NULL
, 0, 0}
754 inline static void get_register_name(const DWORD param
, char* regstr
, CHAR
*constants
) {
756 DWORD reg
= param
& D3DSP_REGNUM_MASK
;
757 DWORD regtype
= shader_get_regtype(param
);
761 sprintf(regstr
, "R%lu", reg
);
765 strcpy(regstr
, "fragment.color.primary");
767 strcpy(regstr
, "fragment.color.secondary");
772 sprintf(regstr
, "C%lu", reg
);
774 sprintf(regstr
, "C[%lu]", reg
);
776 case D3DSPR_TEXTURE
: /* case D3DSPR_ADDR: */
777 sprintf(regstr
,"T%lu", reg
);
779 case D3DSPR_COLOROUT
:
781 sprintf(regstr
, "result.color");
783 /* TODO: See GL_ARB_draw_buffers */
784 FIXME("Unsupported write to render target %lu\n", reg
);
785 sprintf(regstr
, "unsupported_register");
788 case D3DSPR_DEPTHOUT
:
789 sprintf(regstr
, "result.depth");
792 sprintf(regstr
, "oD[%lu]", reg
);
794 case D3DSPR_TEXCRDOUT
:
795 sprintf(regstr
, "oT[%lu]", reg
);
798 FIXME("Unhandled register name Type(%ld)\n", regtype
);
799 sprintf(regstr
, "unrecognized_register");
804 inline static void get_write_mask(const DWORD output_reg
, char *write_mask
) {
806 if ((output_reg
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
807 strcat(write_mask
, ".");
808 if (output_reg
& D3DSP_WRITEMASK_0
) strcat(write_mask
, "r");
809 if (output_reg
& D3DSP_WRITEMASK_1
) strcat(write_mask
, "g");
810 if (output_reg
& D3DSP_WRITEMASK_2
) strcat(write_mask
, "b");
811 if (output_reg
& D3DSP_WRITEMASK_3
) strcat(write_mask
, "a");
815 static void pshader_get_input_register_swizzle(const DWORD instr
, char *swzstring
) {
816 static const char swizzle_reg_chars
[] = "rgba";
817 DWORD swizzle
= (instr
& D3DSP_SWIZZLE_MASK
) >> D3DSP_SWIZZLE_SHIFT
;
818 DWORD swizzle_x
= swizzle
& 0x03;
819 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
820 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
821 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
823 * swizzle bits fields:
827 if ((D3DSP_NOSWIZZLE
>> D3DSP_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
828 if (swizzle_x
== swizzle_y
&&
829 swizzle_x
== swizzle_z
&&
830 swizzle_x
== swizzle_w
) {
831 sprintf(swzstring
, ".%c", swizzle_reg_chars
[swizzle_x
]);
833 sprintf(swzstring
, ".%c%c%c%c",
834 swizzle_reg_chars
[swizzle_x
],
835 swizzle_reg_chars
[swizzle_y
],
836 swizzle_reg_chars
[swizzle_z
],
837 swizzle_reg_chars
[swizzle_w
]);
842 static const char* shift_tab
[] = {
843 "dummy", /* 0 (none) */
844 "coefmul.x", /* 1 (x2) */
845 "coefmul.y", /* 2 (x4) */
846 "coefmul.z", /* 3 (x8) */
847 "coefmul.w", /* 4 (x16) */
848 "dummy", /* 5 (x32) */
849 "dummy", /* 6 (x64) */
850 "dummy", /* 7 (x128) */
851 "dummy", /* 8 (d256) */
852 "dummy", /* 9 (d128) */
853 "dummy", /* 10 (d64) */
854 "dummy", /* 11 (d32) */
855 "coefdiv.w", /* 12 (d16) */
856 "coefdiv.z", /* 13 (d8) */
857 "coefdiv.y", /* 14 (d4) */
858 "coefdiv.x" /* 15 (d2) */
861 inline static void pshader_gen_output_modifier_line(
862 SHADER_BUFFER
* buffer
,
868 /* Generate a line that does the output modifier computation */
869 shader_addline(buffer
, "MUL%s %s%s, %s, %s;\n", saturate
? "_SAT" : "",
870 regstr
, write_mask
, regstr
, shift_tab
[shift
]);
873 static void pshader_gen_input_modifier_line (
874 SHADER_BUFFER
* buffer
,
880 /* Generate a line that does the input modifier computation and return the input register to use */
885 /* Assume a new line will be added */
888 /* Get register name */
889 get_register_name(instr
, regstr
, constants
);
890 pshader_get_input_register_swizzle(instr
, swzstr
);
892 switch (instr
& D3DSP_SRCMOD_MASK
) {
894 sprintf(outregstr
, "%s%s", regstr
, swzstr
);
898 sprintf(outregstr
, "-%s%s", regstr
, swzstr
);
902 shader_addline(buffer
, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg
, regstr
);
904 case D3DSPSM_BIASNEG
:
905 shader_addline(buffer
, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg
, regstr
);
908 shader_addline(buffer
, "MAD T%c, %s, coefmul.x, -one.x;\n", 'A' + tmpreg
, regstr
);
910 case D3DSPSM_SIGNNEG
:
911 shader_addline(buffer
, "MAD T%c, %s, -coefmul.x, one.x;\n", 'A' + tmpreg
, regstr
);
914 shader_addline(buffer
, "SUB T%c, one.x, %s;\n", 'A' + tmpreg
, regstr
);
917 shader_addline(buffer
, "ADD T%c, %s, %s;\n", 'A' + tmpreg
, regstr
, regstr
);
920 shader_addline(buffer
, "ADD T%c, -%s, -%s;\n", 'A' + tmpreg
, regstr
, regstr
);
923 shader_addline(buffer
, "RCP T%c, %s.z;\n", 'A' + tmpreg
, regstr
);
924 shader_addline(buffer
, "MUL T%c, %s, T%c;\n", 'A' + tmpreg
, regstr
, 'A' + tmpreg
);
927 shader_addline(buffer
, "RCP T%c, %s.w;\n", 'A' + tmpreg
, regstr
);
928 shader_addline(buffer
, "MUL T%c, %s, T%c;\n", 'A' + tmpreg
, regstr
, 'A' + tmpreg
);
931 sprintf(outregstr
, "%s%s", regstr
, swzstr
);
935 /* Return modified or original register, with swizzle */
937 sprintf(outregstr
, "T%c%s", 'A' + tmpreg
, swzstr
);
940 static void pshader_set_version(
941 IWineD3DPixelShaderImpl
*This
,
944 DWORD major
= (version
>> 8) & 0x0F;
945 DWORD minor
= version
& 0x0F;
947 This
->baseShader
.hex_version
= version
;
948 This
->baseShader
.version
= major
* 10 + minor
;
949 TRACE("ps_%lu_%lu\n", major
, minor
);
951 This
->baseShader
.limits
.attributes
= 0;
952 This
->baseShader
.limits
.address
= 0;
954 switch (This
->baseShader
.version
) {
958 case 13: This
->baseShader
.limits
.temporary
= 2;
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
= 4;
965 case 14: This
->baseShader
.limits
.temporary
= 6;
966 This
->baseShader
.limits
.constant_float
= 8;
967 This
->baseShader
.limits
.constant_int
= 0;
968 This
->baseShader
.limits
.constant_bool
= 0;
969 This
->baseShader
.limits
.texture
= 6;
972 /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */
974 case 21: This
->baseShader
.limits
.temporary
= 32;
975 This
->baseShader
.limits
.constant_float
= 32;
976 This
->baseShader
.limits
.constant_int
= 16;
977 This
->baseShader
.limits
.constant_bool
= 16;
978 This
->baseShader
.limits
.texture
= 8;
981 case 30: This
->baseShader
.limits
.temporary
= 32;
982 This
->baseShader
.limits
.constant_float
= 224;
983 This
->baseShader
.limits
.constant_int
= 16;
984 This
->baseShader
.limits
.constant_bool
= 16;
985 This
->baseShader
.limits
.texture
= 0;
988 default: This
->baseShader
.limits
.temporary
= 32;
989 This
->baseShader
.limits
.constant_float
= 8;
990 This
->baseShader
.limits
.constant_int
= 0;
991 This
->baseShader
.limits
.constant_bool
= 0;
992 This
->baseShader
.limits
.texture
= 8;
993 FIXME("Unrecognized pixel shader version %lx!\n", version
);
997 static void pshader_hw_cnd(SHADER_OPCODE_ARG
* arg
) {
999 SHADER_BUFFER
* buffer
= arg
->buffer
;
1002 char src_name
[3][50];
1004 /* FIXME: support output modifiers */
1006 /* Handle output register */
1007 get_register_name(arg
->dst
, dst_name
, arg
->reg_maps
->constantsF
);
1008 get_write_mask(arg
->dst
, dst_wmask
);
1009 strcat(dst_name
, dst_wmask
);
1011 /* Generate input register names (with modifiers) */
1012 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src_name
[0], arg
->reg_maps
->constantsF
);
1013 pshader_gen_input_modifier_line(buffer
, arg
->src
[1], 1, src_name
[1], arg
->reg_maps
->constantsF
);
1014 pshader_gen_input_modifier_line(buffer
, arg
->src
[2], 2, src_name
[2], arg
->reg_maps
->constantsF
);
1016 shader_addline(buffer
, "ADD TMP, -%s, coefdiv.x;\n", src_name
[0]);
1017 shader_addline(buffer
, "CMP %s, TMP, %s, %s;\n", dst_name
, src_name
[1], src_name
[2]);
1020 static void pshader_hw_cmp(SHADER_OPCODE_ARG
* arg
) {
1022 SHADER_BUFFER
* buffer
= arg
->buffer
;
1025 char src_name
[3][50];
1027 /* FIXME: support output modifiers */
1029 /* Handle output register */
1030 get_register_name(arg
->dst
, dst_name
, arg
->reg_maps
->constantsF
);
1031 get_write_mask(arg
->dst
, dst_wmask
);
1032 strcat(dst_name
, dst_wmask
);
1034 /* Generate input register names (with modifiers) */
1035 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src_name
[0], arg
->reg_maps
->constantsF
);
1036 pshader_gen_input_modifier_line(buffer
, arg
->src
[1], 1, src_name
[1], arg
->reg_maps
->constantsF
);
1037 pshader_gen_input_modifier_line(buffer
, arg
->src
[2], 2, src_name
[2], arg
->reg_maps
->constantsF
);
1039 shader_addline(buffer
, "CMP %s, %s, %s, %s;\n", dst_name
,
1040 src_name
[0], src_name
[2], src_name
[1]);
1043 /* Map the opcode 1-to-1 to the GL code */
1044 static void pshader_hw_map2gl(SHADER_OPCODE_ARG
* arg
) {
1046 CONST SHADER_OPCODE
* curOpcode
= arg
->opcode
;
1047 SHADER_BUFFER
* buffer
= arg
->buffer
;
1048 DWORD dst
= arg
->dst
;
1049 DWORD
* src
= arg
->src
;
1054 /* Output token related */
1055 char output_rname
[256];
1056 char output_wmask
[20];
1057 BOOL saturate
= FALSE
;
1058 BOOL centroid
= FALSE
;
1059 BOOL partialprecision
= FALSE
;
1062 strcpy(tmpLine
, curOpcode
->glname
);
1064 /* Process modifiers */
1065 if (0 != (dst
& D3DSP_DSTMOD_MASK
)) {
1066 DWORD mask
= dst
& D3DSP_DSTMOD_MASK
;
1068 saturate
= mask
& D3DSPDM_SATURATE
;
1069 centroid
= mask
& D3DSPDM_MSAMPCENTROID
;
1070 partialprecision
= mask
& D3DSPDM_PARTIALPRECISION
;
1071 mask
&= ~(D3DSPDM_MSAMPCENTROID
| D3DSPDM_PARTIALPRECISION
| D3DSPDM_SATURATE
);
1074 FIXME("Unrecognized modifier(0x%#lx)\n", mask
>> D3DSP_DSTMOD_SHIFT
);
1077 FIXME("Unhandled modifier(0x%#lx)\n", mask
>> D3DSP_DSTMOD_SHIFT
);
1079 shift
= (dst
& D3DSP_DSTSHIFT_MASK
) >> D3DSP_DSTSHIFT_SHIFT
;
1081 /* Generate input and output registers */
1082 if (curOpcode
->num_params
> 0) {
1083 char operands
[4][100];
1085 /* Generate input register names (with modifiers) */
1086 for (i
= 1; i
< curOpcode
->num_params
; ++i
)
1087 pshader_gen_input_modifier_line(buffer
, src
[i
-1], i
-1, operands
[i
], arg
->reg_maps
->constantsF
);
1089 /* Handle output register */
1090 get_register_name(dst
, output_rname
, arg
->reg_maps
->constantsF
);
1091 strcpy(operands
[0], output_rname
);
1092 get_write_mask(dst
, output_wmask
);
1093 strcat(operands
[0], output_wmask
);
1095 if (saturate
&& (shift
== 0))
1096 strcat(tmpLine
, "_SAT");
1097 strcat(tmpLine
, " ");
1098 strcat(tmpLine
, operands
[0]);
1099 for (i
= 1; i
< curOpcode
->num_params
; i
++) {
1100 strcat(tmpLine
, ", ");
1101 strcat(tmpLine
, operands
[i
]);
1103 strcat(tmpLine
,";\n");
1104 shader_addline(buffer
, tmpLine
);
1106 /* A shift requires another line. */
1108 pshader_gen_output_modifier_line(buffer
, saturate
, output_wmask
, shift
, output_rname
);
1112 static void pshader_hw_tex(SHADER_OPCODE_ARG
* arg
) {
1114 IWineD3DPixelShaderImpl
* This
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1115 DWORD dst
= arg
->dst
;
1116 DWORD
* src
= arg
->src
;
1117 SHADER_BUFFER
* buffer
= arg
->buffer
;
1118 DWORD version
= This
->baseShader
.version
;
1122 DWORD reg_dest_code
;
1123 DWORD reg_sampler_code
;
1125 /* All versions have a destination register */
1126 reg_dest_code
= dst
& D3DSP_REGNUM_MASK
;
1127 get_register_name(dst
, reg_dest
, arg
->reg_maps
->constantsF
);
1129 /* 1.0-1.3: Use destination register as coordinate source.
1130 2.0+: Use provided coordinate source register. */
1132 strcpy(reg_coord
, reg_dest
);
1134 pshader_gen_input_modifier_line(buffer
, src
[0], 0, reg_coord
, arg
->reg_maps
->constantsF
);
1136 /* 1.0-1.4: Use destination register number as texture code.
1137 2.0+: Use provided sampler number as texure code. */
1139 reg_sampler_code
= reg_dest_code
;
1141 reg_sampler_code
= src
[1] & D3DSP_REGNUM_MASK
;
1143 shader_addline(buffer
, "TEX %s, %s, texture[%lu], 2D;\n",
1144 reg_dest
, reg_coord
, reg_sampler_code
);
1147 static void pshader_hw_texcoord(SHADER_OPCODE_ARG
* arg
) {
1149 IWineD3DPixelShaderImpl
* This
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1150 DWORD dst
= arg
->dst
;
1151 DWORD
* src
= arg
->src
;
1152 SHADER_BUFFER
* buffer
= arg
->buffer
;
1153 DWORD version
= This
->baseShader
.version
;
1156 get_write_mask(dst
, tmp
);
1157 if (version
!= 14) {
1158 DWORD reg
= dst
& D3DSP_REGNUM_MASK
;
1159 shader_addline(buffer
, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg
, tmp
, reg
);
1161 DWORD reg1
= dst
& D3DSP_REGNUM_MASK
;
1162 DWORD reg2
= src
[0] & D3DSP_REGNUM_MASK
;
1163 shader_addline(buffer
, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1
, tmp
, reg2
);
1167 static void pshader_hw_texreg2ar(SHADER_OPCODE_ARG
* arg
) {
1169 SHADER_BUFFER
* buffer
= arg
->buffer
;
1171 DWORD reg1
= arg
->dst
& D3DSP_REGNUM_MASK
;
1172 DWORD reg2
= arg
->src
[0] & D3DSP_REGNUM_MASK
;
1173 shader_addline(buffer
, "MOV TMP.r, T%lu.a;\n", reg2
);
1174 shader_addline(buffer
, "MOV TMP.g, T%lu.r;\n", reg2
);
1175 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1
, reg1
);
1178 static void pshader_hw_texreg2gb(SHADER_OPCODE_ARG
* arg
) {
1180 SHADER_BUFFER
* buffer
= arg
->buffer
;
1182 DWORD reg1
= arg
->dst
& D3DSP_REGNUM_MASK
;
1183 DWORD reg2
= arg
->src
[0] & D3DSP_REGNUM_MASK
;
1184 shader_addline(buffer
, "MOV TMP.r, T%lu.g;\n", reg2
);
1185 shader_addline(buffer
, "MOV TMP.g, T%lu.b;\n", reg2
);
1186 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1
, reg1
);
1189 static void pshader_hw_texbem(SHADER_OPCODE_ARG
* arg
) {
1191 SHADER_BUFFER
* buffer
= arg
->buffer
;
1193 DWORD reg1
= arg
->dst
& D3DSP_REGNUM_MASK
;
1194 DWORD reg2
= arg
->src
[0] & D3DSP_REGNUM_MASK
;
1196 /* FIXME: Should apply the BUMPMAPENV matrix */
1197 shader_addline(buffer
, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1
, reg2
);
1198 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1
, reg1
);
1201 static void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG
* arg
) {
1203 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1204 SHADER_BUFFER
* buffer
= arg
->buffer
;
1207 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1208 shader_addline(buffer
, "DP3 TMP.x, T%lu, %s;\n", reg
, src0_name
);
1211 static void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG
* arg
) {
1213 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1214 SHADER_BUFFER
* buffer
= arg
->buffer
;
1217 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1218 shader_addline(buffer
, "DP3 TMP.y, T%lu, %s;\n", reg
, src0_name
);
1219 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg
, reg
);
1222 static void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG
* arg
) {
1224 IWineD3DPixelShaderImpl
* shader
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1225 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1226 SHADER_BUFFER
* buffer
= arg
->buffer
;
1227 SHADER_PARSE_STATE current_state
= shader
->baseShader
.parse_state
;
1230 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1231 shader_addline(buffer
, "DP3 TMP.%c, T%lu, %s;\n", 'x' + current_state
.current_row
, reg
, src0_name
);
1232 current_state
.texcoord_w
[current_state
.current_row
++] = reg
;
1235 static void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG
* arg
) {
1237 IWineD3DPixelShaderImpl
* shader
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1238 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1239 SHADER_BUFFER
* buffer
= arg
->buffer
;
1240 SHADER_PARSE_STATE current_state
= shader
->baseShader
.parse_state
;
1243 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1244 shader_addline(buffer
, "DP3 TMP.z, T%lu, %s;\n", reg
, src0_name
);
1246 /* Cubemap textures will be more used than 3D ones. */
1247 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg
, reg
);
1248 current_state
.current_row
= 0;
1251 static void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG
* arg
) {
1253 IWineD3DPixelShaderImpl
* shader
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1254 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1255 SHADER_BUFFER
* buffer
= arg
->buffer
;
1256 SHADER_PARSE_STATE current_state
= shader
->baseShader
.parse_state
;
1259 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1260 shader_addline(buffer
, "DP3 TMP.z, T%lu, %s;\n", reg
, src0_name
);
1262 /* Construct the eye-ray vector from w coordinates */
1263 shader_addline(buffer
, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", current_state
.texcoord_w
[0]);
1264 shader_addline(buffer
, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", current_state
.texcoord_w
[1]);
1265 shader_addline(buffer
, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg
);
1267 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1268 shader_addline(buffer
, "DP3 TMP.w, TMP, TMP2;\n");
1269 shader_addline(buffer
, "MUL TMP, TMP.w, TMP;\n");
1270 shader_addline(buffer
, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
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 static void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG
* arg
) {
1279 IWineD3DPixelShaderImpl
* shader
= (IWineD3DPixelShaderImpl
*) arg
->shader
;
1280 DWORD reg
= arg
->dst
& D3DSP_REGNUM_MASK
;
1281 DWORD reg3
= arg
->src
[1] & D3DSP_REGNUM_MASK
;
1282 SHADER_PARSE_STATE current_state
= shader
->baseShader
.parse_state
;
1283 SHADER_BUFFER
* buffer
= arg
->buffer
;
1286 pshader_gen_input_modifier_line(buffer
, arg
->src
[0], 0, src0_name
, arg
->reg_maps
->constantsF
);
1287 shader_addline(buffer
, "DP3 TMP.z, T%lu, %s;\n", reg
, src0_name
);
1289 /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1290 shader_addline(buffer
, "DP3 TMP.w, TMP, C[%lu];\n", reg3
);
1291 shader_addline(buffer
, "MUL TMP, TMP.w, TMP;\n");
1292 shader_addline(buffer
, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3
);
1294 /* Cubemap textures will be more used than 3D ones. */
1295 shader_addline(buffer
, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg
, reg
);
1296 current_state
.current_row
= 0;
1299 /** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
1300 or GLSL and send it to the card */
1301 inline static VOID
IWineD3DPixelShaderImpl_GenerateShader(
1302 IWineD3DPixelShader
*iface
,
1303 CONST DWORD
*pFunction
) {
1305 IWineD3DPixelShaderImpl
*This
= (IWineD3DPixelShaderImpl
*)iface
;
1306 SHADER_BUFFER buffer
;
1308 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1309 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1310 if (This
->device
->fixupVertexBufferSize
< SHADER_PGMSIZE
) {
1311 HeapFree(GetProcessHeap(), 0, This
->fixupVertexBuffer
);
1312 This
->fixupVertexBuffer
= HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE
);
1313 This
->fixupVertexBufferSize
= PGMSIZE
;
1314 This
->fixupVertexBuffer
[0] = 0;
1316 buffer
.buffer
= This
->device
->fixupVertexBuffer
;
1318 buffer
.buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, SHADER_PGMSIZE
);
1323 if (wined3d_settings
.shader_mode
== SHADER_GLSL
) {
1325 /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
1326 GLhandleARB shader_obj
= GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB
));
1328 /* Generate the bulk of the shader code */
1329 generate_base_shader( (IWineD3DBaseShader
*) This
, &buffer
, pFunction
);
1331 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
1332 if (This
->baseShader
.hex_version
< D3DPS_VERSION(2,0))
1333 shader_addline(&buffer
, "gl_FragColor = R0;\n");
1334 shader_addline(&buffer
, "}\n\0");
1336 TRACE("Compiling shader object %u\n", shader_obj
);
1337 GL_EXTCALL(glShaderSourceARB(shader_obj
, 1, (const char**)&buffer
.buffer
, NULL
));
1338 GL_EXTCALL(glCompileShaderARB(shader_obj
));
1339 print_glsl_info_log(&GLINFO_LOCATION
, shader_obj
);
1341 /* Store the shader object */
1342 This
->baseShader
.prgId
= shader_obj
;
1344 } else if (wined3d_settings
.shader_mode
== SHADER_ARB
) {
1345 /* Create the hw ARB shader */
1346 shader_addline(&buffer
, "!!ARBfp1.0\n");
1348 shader_addline(&buffer
, "TEMP TMP;\n"); /* Used in matrix ops */
1349 shader_addline(&buffer
, "TEMP TMP2;\n"); /* Used in matrix ops */
1350 shader_addline(&buffer
, "TEMP TA;\n"); /* Used for modifiers */
1351 shader_addline(&buffer
, "TEMP TB;\n"); /* Used for modifiers */
1352 shader_addline(&buffer
, "TEMP TC;\n"); /* Used for modifiers */
1353 shader_addline(&buffer
, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
1354 shader_addline(&buffer
, "PARAM coefmul = { 2, 4, 8, 16 };\n");
1355 shader_addline(&buffer
, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
1357 /** Call the base shader generation routine to generate most
1358 of the pixel shader string for us */
1359 generate_base_shader( (IWineD3DBaseShader
*) This
, &buffer
, pFunction
);
1361 if (This
->baseShader
.hex_version
< D3DPS_VERSION(2,0))
1362 shader_addline(&buffer
, "MOV result.color, R0;\n");
1363 shader_addline(&buffer
, "END\n\0");
1365 /* TODO: change to resource.glObjectHandle or something like that */
1366 GL_EXTCALL(glGenProgramsARB(1, &This
->baseShader
.prgId
));
1368 TRACE("Creating a hw pixel shader, prg=%d\n", This
->baseShader
.prgId
);
1369 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, This
->baseShader
.prgId
));
1371 TRACE("Created hw pixel shader, prg=%d\n", This
->baseShader
.prgId
);
1372 /* Create the program and check for errors */
1373 GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
1374 buffer
.bsize
, buffer
.buffer
));
1376 if (glGetError() == GL_INVALID_OPERATION
) {
1378 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errPos
);
1379 FIXME("HW PixelShader Error at position %d: %s\n",
1380 errPos
, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB
)));
1381 This
->baseShader
.prgId
= -1;
1385 #if 1 /* if were using the data buffer of device then we don't need to free it */
1386 HeapFree(GetProcessHeap(), 0, buffer
.buffer
);
1390 static HRESULT WINAPI
IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader
*iface
, CONST DWORD
*pFunction
) {
1391 IWineD3DPixelShaderImpl
*This
= (IWineD3DPixelShaderImpl
*)iface
;
1392 const DWORD
* pToken
= pFunction
;
1393 const SHADER_OPCODE
*curOpcode
= NULL
;
1397 TRACE("(%p) : Parsing programme\n", This
);
1399 if (NULL
!= pToken
) {
1400 while (D3DPS_END() != *pToken
) {
1401 if (shader_is_pshader_version(*pToken
)) { /** version */
1402 pshader_set_version(This
, *pToken
);
1407 if (shader_is_comment(*pToken
)) { /** comment */
1408 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1410 TRACE("//%s\n", (char*)pToken
);
1411 pToken
+= comment_len
;
1412 len
+= comment_len
+ 1;
1415 if (!This
->baseShader
.version
) {
1416 WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This
);
1418 opcode_token
= *pToken
++;
1419 curOpcode
= shader_get_opcode((IWineD3DBaseShader
*) This
, opcode_token
);
1421 if (NULL
== curOpcode
) {
1424 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token
);
1425 tokens_read
= shader_skip_unrecognized((IWineD3DBaseShader
*) This
, pToken
);
1426 pToken
+= tokens_read
;
1430 if (curOpcode
->opcode
== D3DSIO_DCL
) {
1431 DWORD usage
= *pToken
;
1432 DWORD param
= *(pToken
+ 1);
1433 DWORD regtype
= shader_get_regtype(param
);
1435 /* Only print extended declaration for samplers or 3.0 input registers */
1436 if (regtype
== D3DSPR_SAMPLER
||
1437 (This
->baseShader
.version
>= 30 && regtype
== D3DSPR_INPUT
))
1438 shader_program_dump_decl_usage(usage
, param
);
1442 shader_dump_ins_modifiers(param
);
1444 shader_dump_param((IWineD3DBaseShader
*) This
, param
, 0, 0);
1448 } else if (curOpcode
->opcode
== D3DSIO_DEF
) {
1450 unsigned int offset
= shader_get_float_offset(*pToken
);
1452 TRACE("def c%u = %f, %f, %f, %f", offset
,
1453 *(float *)(pToken
+ 1),
1454 *(float *)(pToken
+ 2),
1455 *(float *)(pToken
+ 3),
1456 *(float *)(pToken
+ 4));
1461 } else if (curOpcode
->opcode
== D3DSIO_DEFI
) {
1463 TRACE("defi i%lu = %ld, %ld, %ld, %ld", *pToken
& D3DSP_REGNUM_MASK
,
1464 (long) *(pToken
+ 1),
1465 (long) *(pToken
+ 2),
1466 (long) *(pToken
+ 3),
1467 (long) *(pToken
+ 4));
1472 } else if (curOpcode
->opcode
== D3DSIO_DEFB
) {
1474 TRACE("defb b%lu = %s", *pToken
& D3DSP_REGNUM_MASK
,
1475 *(pToken
+ 1)? "true": "false");
1482 DWORD param
, addr_token
;
1485 /* Print out predication source token first - it follows
1486 * the destination token. */
1487 if (opcode_token
& D3DSHADER_INSTRUCTION_PREDICATED
) {
1489 shader_dump_param((IWineD3DBaseShader
*) This
, *(pToken
+ 2), 0, 1);
1493 TRACE("%s", curOpcode
->name
);
1494 if (curOpcode
->num_params
> 0) {
1496 /* Destination token */
1497 tokens_read
= shader_get_param((IWineD3DBaseShader
*) This
,
1498 pToken
, ¶m
, &addr_token
);
1499 pToken
+= tokens_read
;
1502 shader_dump_ins_modifiers(param
);
1504 shader_dump_param((IWineD3DBaseShader
*) This
, param
, addr_token
, 0);
1506 /* Predication token - already printed out, just skip it */
1507 if (opcode_token
& D3DSHADER_INSTRUCTION_PREDICATED
) {
1512 /* Other source tokens */
1513 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1515 tokens_read
= shader_get_param((IWineD3DBaseShader
*) This
,
1516 pToken
, ¶m
, &addr_token
);
1517 pToken
+= tokens_read
;
1521 shader_dump_param((IWineD3DBaseShader
*) This
, param
, addr_token
, 1);
1528 This
->baseShader
.functionLength
= (len
+ 1) * sizeof(DWORD
);
1530 This
->baseShader
.functionLength
= 1; /* no Function defined use fixed function vertex processing */
1533 /* Generate HW shader in needed */
1534 if (NULL
!= pFunction
&& wined3d_settings
.vs_mode
== VS_HW
) {
1535 TRACE("(%p) : Generating hardware program\n", This
);
1537 IWineD3DPixelShaderImpl_GenerateShader(iface
, pFunction
);
1541 TRACE("(%p) : Copying the function\n", This
);
1542 /* copy the function ... because it will certainly be released by application */
1543 if (NULL
!= pFunction
) {
1544 This
->baseShader
.function
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->baseShader
.functionLength
);
1545 memcpy((void *)This
->baseShader
.function
, pFunction
, This
->baseShader
.functionLength
);
1547 This
->baseShader
.function
= NULL
;
1550 /* TODO: Some proper return values for failures */
1551 TRACE("(%p) : Returning WINED3D_OK\n", This
);
1555 const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl
=
1557 /*** IUnknown methods ***/
1558 IWineD3DPixelShaderImpl_QueryInterface
,
1559 IWineD3DPixelShaderImpl_AddRef
,
1560 IWineD3DPixelShaderImpl_Release
,
1561 /*** IWineD3DBase methods ***/
1562 IWineD3DPixelShaderImpl_GetParent
,
1563 /*** IWineD3DBaseShader methods ***/
1564 IWineD3DPixelShaderImpl_SetFunction
,
1565 /*** IWineD3DPixelShader methods ***/
1566 IWineD3DPixelShaderImpl_GetDevice
,
1567 IWineD3DPixelShaderImpl_GetFunction