2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader
);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34 /* Shader debugging - Change the following line to enable debugging of software
36 #if 0 /* Musxt not be 1 in cvs version */
37 # define VSTRACE(A) TRACE A
38 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
41 # define TRACE_VSVECTOR(name)
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
51 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
53 * Using Vertex Shaders
54 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
60 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
69 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
71 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
72 * http://developer.nvidia.com/view.asp?IO=vstovp
74 * NVIDIA: Memory Management with VAR
75 * http://developer.nvidia.com/view.asp?IO=var_memory_management
78 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
79 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
81 typedef void (*shader_fct_t
)();
83 typedef struct SHADER_OPCODE
{
87 CONST UINT num_params
;
88 shader_fct_t soft_fct
;
93 #define GLNAME_REQUIRE_GLSL ((const char *)1)
95 /*******************************
96 * vshader functions software VM
99 void vshader_add(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
100 d
->x
= s0
->x
+ s1
->x
;
101 d
->y
= s0
->y
+ s1
->y
;
102 d
->z
= s0
->z
+ s1
->z
;
103 d
->w
= s0
->w
+ s1
->w
;
104 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
105 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
108 void vshader_dp3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
109 d
->x
= d
->y
= d
->z
= d
->w
= s0
->x
* s1
->x
+ s0
->y
* s1
->y
+ s0
->z
* s1
->z
;
110 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
111 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
114 void vshader_dp4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
115 d
->x
= d
->y
= d
->z
= d
->w
= s0
->x
* s1
->x
+ s0
->y
* s1
->y
+ s0
->z
* s1
->z
+ s0
->w
* s1
->w
;
116 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
117 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
120 void vshader_dst(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
122 d
->y
= s0
->y
* s1
->y
;
125 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
126 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
129 void vshader_expp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
135 tmp
.f
= floorf(s0
->w
);
136 d
->x
= powf(2.0f
, tmp
.f
);
137 d
->y
= s0
->w
- tmp
.f
;
138 tmp
.f
= powf(2.0f
, s0
->w
);
139 tmp
.d
&= 0xFFFFFF00U
;
142 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
143 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
146 void vshader_lit(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
148 d
->y
= (0.0f
< s0
->x
) ? s0
->x
: 0.0f
;
149 d
->z
= (0.0f
< s0
->x
&& 0.0f
< s0
->y
) ? powf(s0
->y
, s0
->w
) : 0.0f
;
151 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
152 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
155 void vshader_logp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
156 float tmp_f
= fabsf(s0
->w
);
157 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
158 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
159 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
162 void vshader_mad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
163 d
->x
= s0
->x
* s1
->x
+ s2
->x
;
164 d
->y
= s0
->y
* s1
->y
+ s2
->y
;
165 d
->z
= s0
->z
* s1
->z
+ s2
->z
;
166 d
->w
= s0
->w
* s1
->w
+ s2
->w
;
167 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
168 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
));
171 void vshader_max(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
172 d
->x
= (s0
->x
>= s1
->x
) ? s0
->x
: s1
->x
;
173 d
->y
= (s0
->y
>= s1
->y
) ? s0
->y
: s1
->y
;
174 d
->z
= (s0
->z
>= s1
->z
) ? s0
->z
: s1
->z
;
175 d
->w
= (s0
->w
>= s1
->w
) ? s0
->w
: s1
->w
;
176 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
177 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
180 void vshader_min(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
181 d
->x
= (s0
->x
< s1
->x
) ? s0
->x
: s1
->x
;
182 d
->y
= (s0
->y
< s1
->y
) ? s0
->y
: s1
->y
;
183 d
->z
= (s0
->z
< s1
->z
) ? s0
->z
: s1
->z
;
184 d
->w
= (s0
->w
< s1
->w
) ? s0
->w
: s1
->w
;
185 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
186 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
189 void vshader_mov(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
194 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
195 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
198 void vshader_mul(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
199 d
->x
= s0
->x
* s1
->x
;
200 d
->y
= s0
->y
* s1
->y
;
201 d
->z
= s0
->z
* s1
->z
;
202 d
->w
= s0
->w
* s1
->w
;
203 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
207 void vshader_nop(void) {
208 /* NOPPPP ahhh too easy ;) */
209 VSTRACE(("executing nop\n"));
212 void vshader_rcp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
213 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
== s0
->w
) ? HUGE_VAL
: 1.0f
/ s0
->w
;
214 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
215 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
218 void vshader_rsq(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
219 float tmp_f
= fabsf(s0
->w
);
220 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
);
221 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
222 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
225 void vshader_sge(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
226 d
->x
= (s0
->x
>= s1
->x
) ? 1.0f
: 0.0f
;
227 d
->y
= (s0
->y
>= s1
->y
) ? 1.0f
: 0.0f
;
228 d
->z
= (s0
->z
>= s1
->z
) ? 1.0f
: 0.0f
;
229 d
->w
= (s0
->w
>= s1
->w
) ? 1.0f
: 0.0f
;
230 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
231 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
234 void vshader_slt(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
235 d
->x
= (s0
->x
< s1
->x
) ? 1.0f
: 0.0f
;
236 d
->y
= (s0
->y
< s1
->y
) ? 1.0f
: 0.0f
;
237 d
->z
= (s0
->z
< s1
->z
) ? 1.0f
: 0.0f
;
238 d
->w
= (s0
->w
< s1
->w
) ? 1.0f
: 0.0f
;
239 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
240 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
243 void vshader_sub(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
244 d
->x
= s0
->x
- s1
->x
;
245 d
->y
= s0
->y
- s1
->y
;
246 d
->z
= s0
->z
- s1
->z
;
247 d
->w
= s0
->w
- s1
->w
;
248 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
249 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
253 * Version 1.1 specific
256 void vshader_exp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
257 d
->x
= d
->y
= d
->z
= d
->w
= powf(2.0f
, s0
->w
);
258 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
259 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
262 void vshader_log(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
263 float tmp_f
= fabsf(s0
->w
);
264 d
->x
= d
->y
= d
->z
= d
->w
= (0.0f
!= tmp_f
) ? logf(tmp_f
) / logf(2.0f
) : -HUGE_VAL
;
265 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
266 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
269 void vshader_frc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
270 d
->x
= s0
->x
- floorf(s0
->x
);
271 d
->y
= s0
->y
- floorf(s0
->y
);
274 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
275 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
278 typedef FLOAT D3DMATRIX44
[4][4];
279 typedef FLOAT D3DMATRIX43
[4][3];
280 typedef FLOAT D3DMATRIX34
[3][4];
281 typedef FLOAT D3DMATRIX33
[3][3];
282 typedef FLOAT D3DMATRIX23
[2][3];
284 void vshader_m4x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat
) {
286 * Buggy CODE: here only if cast not work for copy/paste
287 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
288 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
289 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
290 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
291 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
292 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
293 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
295 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
296 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
297 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
298 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
+ mat
[3][3] * s0
->w
;
299 VSTRACE(("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
));
300 VSTRACE(("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
));
301 VSTRACE(("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
));
302 VSTRACE(("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
));
305 void vshader_m4x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX34 mat
) {
306 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
+ mat
[0][3] * s0
->w
;
307 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
+ mat
[1][3] * s0
->w
;
308 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
+ mat
[2][3] * s0
->w
;
310 VSTRACE(("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
));
311 VSTRACE(("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
));
312 VSTRACE(("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
));
313 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0
->w
, d
->w
));
316 void vshader_m3x4(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX43 mat
) {
317 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
318 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
319 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
320 d
->w
= mat
[3][0] * s0
->x
+ mat
[3][1] * s0
->y
+ mat
[3][2] * s0
->z
;
321 VSTRACE(("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
));
322 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
323 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], s0
->z
, d
->z
));
324 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat
[3][0], mat
[3][1], mat
[3][2], s0
->w
, d
->w
));
327 void vshader_m3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX33 mat
) {
328 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
329 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
330 d
->z
= mat
[2][0] * s0
->x
+ mat
[2][1] * s0
->y
+ mat
[2][2] * s0
->z
;
332 VSTRACE(("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
));
333 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat
[1][0], mat
[1][1], mat
[1][2], s0
->y
, d
->y
));
334 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat
[2][0], mat
[2][1], mat
[2][2], s0
->z
, d
->z
));
335 VSTRACE(("executing m3x3(4): (%f) \n", d
->w
));
338 void vshader_m3x2(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, D3DMATRIX23 mat
) {
340 d
->x
= mat
[0][0] * s0
->x
+ mat
[0][1] * s0
->y
+ mat
[0][2] * s0
->z
;
341 d
->y
= mat
[1][0] * s0
->x
+ mat
[1][1] * s0
->y
+ mat
[1][2] * s0
->z
;
347 * Version 2.0 specific
349 void vshader_lrp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
350 d
->x
= s0
->x
* (s1
->x
- s2
->x
) + s2
->x
;
351 d
->y
= s0
->y
* (s1
->y
- s2
->y
) + s2
->y
;
352 d
->z
= s0
->z
* (s1
->z
- s2
->z
) + s2
->z
;
353 d
->w
= s0
->w
* (s1
->w
- s2
->w
) + s2
->w
;
356 void vshader_crs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
357 d
->x
= s0
->y
* s1
->z
- s0
->z
* s1
->y
;
358 d
->y
= s0
->z
* s1
->x
- s0
->x
* s1
->z
;
359 d
->z
= s0
->x
* s1
->y
- s0
->y
* s1
->x
;
360 d
->w
= 0.9f
; /* w is undefined, so set it to something safeish */
362 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
363 s0
->x
, s0
->y
, s0
->z
, s0
->w
, s1
->x
, s1
->y
, s1
->z
, s1
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
366 void vshader_abs(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
372 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
373 s0
->x
, s0
->y
, s0
->z
, s0
->w
, d
->x
, d
->y
, d
->z
, d
->w
));
377 void vshader_texcoord(WINED3DSHADERVECTOR
* d
) {
381 void vshader_texkill(WINED3DSHADERVECTOR
* d
) {
385 void vshader_tex(WINED3DSHADERVECTOR
* d
) {
388 void vshader_texld(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
392 void vshader_texbem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
396 void vshader_texbeml(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
400 void vshader_texreg2ar(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
404 void vshader_texreg2gb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
408 void vshader_texm3x2pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
412 void vshader_texm3x2tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
416 void vshader_texm3x3pad(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
420 void vshader_texm3x3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
424 void vshader_texm3x3diff(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
428 void vshader_texm3x3spec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
432 void vshader_texm3x3vspec(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
436 void vshader_cnd(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
440 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
441 void vshader_def(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
, WINED3DSHADERVECTOR
* s3
) {
445 void vshader_texreg2rgb(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
449 void vshader_texdp3tex(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
453 void vshader_texm3x2depth(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
457 void vshader_texdp3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
461 void vshader_texm3x3(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
465 void vshader_texdepth(WINED3DSHADERVECTOR
* d
) {
469 void vshader_cmp(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
, WINED3DSHADERVECTOR
* s2
) {
473 void vshader_bem(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
477 void vshader_call(WINED3DSHADERVECTOR
* d
) {
481 void vshader_callnz(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
485 void vshader_loop(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
489 void vshader_ret(WINED3DSHADERVECTOR
* d
) {
493 void vshader_endloop(WINED3DSHADERVECTOR
* d
) {
497 void vshader_dcl(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
501 void vshader_pow(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
, WINED3DSHADERVECTOR
* s1
) {
505 void vshader_sng(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
509 void vshader_nrm(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
513 void vshader_sincos(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
517 void vshader_rep(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
521 void vshader_endrep(void) {
525 void vshader_if(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
529 void vshader_ifc(WINED3DSHADERVECTOR
* d
, WINED3DSHADERVECTOR
* s0
) {
533 void vshader_else(WINED3DSHADERVECTOR
* d
) {
537 void vshader_label(WINED3DSHADERVECTOR
* d
) {
541 void vshader_endif(WINED3DSHADERVECTOR
* d
) {
545 void vshader_break(WINED3DSHADERVECTOR
* d
) {
549 void vshader_breakc(WINED3DSHADERVECTOR
* d
) {
553 void vshader_mova(WINED3DSHADERVECTOR
* d
) {
557 void vshader_defb(WINED3DSHADERVECTOR
* d
) {
561 void vshader_defi(WINED3DSHADERVECTOR
* d
) {
565 void vshader_dp2add(WINED3DSHADERVECTOR
* d
) {
569 void vshader_dsx(WINED3DSHADERVECTOR
* d
) {
573 void vshader_dsy(WINED3DSHADERVECTOR
* d
) {
577 void vshader_texldd(WINED3DSHADERVECTOR
* d
) {
581 void vshader_setp(WINED3DSHADERVECTOR
* d
) {
585 void vshader_texldl(WINED3DSHADERVECTOR
* d
) {
589 void vshader_breakp(WINED3DSHADERVECTOR
* d
) {
595 * log, exp, frc, m*x* seems to be macros ins ... to see
597 static CONST SHADER_OPCODE vshader_ins
[] = {
598 {D3DSIO_NOP
, "nop", "NOP", 0, vshader_nop
, 0, 0},
599 {D3DSIO_MOV
, "mov", "MOV", 2, vshader_mov
, 0, 0},
600 {D3DSIO_ADD
, "add", "ADD", 3, vshader_add
, 0, 0},
601 {D3DSIO_SUB
, "sub", "SUB", 3, vshader_sub
, 0, 0},
602 {D3DSIO_MAD
, "mad", "MAD", 4, vshader_mad
, 0, 0},
603 {D3DSIO_MUL
, "mul", "MUL", 3, vshader_mul
, 0, 0},
604 {D3DSIO_RCP
, "rcp", "RCP", 2, vshader_rcp
, 0, 0},
605 {D3DSIO_RSQ
, "rsq", "RSQ", 2, vshader_rsq
, 0, 0},
606 {D3DSIO_DP3
, "dp3", "DP3", 3, vshader_dp3
, 0, 0},
607 {D3DSIO_DP4
, "dp4", "DP4", 3, vshader_dp4
, 0, 0},
608 {D3DSIO_MIN
, "min", "MIN", 3, vshader_min
, 0, 0},
609 {D3DSIO_MAX
, "max", "MAX", 3, vshader_max
, 0, 0},
610 {D3DSIO_SLT
, "slt", "SLT", 3, vshader_slt
, 0, 0},
611 {D3DSIO_SGE
, "sge", "SGE", 3, vshader_sge
, 0, 0},
612 {D3DSIO_ABS
, "abs", "ABS", 2, vshader_abs
, 0, 0},
613 {D3DSIO_EXP
, "exp", "EX2", 2, vshader_exp
, 0, 0},
614 {D3DSIO_LOG
, "log", "LG2", 2, vshader_log
, 0, 0},
615 {D3DSIO_LIT
, "lit", "LIT", 2, vshader_lit
, 0, 0},
616 {D3DSIO_DST
, "dst", "DST", 3, vshader_dst
, 0, 0},
617 {D3DSIO_LRP
, "lrp", "LRP", 4, vshader_lrp
, 0, 0},
618 {D3DSIO_FRC
, "frc", "FRC", 2, vshader_frc
, 0, 0},
619 {D3DSIO_M4x4
, "m4x4", "undefined", 3, vshader_m4x4
, 0, 0},
620 {D3DSIO_M4x3
, "m4x3", "undefined", 3, vshader_m4x3
, 0, 0},
621 {D3DSIO_M3x4
, "m3x4", "undefined", 3, vshader_m3x4
, 0, 0},
622 {D3DSIO_M3x3
, "m3x3", "undefined", 3, vshader_m3x3
, 0, 0},
623 {D3DSIO_M3x2
, "m3x2", "undefined", 3, vshader_m3x2
, 0, 0},
624 /** FIXME: use direct access so add the others opcodes as stubs */
625 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
626 They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
627 {D3DSIO_CALL
, "call", GLNAME_REQUIRE_GLSL
, 1, vshader_call
, 0, 0},
628 {D3DSIO_CALLNZ
, "callnz", GLNAME_REQUIRE_GLSL
, 2, vshader_callnz
, 0, 0},
629 {D3DSIO_LOOP
, "loop", GLNAME_REQUIRE_GLSL
, 2, vshader_loop
, 0, 0},
630 {D3DSIO_RET
, "ret", GLNAME_REQUIRE_GLSL
, 0, vshader_ret
, 0, 0},
631 {D3DSIO_ENDLOOP
, "endloop", GLNAME_REQUIRE_GLSL
, 0, vshader_endloop
, 0, 0},
632 {D3DSIO_LABEL
, "label", GLNAME_REQUIRE_GLSL
, 1, vshader_label
, 0, 0},
633 /* DCL is a specil operation */
634 {D3DSIO_DCL
, "dcl", NULL
, 1, vshader_dcl
, 0, 0},
635 {D3DSIO_POW
, "pow", "POW", 3, vshader_pow
, 0, 0},
636 {D3DSIO_CRS
, "crs", "XPS", 3, vshader_crs
, 0, 0},
637 /* TODO: sng can possibly be performed as
640 {D3DSIO_SGN
, "sng", NULL
, 2, vshader_sng
, 0, 0},
641 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
644 MUL vec.xyz, vec, tmp;
645 but I think this is better because it accounts for w properly.
651 {D3DSIO_NRM
, "nrm", NULL
, 2, vshader_nrm
, 0, 0},
652 {D3DSIO_SINCOS
, "sincos", NULL
, 2, vshader_sincos
, 0, 0},
653 {D3DSIO_REP
, "rep", GLNAME_REQUIRE_GLSL
, 2, vshader_rep
, 0, 0},
654 {D3DSIO_ENDREP
, "endrep", GLNAME_REQUIRE_GLSL
, 0, vshader_endrep
, 0, 0},
655 {D3DSIO_IF
, "if", GLNAME_REQUIRE_GLSL
, 2, vshader_if
, 0, 0},
656 {D3DSIO_IFC
, "ifc", GLNAME_REQUIRE_GLSL
, 2, vshader_ifc
, 0, 0},
657 {D3DSIO_ELSE
, "else", GLNAME_REQUIRE_GLSL
, 2, vshader_else
, 0, 0},
658 {D3DSIO_ENDIF
, "endif", GLNAME_REQUIRE_GLSL
, 2, vshader_endif
, 0, 0},
659 {D3DSIO_BREAK
, "break", GLNAME_REQUIRE_GLSL
, 2, vshader_break
, 0, 0},
660 {D3DSIO_BREAKC
, "breakc", GLNAME_REQUIRE_GLSL
, 2, vshader_breakc
, 0, 0},
661 {D3DSIO_MOVA
, "mova", GLNAME_REQUIRE_GLSL
, 2, vshader_mova
, 0, 0},
662 {D3DSIO_DEFB
, "defb", GLNAME_REQUIRE_GLSL
, 2, vshader_defb
, 0, 0},
663 {D3DSIO_DEFI
, "defi", GLNAME_REQUIRE_GLSL
, 2, vshader_defi
, 0, 0},
665 {D3DSIO_TEXCOORD
, "texcoord", GLNAME_REQUIRE_GLSL
, 1, vshader_texcoord
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXCOORD
, "texcrd", GLNAME_REQUIRE_GLSL
, 2, vshader_texcoord
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
667 {D3DSIO_TEXKILL
, "texkill", GLNAME_REQUIRE_GLSL
, 1, vshader_texkill
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
668 {D3DSIO_TEX
, "tex", GLNAME_REQUIRE_GLSL
, 1, vshader_tex
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
669 {D3DSIO_TEX
, "texld", GLNAME_REQUIRE_GLSL
, 2, vshader_texld
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
670 {D3DSIO_TEXBEM
, "texbem", GLNAME_REQUIRE_GLSL
, 2, vshader_texbem
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
671 {D3DSIO_TEXBEML
, "texbeml", GLNAME_REQUIRE_GLSL
, 2, vshader_texbeml
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
672 {D3DSIO_TEXREG2AR
,"texreg2ar",GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2ar
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
673 {D3DSIO_TEXREG2GB
,"texreg2gb",GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2gb
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXM3x2PAD
, "texm3x2pad", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2pad
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2TEX
, "texm3x2tex", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2tex
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXM3x3DIFF
, "texm3x3diff", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3diff
, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
677 {D3DSIO_TEXM3x3SPEC
, "texm3x3spec", GLNAME_REQUIRE_GLSL
, 3, vshader_texm3x3spec
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXM3x3VSPEC
, "texm3x3vspe", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3vspec
, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
680 {D3DSIO_EXPP
, "expp", "EXP", 2, vshader_expp
, 0, 0},
681 {D3DSIO_LOGP
, "logp", "LOG", 2, vshader_logp
, 0, 0},
682 {D3DSIO_CND
, "cnd", GLNAME_REQUIRE_GLSL
, 4, vshader_cnd
, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
683 /* def is a special operation */
684 {D3DSIO_DEF
, "def", NULL
, 5, vshader_def
, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
685 {D3DSIO_TEXREG2RGB
, "texreg2rgb", GLNAME_REQUIRE_GLSL
, 2, vshader_texreg2rgb
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
686 {D3DSIO_TEXDP3TEX
, "texdp3tex", GLNAME_REQUIRE_GLSL
, 2, vshader_texdp3tex
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
687 {D3DSIO_TEXM3x2DEPTH
, "texm3x2depth", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x2depth
,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
688 {D3DSIO_TEXDP3
, "texdp3", GLNAME_REQUIRE_GLSL
, 2, vshader_texdp3
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
689 {D3DSIO_TEXM3x3
, "texm3x3", GLNAME_REQUIRE_GLSL
, 2, vshader_texm3x3
, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
690 {D3DSIO_TEXDEPTH
, "texdepth", GLNAME_REQUIRE_GLSL
,1, vshader_texdepth
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
691 {D3DSIO_CMP
, "cmp", GLNAME_REQUIRE_GLSL
, 4, vshader_cmp
, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
692 {D3DSIO_BEM
, "bem", GLNAME_REQUIRE_GLSL
, 3, vshader_bem
, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
693 /* TODO: dp2add can be made out of multiple instuctions */
694 {D3DSIO_DP2ADD
, "dp2add", GLNAME_REQUIRE_GLSL
, 2, vshader_dp2add
, 0, 0},
695 {D3DSIO_DSX
, "dsx", GLNAME_REQUIRE_GLSL
, 2, vshader_dsx
, 0, 0},
696 {D3DSIO_DSY
, "dsy", GLNAME_REQUIRE_GLSL
, 2, vshader_dsy
, 0, 0},
697 {D3DSIO_TEXLDD
, "texldd", GLNAME_REQUIRE_GLSL
, 2, vshader_texldd
, 0, 0},
698 {D3DSIO_SETP
, "setp", GLNAME_REQUIRE_GLSL
, 2, vshader_setp
, 0, 0},
699 {D3DSIO_TEXLDL
, "texdl", GLNAME_REQUIRE_GLSL
, 2, vshader_texldl
, 0, 0},
700 {D3DSIO_BREAKP
, "breakp", GLNAME_REQUIRE_GLSL
, 2, vshader_breakp
, 0, 0},
701 {D3DSIO_PHASE
, "phase", GLNAME_REQUIRE_GLSL
, 0, vshader_nop
, 0, 0},
702 {0, NULL
, NULL
, 0, NULL
, 0, 0}
706 inline static const SHADER_OPCODE
* vshader_program_get_opcode(const DWORD code
) {
708 /** TODO: use dichotomic search or hash table */
709 while (NULL
!= vshader_ins
[i
].name
) {
710 if ((code
& D3DSI_OPCODE_MASK
) == vshader_ins
[i
].opcode
) {
711 return &vshader_ins
[i
];
715 FIXME("Unsupported opcode %lx\n",code
);
719 inline static void vshader_program_dump_param(const DWORD param
, int input
) {
720 static const char* rastout_reg_names
[] = { "oPos", "oFog", "oPts" };
721 static const char swizzle_reg_chars
[] = "xyzw";
723 DWORD reg
= param
& 0x00001FFF;
724 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
726 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) TRACE("-");
730 TRACE("R[%lu]", reg
);
736 TRACE("C[%s%lu]", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
738 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
739 TRACE("a[%lu]", reg
);
742 TRACE("%s", rastout_reg_names
[reg
]);
745 TRACE("oD[%lu]", reg
);
747 case D3DSPR_TEXCRDOUT
:
748 TRACE("oT[%lu]", reg
);
751 FIXME("Unknown %lu %u reg %lu\n",regtype
, D3DSPR_ATTROUT
, reg
);
756 /** operand output */
757 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
758 if (param
& D3DSP_WRITEMASK_0
) TRACE(".x");
759 if (param
& D3DSP_WRITEMASK_1
) TRACE(".y");
760 if (param
& D3DSP_WRITEMASK_2
) TRACE(".z");
761 if (param
& D3DSP_WRITEMASK_3
) TRACE(".w");
765 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
766 DWORD swizzle_x
= swizzle
& 0x03;
767 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
768 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
769 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
771 * swizzle bits fields:
774 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
775 if (swizzle_x
== swizzle_y
&&
776 swizzle_x
== swizzle_z
&&
777 swizzle_x
== swizzle_w
) {
778 TRACE(".%c", swizzle_reg_chars
[swizzle_x
]);
781 swizzle_reg_chars
[swizzle_x
],
782 swizzle_reg_chars
[swizzle_y
],
783 swizzle_reg_chars
[swizzle_z
],
784 swizzle_reg_chars
[swizzle_w
]);
790 inline static void vshader_program_dump_vs_param(const DWORD param
, int input
) {
791 static const char* rastout_reg_names
[] = { "oPos", "oFog", "oPts" };
792 static const char swizzle_reg_chars
[] = "xyzw";
793 /* the unknown mask is for bits not yet accounted for by any other mask... */
794 #define UNKNOWN_MASK 0xC000
796 /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
797 #define EXTENDED_REG 0x1800
799 DWORD reg
= param
& D3DSP_REGNUM_MASK
; /* 0x00001FFF; isn't this D3DSP_REGNUM_MASK? */
800 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
) | ((param
& EXTENDED_REG
) >> 8);
802 if(param
& UNKNOWN_MASK
) { /* if this register has any of the unknown bits set then report them*/
803 FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype
, (param
& EXTENDED_REG
), param
& UNKNOWN_MASK
);
806 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) TRACE("-");
808 switch (regtype
/*<< D3DSP_REGTYPE_SHIFT*/) {
816 TRACE("c%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
818 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
822 TRACE("%s", rastout_reg_names
[reg
]);
827 case D3DSPR_TEXCRDOUT
:
830 case D3DSPR_CONSTINT
:
831 TRACE("i%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
833 case D3DSPR_CONSTBOOL
:
834 TRACE("b%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
840 TRACE("aL%s%lu", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "a0.x + " : "", reg
);
843 FIXME("Unknown %lu reg %lu\n",regtype
, reg
);
848 /** operand output */
849 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
850 if (param
& D3DSP_WRITEMASK_0
) TRACE(".x");
851 if (param
& D3DSP_WRITEMASK_1
) TRACE(".y");
852 if (param
& D3DSP_WRITEMASK_2
) TRACE(".z");
853 if (param
& D3DSP_WRITEMASK_3
) TRACE(".w");
857 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
858 DWORD swizzle_x
= swizzle
& 0x03;
859 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
860 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
861 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
863 * swizzle bits fields:
866 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) != swizzle
) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
867 if (swizzle_x
== swizzle_y
&&
868 swizzle_x
== swizzle_z
&&
869 swizzle_x
== swizzle_w
) {
870 TRACE(".%c", swizzle_reg_chars
[swizzle_x
]);
873 swizzle_reg_chars
[swizzle_x
],
874 swizzle_reg_chars
[swizzle_y
],
875 swizzle_reg_chars
[swizzle_z
],
876 swizzle_reg_chars
[swizzle_w
]);
882 inline static void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl
*This
, DWORD token
) {
884 switch(token
& 0xFFFF) {
885 case D3DDECLUSAGE_POSITION
:
886 TRACE("%s%ld ", "position",(token
& 0xF0000) >> 16);
888 case D3DDECLUSAGE_BLENDINDICES
:
889 TRACE("%s ", "blend");
891 case D3DDECLUSAGE_BLENDWEIGHT
:
892 TRACE("%s ", "weight");
894 case D3DDECLUSAGE_NORMAL
:
895 TRACE("%s%ld ", "normal",(token
& 0xF0000) >> 16);
897 case D3DDECLUSAGE_PSIZE
:
898 TRACE("%s ", "psize");
900 case D3DDECLUSAGE_COLOR
:
901 if((token
& 0xF0000) >> 16 == 0) {
902 TRACE("%s ", "color");
904 TRACE("%s ", "specular");
907 case D3DDECLUSAGE_TEXCOORD
:
908 TRACE("%s%ld ", "texture", (token
& 0xF0000) >> 16);
910 case D3DDECLUSAGE_TANGENT
:
911 TRACE("%s ", "tangent");
913 case D3DDECLUSAGE_BINORMAL
:
914 TRACE("%s ", "binormal");
916 case D3DDECLUSAGE_TESSFACTOR
:
917 TRACE("%s ", "tessfactor");
919 case D3DDECLUSAGE_POSITIONT
:
920 TRACE("%s%ld ", "positionT",(token
& 0xF0000) >> 16);
922 case D3DDECLUSAGE_FOG
:
925 case D3DDECLUSAGE_DEPTH
:
926 TRACE("%s ", "depth");
928 case D3DDECLUSAGE_SAMPLE
:
929 TRACE("%s ", "sample");
932 FIXME("Unrecognised dcl %08lx", token
& 0xFFFF);
936 inline static BOOL
vshader_is_version_token(DWORD token
) {
937 return 0xFFFE0000 == (token
& 0xFFFE0000);
940 inline static BOOL
vshader_is_comment_token(DWORD token
) {
941 return D3DSIO_COMMENT
== (token
& D3DSI_OPCODE_MASK
);
944 inline static void vshader_program_add_output_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
945 /** operand output */
946 if ((param
& D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
948 if (param
& D3DSP_WRITEMASK_0
) { strcat(hwLine
, "x"); }
949 if (param
& D3DSP_WRITEMASK_1
) { strcat(hwLine
, "y"); }
950 if (param
& D3DSP_WRITEMASK_2
) { strcat(hwLine
, "z"); }
951 if (param
& D3DSP_WRITEMASK_3
) { strcat(hwLine
, "w"); }
955 inline static void vshader_program_add_input_param_swizzle(const DWORD param
, int is_color
, char *hwLine
) {
956 static const char swizzle_reg_chars_color_fix
[] = "zyxw";
957 static const char swizzle_reg_chars
[] = "xyzw";
958 const char* swizzle_regs
= NULL
;
962 DWORD swizzle
= (param
& D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
963 DWORD swizzle_x
= swizzle
& 0x03;
964 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
965 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
966 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
969 swizzle_regs
= swizzle_reg_chars_color_fix
;
971 swizzle_regs
= swizzle_reg_chars
;
975 * swizzle bits fields:
978 if ((D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
980 sprintf(tmpReg
, ".%c%c%c%c",
981 swizzle_regs
[swizzle_x
],
982 swizzle_regs
[swizzle_y
],
983 swizzle_regs
[swizzle_z
],
984 swizzle_regs
[swizzle_w
]);
985 strcat(hwLine
, tmpReg
);
989 if (swizzle_x
== swizzle_y
&&
990 swizzle_x
== swizzle_z
&&
991 swizzle_x
== swizzle_w
)
993 sprintf(tmpReg
, ".%c", swizzle_regs
[swizzle_x
]);
994 strcat(hwLine
, tmpReg
);
996 sprintf(tmpReg
, ".%c%c%c%c",
997 swizzle_regs
[swizzle_x
],
998 swizzle_regs
[swizzle_y
],
999 swizzle_regs
[swizzle_z
],
1000 swizzle_regs
[swizzle_w
]);
1001 strcat(hwLine
, tmpReg
);
1005 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl
*This
, const DWORD param
, BOOL is_input
, char *hwLine
) {
1006 /* oPos, oFog and oPts in D3D */
1007 static const char* hwrastout_reg_names
[] = { "result.position", "result.fogcoord", "result.pointsize" };
1009 DWORD reg
= param
& 0x00001FFF;
1010 DWORD regtype
= ((param
& D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
1012 BOOL is_color
= FALSE
;
1014 if ((param
& D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
) {
1015 strcat(hwLine
, " -");
1017 strcat(hwLine
, " ");
1022 sprintf(tmpReg
, "T%lu", reg
);
1023 strcat(hwLine
, tmpReg
);
1026 if (reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
]
1027 || reg
== This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
]) {
1030 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1031 if (This
->namedArrays
) {
1032 sprintf(tmpReg
, "namedVertex%lu", reg
);
1034 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1035 sprintf(tmpReg
, "vertex.attrib[%lu]", reg
);
1037 strcat(hwLine
, tmpReg
);
1040 /* FIXME: some constants are named so we need a constants map*/
1041 if (This
->constantsUsedBitmap
[reg
] == VS_CONSTANT_CONSTANT
) {
1042 if (param
& D3DVS_ADDRMODE_RELATIVE
) {
1043 FIXME("Relative addressing not expected for a named constant %lu\n", reg
);
1045 sprintf(tmpReg
, "const%lu", reg
);
1047 sprintf(tmpReg
, "C[%s%lu]", (param
& D3DVS_ADDRMODE_RELATIVE
) ? "A0.x + " : "", reg
);
1049 strcat(hwLine
, tmpReg
);
1051 case D3DSPR_ADDR
: /*case D3DSPR_TEXTURE:*/
1052 sprintf(tmpReg
, "A%lu", reg
);
1053 strcat(hwLine
, tmpReg
);
1055 case D3DSPR_RASTOUT
:
1056 sprintf(tmpReg
, "%s", hwrastout_reg_names
[reg
]);
1057 strcat(hwLine
, tmpReg
);
1059 case D3DSPR_ATTROUT
:
1061 strcat(hwLine
, "result.color.primary");
1063 strcat(hwLine
, "result.color.secondary");
1066 case D3DSPR_TEXCRDOUT
:
1067 sprintf(tmpReg
, "result.texcoord[%lu]", reg
);
1068 strcat(hwLine
, tmpReg
);
1071 FIXME("Unknown reg type %ld %ld\n", regtype
, reg
);
1076 vshader_program_add_output_param_swizzle(param
, is_color
, hwLine
);
1078 vshader_program_add_input_param_swizzle(param
, is_color
, hwLine
);
1082 DWORD MacroExpansion
[4*4];
1084 int ExpandMxMacro(DWORD macro_opcode
, const DWORD
* args
) {
1086 int nComponents
= 0;
1088 switch(macro_opcode
) {
1091 opcode
= D3DSIO_DP4
;
1095 opcode
= D3DSIO_DP4
;
1099 opcode
= D3DSIO_DP3
;
1103 opcode
= D3DSIO_DP3
;
1107 opcode
= D3DSIO_DP3
;
1112 for (i
= 0; i
< nComponents
; i
++) {
1113 MacroExpansion
[i
*4+0] = opcode
;
1114 MacroExpansion
[i
*4+1] = ((*args
) & ~D3DSP_WRITEMASK_ALL
)|(D3DSP_WRITEMASK_0
<<i
);
1115 MacroExpansion
[i
*4+2] = *(args
+1);
1116 MacroExpansion
[i
*4+3] = (*(args
+2))+i
;
1121 static void parse_decl_usage(IWineD3DVertexShaderImpl
*This
, INT usage
, INT arrayNo
)
1123 switch(usage
& 0xFFFF) {
1124 case D3DDECLUSAGE_POSITION
:
1125 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1126 TRACE("Setting position to %d\n", arrayNo
);
1127 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION
] = arrayNo
;
1128 This
->namedArrays
= TRUE
;
1130 /* TODO: position indexes go from 0-8!!*/
1131 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1132 /* robots uses positions up to 8, the position arrays are just packed.*/
1133 if ((usage
& 0xF0000) >> 16 > 1) {
1134 TRACE("Loaded for position %d (greater than 2)\n", (usage
& 0xF0000) >> 16);
1136 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITION2
+ ((usage
& 0xF0000) >> 16) -1] = arrayNo
;
1137 This
->declaredArrays
= TRUE
;
1140 case D3DDECLUSAGE_BLENDINDICES
:
1141 /* not supported by openGL */
1142 TRACE("Setting BLENDINDICES to %d\n", arrayNo
);
1143 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDINDICES
] = arrayNo
;
1144 This
->declaredArrays
= TRUE
;
1145 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1147 case D3DDECLUSAGE_BLENDWEIGHT
:
1148 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo
);
1149 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BLENDWEIGHT
] = arrayNo
;
1150 This
->namedArrays
= TRUE
;
1151 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1153 case D3DDECLUSAGE_NORMAL
:
1154 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1155 TRACE("Setting normal to %d\n", arrayNo
);
1156 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL
] = arrayNo
;
1157 This
->namedArrays
= TRUE
;
1159 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1160 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_NORMAL2
] = arrayNo
;
1161 This
->declaredArrays
= TRUE
;
1164 case D3DDECLUSAGE_PSIZE
:
1165 TRACE("Setting PSIZE to %d\n", arrayNo
);
1166 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_PSIZE
] = arrayNo
;
1167 This
->namedArrays
= TRUE
;
1168 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1170 case D3DDECLUSAGE_COLOR
:
1171 if((usage
& 0xF0000) >> 16 == 0) {
1172 TRACE("Setting DIFFUSE to %d\n", arrayNo
);
1173 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DIFFUSE
] = arrayNo
;
1174 This
->namedArrays
= TRUE
;
1176 TRACE("Setting SPECULAR to %d\n", arrayNo
);
1177 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SPECULAR
] = arrayNo
;
1178 This
->namedArrays
= TRUE
;
1181 case D3DDECLUSAGE_TEXCOORD
:
1182 This
->namedArrays
= TRUE
;
1183 /* only 7 texture coords have been designed for, so run a quick sanity check */
1184 if ((usage
& 0xF0000) >> 16 > 7) {
1185 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This
, (usage
& 0xF0000) >> 16);
1187 TRACE("Setting TEXCOORD %d to %d\n", ((usage
& 0xF0000) >> 16), arrayNo
);
1188 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TEXCOORD0
+ ((usage
& 0xF0000) >> 16)] = arrayNo
;
1191 /* The following aren't supported by openGL,
1192 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1193 this should be caught in the first pass */
1194 case D3DDECLUSAGE_TANGENT
:
1195 TRACE("Setting TANGENT to %d\n", arrayNo
);
1196 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TANGENT
] = arrayNo
;
1197 This
->declaredArrays
= TRUE
;
1199 case D3DDECLUSAGE_BINORMAL
:
1200 TRACE("Setting BINORMAL to %d\n", arrayNo
);
1201 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_BINORMAL
] = arrayNo
;
1202 This
->declaredArrays
= TRUE
;
1204 case D3DDECLUSAGE_TESSFACTOR
:
1205 TRACE("Setting TESSFACTOR to %d\n", arrayNo
);
1206 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_TESSFACTOR
] = arrayNo
;
1207 This
->declaredArrays
= TRUE
;
1209 case D3DDECLUSAGE_POSITIONT
:
1210 if((usage
& 0xF0000) >> 16 == 0) { /* tween data */
1211 FIXME("Setting positiont to %d\n", arrayNo
);
1212 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT
] = arrayNo
;
1213 This
->namedArrays
= TRUE
;
1215 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo
, (usage
& 0xF0000) >> 16);
1216 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_POSITIONT2
] = arrayNo
;
1217 This
->declaredArrays
= TRUE
;
1218 if ((usage
& 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1221 case D3DDECLUSAGE_FOG
:
1222 /* supported by OpenGL */
1223 TRACE("Setting FOG to %d\n", arrayNo
);
1224 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_FOG
] = arrayNo
;
1225 This
->namedArrays
= TRUE
;
1227 case D3DDECLUSAGE_DEPTH
:
1228 TRACE("Setting DEPTH to %d\n", arrayNo
);
1229 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_DEPTH
] = arrayNo
;
1230 This
->declaredArrays
= TRUE
;
1232 case D3DDECLUSAGE_SAMPLE
:
1233 TRACE("Setting SAMPLE to %d\n", arrayNo
);
1234 This
->arrayUsageMap
[WINED3DSHADERDECLUSAGE_SAMPLE
] = arrayNo
;
1235 This
->declaredArrays
= TRUE
;
1238 FIXME("Unrecognised dcl %08x", usage
& 0xFFFF);
1243 * Function parser ...
1246 inline static VOID
IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader
*iface
, CONST DWORD
* pFunction
) {
1247 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1248 const DWORD
* pToken
= pFunction
;
1249 const DWORD
* pSavedToken
= NULL
;
1250 const SHADER_OPCODE
* curOpcode
= NULL
;
1253 unsigned lineNum
= 0;
1254 char *pgmStr
= NULL
;
1256 DWORD nUseAddressRegister
= 0;
1257 DWORD nUseTempRegister
= 0;
1261 #if 0 /* TODO: loope register (just another address register ) */
1262 BOOL hasLoops
= FALSE
;
1265 #define PGMSIZE 65535
1266 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1269 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1270 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1271 if (This
->device
->fixupVertexBufferSize
< PGMSIZE
) {
1272 HeapFree(GetProcessHeap(), 0, This
->fixupVertexBuffer
);
1273 This
->fixupVertexBuffer
= HeapAlloc(GetProcessHeap() , 0, PGMSIZE
);
1274 This
->fixupVertexBufferSize
= PGMSIZE
;
1275 This
->fixupVertexBuffer
[0] = 0;
1277 pgmStr
= This
->device
->fixupVertexBuffer
;
1279 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1280 int _tmpLineLen = strlen(_tmpLine); \
1281 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1282 ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1284 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1286 pgmLength += _tmpLineLen; \
1289 pgmStr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 65535); /* 64kb should be enough */
1290 /* Initialise the shader */
1291 This
->namedArrays
= FALSE
;
1292 This
->declaredArrays
= FALSE
;
1293 for (i
= 0; i
< WINED3DSHADERDECLUSAGE_MAX_USAGE
; i
++) {
1294 This
->arrayUsageMap
[i
] = -1;
1296 /* set all the tmpsUsed to not used */
1297 memset(tmpsUsed
, FALSE
, sizeof(tmpsUsed
));
1299 /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1300 This
->highestConstant
= -1;
1303 * First pass to determine what we need to declare:
1304 * - Temporary variables
1305 * - Address variables
1307 if (NULL
!= pToken
) {
1308 while (D3DVS_END() != *pToken
) {
1309 if (vshader_is_version_token(*pToken
)) {
1314 if (vshader_is_comment_token(*pToken
)) { /** comment */
1315 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1317 pToken
+= comment_len
;
1320 curOpcode
= vshader_program_get_opcode(*pToken
);
1325 if (NULL
== curOpcode
) {
1326 while (*pToken
& 0x80000000) {
1327 FIXME("unrecognized opcode: %08lx\n", *pToken
);
1328 /* skip unrecognized opcode */
1332 if (curOpcode
->opcode
== D3DSIO_DCL
){
1333 INT usage
= *pToken
++;
1334 INT arrayNo
= (*pToken
++ & 0x00001FFF);
1335 parse_decl_usage(This
, usage
, arrayNo
);
1336 } else if(curOpcode
->opcode
== D3DSIO_DEF
) {
1337 This
->constantsUsedBitmap
[*pToken
& 0xFF] = VS_CONSTANT_CONSTANT
;
1338 FIXME("Constant %ld\n", *pToken
& 0xFF);
1346 /* Check to see if and tmp or addressing redisters are used */
1347 if (curOpcode
->num_params
> 0) {
1348 regtype
= ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
));
1349 reg
= ((*pToken
) & 0x00001FFF);
1350 if (D3DSPR_ADDR
== regtype
&& nUseAddressRegister
<= reg
) nUseAddressRegister
= reg
+ 1;
1351 if (D3DSPR_TEMP
== regtype
){
1352 tmpsUsed
[reg
] = TRUE
;
1353 if(nUseTempRegister
<= reg
) nUseTempRegister
= reg
+ 1;
1356 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1357 regtype
= ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
));
1358 reg
= ((*pToken
) & 0x00001FFF);
1359 if (D3DSPR_ADDR
== regtype
&& nUseAddressRegister
<= reg
) nUseAddressRegister
= reg
+ 1;
1360 if (D3DSPR_TEMP
== regtype
){
1361 tmpsUsed
[reg
] = TRUE
;
1362 if(nUseTempRegister
<= reg
) nUseTempRegister
= reg
+ 1;
1368 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1369 if (curOpcode
->glname
== GLNAME_REQUIRE_GLSL
) {
1370 FIXME("This shader requires gl shader language support\n");
1372 This
->shaderLanguage
= GLSHADER_GLSL
;
1380 #define VSHADER_ALWAYS_NUMBERED
1383 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1384 /* TODO: using numbered arrays for software shaders makes things easier */
1385 This
->declaredArrays
= TRUE
;
1388 /* named arrays and declared arrays are mutually exclusive */
1389 if (This
->declaredArrays
) {
1390 This
->namedArrays
= FALSE
;
1393 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1394 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1397 /** second pass, now generate */
1400 if (NULL
!= pToken
) {
1403 if ((nRemInstr
>= 0) && (--nRemInstr
== -1))
1404 /* Macro is finished, continue normal path */
1405 pToken
= pSavedToken
;
1406 if (D3DVS_END() == *pToken
)
1409 if (vshader_is_version_token(*pToken
)) { /** version */
1410 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1411 int version
= (((*pToken
>> 8) & 0x0F) * 10) + (*pToken
& 0x0F);
1415 TRACE("found version token vs.%lu.%lu;\n", (*pToken
>> 8) & 0x0F, (*pToken
& 0x0F));
1417 /* Each release of vertex shaders has had different numbers of temp registers */
1420 case 11: numTemps
=12;
1421 numConstants
=96;/* min(GL_LIMITS(constants),96) */
1422 strcpy(tmpLine
, "!!ARBvp1.0\n");
1423 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1425 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1426 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1427 TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1428 case 20: numTemps
=12; /* min(GL_LIMITS(temps),12) */
1429 numConstants
=96; /* min(GL_LIMITS(constants),256) */
1430 strcpy(tmpLine
, "!!ARBvp1.0\n");
1431 FIXME("No work done yet to support vs2.0 in hw\n");
1432 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1434 case 21: numTemps
=12; /* min(GL_LIMITS(temps),12) */
1435 numConstants
=96; /* min(GL_LIMITS(constants),256) */
1436 strcpy(tmpLine
, "!!ARBvp1.0\n");
1437 FIXME("No work done yet to support vs2.1 in hw\n");
1438 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1440 case 30: numTemps
=32; /* min(GL_LIMITS(temps),32) */
1441 numConstants
=96;/* min(GL_LIMITS(constants),256) */
1442 strcpy(tmpLine
, "!!ARBvp3.0\n");
1443 FIXME("No work done yet to support vs3.0 in hw\n");
1444 TRACE("GL HW (%u) : %s", pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1447 numTemps
=12;/* min(GL_LIMITS(temps),12) */
1448 numConstants
=96;/* min(GL_LIMITS(constants),96) */
1449 strcpy(tmpLine
, "!!ARBvp1.0\n");
1450 FIXME("Unrecognized vertex shader version %d!\n", version
);
1452 PNSTRCAT(pgmStr
, tmpLine
);
1456 /* This should be a bitmap so that only temp registers that are used are declared. */
1457 for (i
= 0; i
< nUseTempRegister
/* we should check numTemps here */ ; i
++) {
1458 if (tmpsUsed
[i
]) { /* only write out the temps if they are actually in use */
1459 sprintf(tmpLine
, "TEMP T%ld;\n", i
);
1461 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1462 PNSTRCAT(pgmStr
, tmpLine
);
1466 /* TODO: loop register counts as an address register */
1467 for (i
= 0; i
< nUseAddressRegister
; i
++) {
1468 sprintf(tmpLine
, "ADDRESS A%ld;\n", i
);
1470 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1471 PNSTRCAT(pgmStr
, tmpLine
);
1474 /* Due to the dynamic constants binding mechanism, we need to declare
1475 * all the constants for relative addressing. */
1476 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1477 if (GL_VEND(MESA
) || GL_VEND(WINE
)) {
1480 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1481 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1483 sprintf(tmpLine
, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants
, numConstants
- 1);
1484 TRACE("GL HW (%u,%u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1485 PNSTRCAT(pgmStr
, tmpLine
);
1492 if (vshader_is_comment_token(*pToken
)) { /** comment */
1493 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1495 FIXME("#%s\n", (char*)pToken
);
1496 pToken
+= comment_len
;
1500 curOpcode
= vshader_program_get_opcode(*pToken
);
1502 if (NULL
== curOpcode
) {
1503 /* unknown current opcode ... (shouldn't be any!) */
1504 while (*pToken
& 0x80000000) {
1505 FIXME("unrecognized opcode: %08lx\n", *pToken
);
1508 } else if (GLNAME_REQUIRE_GLSL
== curOpcode
->glname
) {
1509 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1511 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode
->name
);
1512 pToken
+= curOpcode
->num_params
;
1514 /* Build opcode for GL vertex_program */
1515 switch (curOpcode
->opcode
) {
1519 /* Address registers must be loaded with the ARL instruction */
1520 if ((((*pToken
) & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
) == D3DSPR_ADDR
) {
1521 if (((*pToken
) & 0x00001FFF) < nUseAddressRegister
) {
1522 strcpy(tmpLine
, "ARL");
1525 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This
, ((*pToken
) & 0x00001FFF));
1547 strcpy(tmpLine
, curOpcode
->glname
);
1554 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1555 nRemInstr
= ExpandMxMacro(curOpcode
->opcode
, pToken
);
1556 /* Save point to next instruction */
1557 pSavedToken
= pToken
+ 3;
1558 /* Execute expanded macro */
1559 pToken
= MacroExpansion
;
1561 /* dcl and def are handeled in the first pass */
1563 if (This
->namedArrays
) {
1564 const char* attribName
= "undefined";
1565 switch(*pToken
& 0xFFFF) {
1566 case D3DDECLUSAGE_POSITION
:
1567 attribName
= "vertex.position";
1569 case D3DDECLUSAGE_BLENDINDICES
:
1570 /* not supported by openGL */
1571 attribName
= "vertex.blend";
1573 case D3DDECLUSAGE_BLENDWEIGHT
:
1574 attribName
= "vertex.weight";
1576 case D3DDECLUSAGE_NORMAL
:
1577 attribName
= "vertex.normal";
1579 case D3DDECLUSAGE_PSIZE
:
1580 attribName
= "vertex.psize";
1582 case D3DDECLUSAGE_COLOR
:
1583 if((*pToken
& 0xF0000) >> 16 == 0) {
1584 attribName
= "vertex.color";
1586 attribName
= "vertex.color.secondary";
1589 case D3DDECLUSAGE_TEXCOORD
:
1593 sprintf(tmpChar
,"vertex.texcoord[%lu]",(*pToken
& 0xF0000) >> 16);
1594 attribName
= tmpChar
;
1597 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1598 case D3DDECLUSAGE_TANGENT
:
1599 attribName
= "vertex.tangent";
1601 case D3DDECLUSAGE_BINORMAL
:
1602 attribName
= "vertex.binormal";
1604 case D3DDECLUSAGE_TESSFACTOR
:
1605 attribName
= "vertex.tessfactor";
1607 case D3DDECLUSAGE_POSITIONT
:
1608 attribName
= "vertex.possitionT";
1610 case D3DDECLUSAGE_FOG
:
1611 attribName
= "vertex.fogcoord";
1613 case D3DDECLUSAGE_DEPTH
:
1614 attribName
= "vertex.depth";
1616 case D3DDECLUSAGE_SAMPLE
:
1617 attribName
= "vertex.sample";
1620 FIXME("Unrecognised dcl %08lx", *pToken
& 0xFFFF);
1625 sprintf(tmpLine
, "ATTRIB ");
1626 vshader_program_add_param(This
, *pToken
, FALSE
, tmpLine
);
1627 sprintf(tmpChar
," = %s", attribName
);
1628 strcat(tmpLine
, tmpChar
);
1629 strcat(tmpLine
,";\n");
1631 if (This
->namedArrays
) {
1632 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
);
1633 PNSTRCAT(pgmStr
, tmpLine
);
1636 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
);
1640 /* eat the token so it doesn't generate a warning */
1648 sprintf(tmpLine
, "PARAM const%lu = {", *pToken
& 0xFF);
1650 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1651 strcat(tmpLine
, tmpChar
);
1653 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1654 strcat(tmpLine
, tmpChar
);
1656 sprintf(tmpChar
,"%f ,", *(float *)pToken
);
1657 strcat(tmpLine
, tmpChar
);
1659 sprintf(tmpChar
,"%f}", *(float *)pToken
);
1660 strcat(tmpLine
, tmpChar
);
1662 strcat(tmpLine
,";\n");
1664 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1665 PNSTRCAT(pgmStr
, tmpLine
);
1671 if (curOpcode
->glname
== GLNAME_REQUIRE_GLSL
) {
1672 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode
->name
);
1674 FIXME("Can't handle opcode %s in hwShader\n", curOpcode
->name
);
1677 if (curOpcode
->num_params
> 0) {
1678 vshader_program_add_param(This
, *pToken
, FALSE
, tmpLine
);
1681 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
1682 strcat(tmpLine
, ",");
1683 vshader_program_add_param(This
, *pToken
, TRUE
, tmpLine
);
1687 strcat(tmpLine
,";\n");
1689 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1690 PNSTRCAT(pgmStr
, tmpLine
);
1694 strcpy(tmpLine
, "END\n");
1696 TRACE("GL HW (%u, %u) : %s", lineNum
, pgmLength
, tmpLine
); /* Don't add \n to this line as already in tmpLine */
1697 PNSTRCAT(pgmStr
, tmpLine
);
1700 /* finally null terminate the pgmStr*/
1701 pgmStr
[pgmLength
] = 0;
1703 /* Check that Vertex Shaders are supported */
1704 if (GL_SUPPORT(ARB_VERTEX_PROGRAM
)) {
1705 /* Create the hw shader */
1706 /* TODO: change to resource.glObjectHandel or something like that */
1707 GL_EXTCALL(glGenProgramsARB(1, &This
->prgId
));
1708 TRACE("Creating a hw vertex shader, prg=%d\n", This
->prgId
);
1709 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, This
->prgId
));
1711 /* Create the program and check for errors */
1712 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
, strlen(pgmStr
)/*pgmLength*/, pgmStr
));
1713 if (glGetError() == GL_INVALID_OPERATION
) {
1715 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &errPos
);
1716 FIXME("HW VertexShader Error at position %d: %s\n",
1717 errPos
, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB
)));
1721 #if 1 /* if were using the data buffer of device then we don't need to free it */
1722 HeapFree(GetProcessHeap(), 0, pgmStr
);
1727 BOOL
IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1729 * TODO: use the NV_vertex_program (or 1_1) extension
1730 * and specifics vendors (ARB_vertex_program??) variants for it
1735 HRESULT WINAPI
IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader
* iface
, WINEVSHADERINPUTDATA
* input
, WINEVSHADEROUTPUTDATA
* output
) {
1736 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1738 /** Vertex Shader Temporary Registers */
1739 WINED3DSHADERVECTOR R
[12];
1740 /*D3DSHADERSCALAR A0;*/
1741 WINED3DSHADERVECTOR A
[1];
1742 /** temporary Vector for modifier management */
1743 WINED3DSHADERVECTOR d
;
1744 WINED3DSHADERVECTOR s
[3];
1746 const DWORD
* pToken
= This
->function
;
1747 const SHADER_OPCODE
* curOpcode
= NULL
;
1748 /** functions parameters */
1749 WINED3DSHADERVECTOR
* p
[4];
1750 WINED3DSHADERVECTOR
* p_send
[4];
1753 /** init temporary register */
1754 memset(R
, 0, 12 * sizeof(WINED3DSHADERVECTOR
));
1756 /* vshader_program_parse(vshader); */
1757 #if 0 /* Must not be 1 in cvs */
1759 TRACE_VSVECTOR(This
->data
->C
[0]);
1760 TRACE_VSVECTOR(This
->data
->C
[1]);
1761 TRACE_VSVECTOR(This
->data
->C
[2]);
1762 TRACE_VSVECTOR(This
->data
->C
[3]);
1763 TRACE_VSVECTOR(This
->data
->C
[4]);
1764 TRACE_VSVECTOR(This
->data
->C
[5]);
1765 TRACE_VSVECTOR(This
->data
->C
[6]);
1766 TRACE_VSVECTOR(This
->data
->C
[7]);
1767 TRACE_VSVECTOR(This
->data
->C
[8]);
1768 TRACE_VSVECTOR(This
->data
->C
[64]);
1769 TRACE_VSVECTOR(input
->V
[D3DVSDE_POSITION
]);
1770 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDWEIGHT
]);
1771 TRACE_VSVECTOR(input
->V
[D3DVSDE_BLENDINDICES
]);
1772 TRACE_VSVECTOR(input
->V
[D3DVSDE_NORMAL
]);
1773 TRACE_VSVECTOR(input
->V
[D3DVSDE_PSIZE
]);
1774 TRACE_VSVECTOR(input
->V
[D3DVSDE_DIFFUSE
]);
1775 TRACE_VSVECTOR(input
->V
[D3DVSDE_SPECULAR
]);
1776 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD0
]);
1777 TRACE_VSVECTOR(input
->V
[D3DVSDE_TEXCOORD1
]);
1780 TRACE_VSVECTOR(vshader
->data
->C
[64]);
1781 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1783 /* the first dword is the version tag */
1784 /* TODO: parse it */
1786 if (vshader_is_version_token(*pToken
)) { /** version */
1789 while (D3DVS_END() != *pToken
) {
1790 if (vshader_is_comment_token(*pToken
)) { /** comment */
1791 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
1793 pToken
+= comment_len
;
1796 curOpcode
= vshader_program_get_opcode(*pToken
);
1798 if (NULL
== curOpcode
) {
1800 /* unknown current opcode ... */
1801 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1802 while (*pToken
& 0x80000000) {
1804 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken
- 1) - This
->function
, *(pToken
- 1));
1806 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken
- This
->function
, *pToken
);
1807 vshader_program_dump_param(*pToken
, i
);
1814 if (curOpcode
->num_params
> 0) {
1815 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1816 for (i
= 0; i
< curOpcode
->num_params
; ++i
) {
1817 DWORD reg
= pToken
[i
] & 0x00001FFF;
1818 DWORD regtype
= ((pToken
[i
] & D3DSP_REGTYPE_MASK
) >> D3DSP_REGTYPE_SHIFT
);
1820 switch (regtype
<< D3DSP_REGTYPE_SHIFT
) {
1822 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1826 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1827 p
[i
] = &input
->V
[reg
];
1830 if (pToken
[i
] & D3DVS_ADDRMODE_RELATIVE
) {
1831 p
[i
] = &This
->data
->C
[(DWORD
) A
[0].x
+ reg
];
1833 p
[i
] = &This
->data
->C
[reg
];
1836 case D3DSPR_ADDR
: /* case D3DSPR_TEXTURE: */
1838 ERR("cannot handle address registers != a0, forcing use of a0\n");
1841 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1844 case D3DSPR_RASTOUT
:
1846 case D3DSRO_POSITION
:
1847 p
[i
] = &output
->oPos
;
1850 p
[i
] = &output
->oFog
;
1852 case D3DSRO_POINT_SIZE
:
1853 p
[i
] = &output
->oPts
;
1857 case D3DSPR_ATTROUT
:
1858 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1859 p
[i
] = &output
->oD
[reg
];
1861 case D3DSPR_TEXCRDOUT
:
1862 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1863 p
[i
] = &output
->oT
[reg
];
1865 /* TODO Decls and defs */
1874 if (i
> 0) { /* input reg */
1875 DWORD swizzle
= (pToken
[i
] & D3DVS_SWIZZLE_MASK
) >> D3DVS_SWIZZLE_SHIFT
;
1876 UINT isNegative
= ((pToken
[i
] & D3DSP_SRCMOD_MASK
) == D3DSPSM_NEG
);
1878 if (!isNegative
&& (D3DVS_NOSWIZZLE
>> D3DVS_SWIZZLE_SHIFT
) == swizzle
) {
1879 /* TRACE("p[%d] not swizzled\n", i); */
1882 DWORD swizzle_x
= swizzle
& 0x03;
1883 DWORD swizzle_y
= (swizzle
>> 2) & 0x03;
1884 DWORD swizzle_z
= (swizzle
>> 4) & 0x03;
1885 DWORD swizzle_w
= (swizzle
>> 6) & 0x03;
1886 /* TRACE("p[%d] swizzled\n", i); */
1887 float* tt
= (float*) p
[i
];
1888 s
[i
].x
= (isNegative
) ? -tt
[swizzle_x
] : tt
[swizzle_x
];
1889 s
[i
].y
= (isNegative
) ? -tt
[swizzle_y
] : tt
[swizzle_y
];
1890 s
[i
].z
= (isNegative
) ? -tt
[swizzle_z
] : tt
[swizzle_z
];
1891 s
[i
].w
= (isNegative
) ? -tt
[swizzle_w
] : tt
[swizzle_w
];
1894 } else { /* output reg */
1895 if ((pToken
[i
] & D3DSP_WRITEMASK_ALL
) == D3DSP_WRITEMASK_ALL
) {
1898 p_send
[i
] = &d
; /* to be post-processed for modifiers management */
1904 switch (curOpcode
->num_params
) {
1906 curOpcode
->soft_fct();
1909 curOpcode
->soft_fct(p_send
[0]);
1912 curOpcode
->soft_fct(p_send
[0], p_send
[1]);
1915 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2]);
1918 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3]);
1921 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4]);
1924 curOpcode
->soft_fct(p_send
[0], p_send
[1], p_send
[2], p_send
[3], p_send
[4], p_send
[5]);
1927 ERR("%s too many params: %u\n", curOpcode
->name
, curOpcode
->num_params
);
1930 /* check if output reg modifier post-process */
1931 if (curOpcode
->num_params
> 0 && (pToken
[0] & D3DSP_WRITEMASK_ALL
) != D3DSP_WRITEMASK_ALL
) {
1932 if (pToken
[0] & D3DSP_WRITEMASK_0
) p
[0]->x
= d
.x
;
1933 if (pToken
[0] & D3DSP_WRITEMASK_1
) p
[0]->y
= d
.y
;
1934 if (pToken
[0] & D3DSP_WRITEMASK_2
) p
[0]->z
= d
.z
;
1935 if (pToken
[0] & D3DSP_WRITEMASK_3
) p
[0]->w
= d
.w
;
1938 TRACE_VSVECTOR(output
->oPos
);
1939 TRACE_VSVECTOR(output
->oD
[0]);
1940 TRACE_VSVECTOR(output
->oD
[1]);
1941 TRACE_VSVECTOR(output
->oT
[0]);
1942 TRACE_VSVECTOR(output
->oT
[1]);
1943 TRACE_VSVECTOR(R
[0]);
1944 TRACE_VSVECTOR(R
[1]);
1945 TRACE_VSVECTOR(R
[2]);
1946 TRACE_VSVECTOR(R
[3]);
1947 TRACE_VSVECTOR(R
[4]);
1948 TRACE_VSVECTOR(R
[5]);
1951 /* to next opcode token */
1952 pToken
+= curOpcode
->num_params
;
1955 TRACE("End of current instruction:\n");
1956 TRACE_VSVECTOR(output
->oPos
);
1957 TRACE_VSVECTOR(output
->oD
[0]);
1958 TRACE_VSVECTOR(output
->oD
[1]);
1959 TRACE_VSVECTOR(output
->oT
[0]);
1960 TRACE_VSVECTOR(output
->oT
[1]);
1961 TRACE_VSVECTOR(R
[0]);
1962 TRACE_VSVECTOR(R
[1]);
1963 TRACE_VSVECTOR(R
[2]);
1964 TRACE_VSVECTOR(R
[3]);
1965 TRACE_VSVECTOR(R
[4]);
1966 TRACE_VSVECTOR(R
[5]);
1969 #if 0 /* Must not be 1 in cvs */
1971 TRACE_VSVECTOR(output
->oPos
);
1972 TRACE_VSVECTOR(output
->oD
[0]);
1973 TRACE_VSVECTOR(output
->oD
[1]);
1974 TRACE_VSVECTOR(output
->oT
[0]);
1975 TRACE_VSVECTOR(output
->oT
[1]);
1980 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST FLOAT
*pConstantData
, UINT Vector4fCount
) {
1981 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1982 FIXME("(%p) : stub\n", This
);
1986 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader
*iface
, UINT StartRegister
, FLOAT
*pConstantData
, UINT Vector4fCount
) {
1987 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1988 FIXME("(%p) : stub\n", This
);
1992 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
) {
1993 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
1994 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
1995 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This
, StartRegister
);
1996 return D3DERR_INVALIDCALL
;
1998 if (NULL
== pConstantData
) {
1999 return D3DERR_INVALIDCALL
;
2001 FIXME("(%p) : stub\n", This
);
2005 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
) {
2006 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2007 TRACE("(%p) : C[%u] count=%u\n", This
, StartRegister
, Vector4iCount
);
2008 if (StartRegister
+ Vector4iCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
2009 return D3DERR_INVALIDCALL
;
2011 if (NULL
== pConstantData
) {
2012 return D3DERR_INVALIDCALL
;
2014 FIXME("(%p) : stub\n", This
);
2018 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
) {
2019 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2020 if (StartRegister
+ BoolCount
> WINED3D_VSHADER_MAX_CONSTANTS
) {
2021 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This
, StartRegister
);
2022 return D3DERR_INVALIDCALL
;
2024 if (NULL
== pConstantData
) {
2025 return D3DERR_INVALIDCALL
;
2027 FIXME("(%p) : stub\n", This
);
2031 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
) {
2032 IWineD3DVertexShaderImpl
* This
= (IWineD3DVertexShaderImpl
*)iface
;
2033 FIXME("(%p) : stub\n", This
);
2039 /* *******************************************
2040 IWineD3DVertexShader IUnknown parts follow
2041 ******************************************* */
2042 HRESULT WINAPI
IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader
*iface
, REFIID riid
, LPVOID
*ppobj
)
2044 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2045 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
2046 if (IsEqualGUID(riid
, &IID_IUnknown
)
2047 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
2048 || IsEqualGUID(riid
, &IID_IWineD3DVertexShader
)) {
2049 IUnknown_AddRef(iface
);
2053 return E_NOINTERFACE
;
2056 ULONG WINAPI
IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader
*iface
) {
2057 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2058 TRACE("(%p) : AddRef increasing from %ld\n", This
, This
->ref
);
2059 return InterlockedIncrement(&This
->ref
);
2062 ULONG WINAPI
IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader
*iface
) {
2063 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2065 TRACE("(%p) : Releasing from %ld\n", This
, This
->ref
);
2066 ref
= InterlockedDecrement(&This
->ref
);
2068 if (This
->vertexDeclaration
) IWineD3DVertexDeclaration_Release(This
->vertexDeclaration
);
2069 HeapFree(GetProcessHeap(), 0, This
);
2074 /* *******************************************
2075 IWineD3DVertexShader IWineD3DVertexShader parts follow
2076 ******************************************* */
2078 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader
*iface
, IUnknown
** parent
){
2079 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2081 *parent
= This
->parent
;
2082 IUnknown_AddRef(*parent
);
2083 TRACE("(%p) : returning %p\n", This
, *parent
);
2087 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader
* iface
, IWineD3DDevice
**pDevice
){
2088 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)iface
;
2089 IWineD3DDevice_AddRef((IWineD3DDevice
*)This
->wineD3DDevice
);
2090 *pDevice
= (IWineD3DDevice
*)This
->wineD3DDevice
;
2091 TRACE("(%p) returning %p\n", This
, *pDevice
);
2095 HRESULT WINAPI
IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader
* impl
, VOID
* pData
, UINT
* pSizeOfData
) {
2096 IWineD3DVertexShaderImpl
*This
= (IWineD3DVertexShaderImpl
*)impl
;
2097 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This
, pData
, pSizeOfData
);
2099 if (NULL
== pData
) {
2100 *pSizeOfData
= This
->functionLength
;
2103 if (*pSizeOfData
< This
->functionLength
) {
2104 *pSizeOfData
= This
->functionLength
;
2105 return D3DERR_MOREDATA
;
2107 if (NULL
== This
->function
) { /* no function defined */
2108 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This
, pData
);
2109 (*(DWORD
**) pData
) = NULL
;
2111 if(This
->functionLength
== 0){
2114 TRACE("(%p) : GetFunction copying to %p\n", This
, pData
);
2115 memcpy(pData
, This
->function
, This
->functionLength
);
2120 HRESULT WINAPI
IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
*iface
, CONST DWORD
*pFunction
) {
2121 IWineD3DVertexShaderImpl
*This
=(IWineD3DVertexShaderImpl
*)iface
;
2122 const DWORD
* pToken
= pFunction
;
2123 const SHADER_OPCODE
* curOpcode
= NULL
;
2126 TRACE("(%p) : Parsing programme\n", This
);
2128 if (NULL
!= pToken
) {
2129 while (D3DVS_END() != *pToken
) {
2130 if (vshader_is_version_token(*pToken
)) { /** version */
2131 TRACE("vs_%lu_%lu\n", (*pToken
>> 8) & 0x0F, (*pToken
& 0x0F));
2136 if (vshader_is_comment_token(*pToken
)) { /** comment */
2137 DWORD comment_len
= (*pToken
& D3DSI_COMMENTSIZE_MASK
) >> D3DSI_COMMENTSIZE_SHIFT
;
2139 TRACE("//%s\n", (char*)pToken
);
2140 pToken
+= comment_len
;
2141 len
+= comment_len
+ 1;
2144 curOpcode
= vshader_program_get_opcode(*pToken
);
2147 if (NULL
== curOpcode
) {
2148 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2149 while (*pToken
& 0x80000000) {
2150 /* unknown current opcode ... */
2151 FIXME("unrecognized opcode: %08lx", *pToken
);
2158 if (curOpcode
->opcode
== D3DSIO_DCL
) {
2159 vshader_program_dump_decl_usage(This
, *pToken
);
2162 vshader_program_dump_vs_param(*pToken
, 0);
2166 if (curOpcode
->opcode
== D3DSIO_DEF
) {
2167 TRACE("def c%lu = ", *pToken
& 0xFF);
2170 TRACE("%f ,", *(float *)pToken
);
2173 TRACE("%f ,", *(float *)pToken
);
2176 TRACE("%f ,", *(float *)pToken
);
2179 TRACE("%f", *(float *)pToken
);
2183 TRACE("%s ", curOpcode
->name
);
2184 if (curOpcode
->num_params
> 0) {
2185 vshader_program_dump_vs_param(*pToken
, 0);
2188 for (i
= 1; i
< curOpcode
->num_params
; ++i
) {
2190 vshader_program_dump_vs_param(*pToken
, 1);
2199 This
->functionLength
= (len
+ 1) * sizeof(DWORD
);
2201 This
->functionLength
= 1; /* no Function defined use fixed function vertex processing */
2204 /* Generate HW shader in needed */
2205 if (NULL
!= pFunction
&& wined3d_settings
.vs_mode
== VS_HW
) {
2207 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface
, pFunction
);
2211 /* copy the function ... because it will certainly be released by application */
2212 if (NULL
!= pFunction
) {
2213 This
->function
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->functionLength
);
2214 memcpy((void *)This
->function
, pFunction
, This
->functionLength
);
2216 This
->function
= NULL
;
2221 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl
=
2223 /*** IUnknown methods ***/
2224 IWineD3DVertexShaderImpl_QueryInterface
,
2225 IWineD3DVertexShaderImpl_AddRef
,
2226 IWineD3DVertexShaderImpl_Release
,
2227 /*** IWineD3DVertexShader methods ***/
2228 IWineD3DVertexShaderImpl_GetParent
,
2229 IWineD3DVertexShaderImpl_GetDevice
,
2230 IWineD3DVertexShaderImpl_GetFunction
,
2231 IWineD3DVertexShaderImpl_SetFunction