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[4][4];
281 typedef FLOAT D3DMATRIX33[4][3];
282 typedef FLOAT D3DMATRIX32[4][2];
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, D3DMATRIX43 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, D3DMATRIX34 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[2][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[2][2] * s0->z;
329 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[2][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, D3DMATRIX32 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, WINED3DSHADERVECTOR* s3) {
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->x;
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", 5, 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 easly 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 is VS_ARB using one tempory 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 opperation */
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 BOOL vshader_is_version_token(DWORD token) {
883 return 0xFFFE0000 == (token & 0xFFFE0000);
886 inline static BOOL vshader_is_comment_token(DWORD token) {
887 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
890 inline static void vshader_program_add_param(const DWORD param, int input, char *hwLine, BOOL namedArrays, CHAR constantsUsedBitmap[]) {
891 /*static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" }; */
892 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
893 static const char swizzle_reg_chars[] = "xyzw";
895 DWORD reg = param & 0x00001FFF;
896 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
899 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
900 strcat(hwLine, " -");
907 sprintf(tmpReg, "T%lu", reg);
908 strcat(hwLine, tmpReg);
911 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
913 sprintf(tmpReg, "namedVertex%lu", reg);
915 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
916 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
918 strcat(hwLine, tmpReg);
921 /* FIXME: some constants are named so we need a constants map*/
922 if (constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
923 if (param & D3DVS_ADDRMODE_RELATIVE) {
924 FIXME("Relitive addressing not expected for a named constant %lu\n", reg);
926 sprintf(tmpReg, "const%lu", reg);
928 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
930 strcat(hwLine, tmpReg);
932 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
933 sprintf(tmpReg, "A%lu", reg);
934 strcat(hwLine, tmpReg);
937 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
938 strcat(hwLine, tmpReg);
942 strcat(hwLine, "result.color.primary");
944 strcat(hwLine, "result.color.secondary");
947 case D3DSPR_TEXCRDOUT:
948 sprintf(tmpReg, "result.texcoord[%lu]", reg);
949 strcat(hwLine, tmpReg);
952 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
957 /** operand output */
958 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
960 if (param & D3DSP_WRITEMASK_0) {
963 if (param & D3DSP_WRITEMASK_1) {
966 if (param & D3DSP_WRITEMASK_2) {
969 if (param & D3DSP_WRITEMASK_3) {
975 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
976 DWORD swizzle_x = swizzle & 0x03;
977 DWORD swizzle_y = (swizzle >> 2) & 0x03;
978 DWORD swizzle_z = (swizzle >> 4) & 0x03;
979 DWORD swizzle_w = (swizzle >> 6) & 0x03;
981 * swizzle bits fields:
984 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
985 if (swizzle_x == swizzle_y &&
986 swizzle_x == swizzle_z &&
987 swizzle_x == swizzle_w)
989 sprintf(tmpReg, ".%c", swizzle_reg_chars[swizzle_x]);
990 strcat(hwLine, tmpReg);
992 sprintf(tmpReg, ".%c%c%c%c",
993 swizzle_reg_chars[swizzle_x],
994 swizzle_reg_chars[swizzle_y],
995 swizzle_reg_chars[swizzle_z],
996 swizzle_reg_chars[swizzle_w]);
997 strcat(hwLine, tmpReg);
1003 DWORD MacroExpansion[4*4];
1005 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1007 int nComponents = 0;
1009 switch(macro_opcode) {
1012 opcode = D3DSIO_DP4;
1016 opcode = D3DSIO_DP4;
1020 opcode = D3DSIO_DP3;
1024 opcode = D3DSIO_DP3;
1028 opcode = D3DSIO_DP3;
1033 for (i = 0; i < nComponents; i++) {
1034 MacroExpansion[i*4+0] = opcode;
1035 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1036 MacroExpansion[i*4+2] = *(args+1);
1037 MacroExpansion[i*4+3] = (*(args+2))+i;
1043 * Function parser ...
1046 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1047 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1048 const DWORD* pToken = pFunction;
1049 const DWORD* pSavedToken = NULL;
1050 const SHADER_OPCODE* curOpcode = NULL;
1053 unsigned lineNum = 0;
1054 char *pgmStr = NULL;
1056 DWORD nUseAddressRegister = 0;
1057 DWORD nUseTempRegister = 0;
1061 #if 0 /* TODO: loope register (just another address register ) */
1062 BOOL hasLoops = FALSE;
1065 #define PGMSIZE 65535
1066 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1069 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1070 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occure... */
1071 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1072 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1073 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1074 This->fixupVertexBufferSize = PGMSIZE;
1075 This->fixupVertexBuffer[0] = 0;
1077 pgmStr = This->device->fixupVertexBuffer;
1079 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1080 int _tmpLineLen = strlen(_tmpLine); \
1081 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1082 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); \
1084 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1086 pgmLength += _tmpLineLen; \
1089 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1090 /* Initilise the shader */
1091 This->namedArrays = FALSE;
1092 This->declaredArrays = FALSE;
1093 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1094 This->arrayUsageMap[i] = -1;
1096 /* set all the tmpsUsed to not used */
1097 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1099 /* 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 */
1100 This->highestConstant = -1;
1104 * First pass to determine what we need to declare:
1105 * - Temporary variables
1106 * - Address variables
1108 if (NULL != pToken) {
1109 while (D3DVS_END() != *pToken) {
1110 if (vshader_is_version_token(*pToken)) {
1115 if (vshader_is_comment_token(*pToken)) { /** comment */
1116 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1118 pToken += comment_len;
1121 curOpcode = vshader_program_get_opcode(*pToken);
1126 if (NULL == curOpcode) {
1127 while (*pToken & 0x80000000) {
1128 TRACE("unrecognized opcode: %08lx\n", *pToken);
1129 /* skip unrecognized opcode */
1133 if (curOpcode->opcode == D3DSIO_DCL){
1134 INT usage = *pToken++;
1135 INT arrayNo = (*pToken++ & 0x00001FFF);
1136 switch(usage & 0xFFFF) {
1137 case D3DDECLUSAGE_POSITION:
1138 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1139 TRACE("Setting position to %d\n", arrayNo);
1140 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1141 This->namedArrays = TRUE;
1143 /* TODO: position indexes go fro 0-8!!*/
1144 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1145 /* robots uses positions upto 8, the position arrays are just packed.*/
1146 if ((usage & 0xF0000) >> 16 > 1) {
1147 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1149 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1150 This->declaredArrays = TRUE;
1153 case D3DDECLUSAGE_BLENDINDICES:
1154 /* not supported by openGL */
1155 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1156 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1157 This->declaredArrays = TRUE;
1158 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1160 case D3DDECLUSAGE_BLENDWEIGHT:
1161 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1162 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1163 This->namedArrays = TRUE;
1164 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1166 case D3DDECLUSAGE_NORMAL:
1167 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1168 TRACE("Setting normal to %d\n", arrayNo);
1169 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1170 This->namedArrays = TRUE;
1172 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1173 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1174 This->declaredArrays = TRUE;
1177 case D3DDECLUSAGE_PSIZE:
1178 TRACE("Setting PSIZE to %d\n", arrayNo);
1179 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1180 This->namedArrays = TRUE;
1181 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1183 case D3DDECLUSAGE_COLOR:
1184 if((usage & 0xF0000) >> 16 == 0) {
1185 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1186 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1187 This->namedArrays = TRUE;
1189 TRACE("Setting SPECULAR to %d\n", arrayNo);
1190 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1191 This->namedArrays = TRUE;
1194 case D3DDECLUSAGE_TEXCOORD:
1195 This->namedArrays = TRUE;
1196 /* only 7 texture coords have been designed for, so run a quick sanity check */
1197 if ((usage & 0xF0000) >> 16 > 7) {
1198 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1200 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1201 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1204 /* The following aren't supported by openGL,
1205 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1206 this should be caught in the first pass */
1207 case D3DDECLUSAGE_TANGENT:
1208 TRACE("Setting TANGENT to %d\n", arrayNo);
1209 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1210 This->declaredArrays = TRUE;
1212 case D3DDECLUSAGE_BINORMAL:
1213 TRACE("Setting BINORMAL to %d\n", arrayNo);
1214 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1215 This->declaredArrays = TRUE;
1217 case D3DDECLUSAGE_TESSFACTOR:
1218 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1219 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1220 This->declaredArrays = TRUE;
1222 case D3DDECLUSAGE_POSITIONT:
1223 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1224 FIXME("Setting positiont to %d\n", arrayNo);
1225 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1226 This->namedArrays = TRUE;
1228 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1229 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1230 This->declaredArrays = TRUE;
1231 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1234 case D3DDECLUSAGE_FOG:
1235 /* supported by OpenGL */
1236 TRACE("Setting FOG to %d\n", arrayNo);
1237 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1238 This->namedArrays = TRUE;
1240 case D3DDECLUSAGE_DEPTH:
1241 TRACE("Setting DEPTH to %d\n", arrayNo);
1242 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1243 This->declaredArrays = TRUE;
1245 case D3DDECLUSAGE_SAMPLE:
1246 TRACE("Setting SAMPLE to %d\n", arrayNo);
1247 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1248 This->declaredArrays = TRUE;
1251 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1253 } else if(curOpcode->opcode == D3DSIO_DEF) {
1254 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1255 FIXME("Constant %ld\n", *pToken & 0xFF);
1263 /* Check to see if and tmp or addressing redisters are used */
1264 if (curOpcode->num_params > 0) {
1265 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1266 reg = ((*pToken) & 0x00001FFF);
1267 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1268 if (D3DSPR_TEMP == regtype){
1269 tmpsUsed[reg] = TRUE;
1270 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1273 for (i = 1; i < curOpcode->num_params; ++i) {
1274 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1275 reg = ((*pToken) & 0x00001FFF);
1276 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1277 if (D3DSPR_TEMP == regtype){
1278 tmpsUsed[reg] = TRUE;
1279 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1285 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1286 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1287 FIXME("This shader requires gl shader language support\n");
1289 This->shaderLanguage = GLSHADER_GLSL;
1297 #define VSHADER_ALWAYS_NUMBERED
1300 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1301 /* TODO: using numbered arrays for software shaders makes things easier */
1302 This->declaredArrays = TRUE;
1305 /* named arrays and declared arrays are mutually exclusive */
1306 if (This->declaredArrays) {
1307 This->namedArrays = FALSE;
1310 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1311 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1314 /** second pass, now generate */
1317 if (NULL != pToken) {
1320 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1321 /* Macro is finished, continue normal path */
1322 pToken = pSavedToken;
1323 if (D3DVS_END() == *pToken)
1326 if (vshader_is_version_token(*pToken)) { /** version */
1327 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1328 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1332 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1334 /* Each release of vertex shaders has had different numbers of temp registers */
1337 case 11: numTemps=12;
1338 numConstants=96;/* min(GL_LIMITS(constants),96) */
1339 strcpy(tmpLine, "!!ARBvp1.0\n");
1340 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1342 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1343 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1344 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)*/
1345 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1346 numConstants=96; /* min(GL_LIMITS(constants),256) */
1347 strcpy(tmpLine, "!!ARBvp1.0\n");
1348 FIXME("No work done yet to support vs2.0 in hw\n");
1349 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1351 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1352 numConstants=96; /* min(GL_LIMITS(constants),256) */
1353 strcpy(tmpLine, "!!ARBvp1.0\n");
1354 FIXME("No work done yet to support vs2.1 in hw\n");
1355 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1357 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1358 numConstants=96;/* min(GL_LIMITS(constants),256) */
1359 strcpy(tmpLine, "!!ARBvp3.0\n");
1360 FIXME("No work done yet to support vs3.0 in hw\n");
1361 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1364 numTemps=12;/* min(GL_LIMITS(temps),12) */
1365 numConstants=96;/* min(GL_LIMITS(constants),96) */
1366 strcpy(tmpLine, "!!ARBvp1.0\n");
1367 FIXME("Unrecognized vertex shader version %d!\n", version);
1369 PNSTRCAT(pgmStr, tmpLine);
1373 /* This should be a bitmap so that only temp registers that are used are declared. */
1374 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1375 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1376 sprintf(tmpLine, "TEMP T%ld;\n", i);
1378 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1379 PNSTRCAT(pgmStr, tmpLine);
1383 /* TODO: loop register counts as an addres register */
1384 for (i = 0; i < nUseAddressRegister; i++) {
1385 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1387 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1388 PNSTRCAT(pgmStr, tmpLine);
1391 /* Due to the dynamic constants binding mechanism, we need to declare
1392 * all the constants for relative addressing. */
1393 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1394 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1397 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1398 Looking at some of the shaders inuse by applications we'd need to create a list of all used env variables
1400 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1401 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1402 PNSTRCAT(pgmStr, tmpLine);
1409 if (vshader_is_comment_token(*pToken)) { /** comment */
1410 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1412 FIXME("#%s\n", (char*)pToken);
1413 pToken += comment_len;
1417 curOpcode = vshader_program_get_opcode(*pToken);
1419 if (NULL == curOpcode) {
1420 /* unkown current opcode ... (shouldn't be any!) */
1421 while (*pToken & 0x80000000) {
1422 TRACE("unrecognized opcode: %08lx\n", *pToken);
1425 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1426 /* if the token isn't supported by this cross compiler then skip it and it's parameters */
1428 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1429 pToken += curOpcode->num_params;
1431 /* Build opcode for GL vertex_program */
1432 switch (curOpcode->opcode) {
1436 /* Address registers must be loaded with the ARL instruction */
1437 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1438 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1439 strcpy(tmpLine, "ARL");
1442 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1464 strcpy(tmpLine, curOpcode->glname);
1471 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1472 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1473 /* Save point to next instruction */
1474 pSavedToken = pToken + 3;
1475 /* Execute expanded macro */
1476 pToken = MacroExpansion;
1478 /* dcl and def are handeled in the first pass */
1480 if (This->namedArrays) {
1481 const char* attribName = "undefined";
1482 switch(*pToken & 0xFFFF) {
1483 case D3DDECLUSAGE_POSITION:
1484 attribName = "vertex.position";
1486 case D3DDECLUSAGE_BLENDINDICES:
1487 /* not supported by openGL */
1488 attribName = "vertex.blend";
1490 case D3DDECLUSAGE_BLENDWEIGHT:
1491 attribName = "vertex.weight";
1493 case D3DDECLUSAGE_NORMAL:
1494 attribName = "vertex.normal";
1496 case D3DDECLUSAGE_PSIZE:
1497 attribName = "vertex.psize";
1499 case D3DDECLUSAGE_COLOR:
1500 if((*pToken & 0xF0000) >> 16 == 0) {
1501 attribName = "vertex.color";
1503 attribName = "vertex.color.secondary";
1506 case D3DDECLUSAGE_TEXCOORD:
1510 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1511 attribName = tmpChar;
1514 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1515 case D3DDECLUSAGE_TANGENT:
1516 attribName = "vertex.tangent";
1518 case D3DDECLUSAGE_BINORMAL:
1519 attribName = "vertex.binormal";
1521 case D3DDECLUSAGE_TESSFACTOR:
1522 attribName = "vertex.tessfactor";
1524 case D3DDECLUSAGE_POSITIONT:
1525 attribName = "vertex.possitionT";
1527 case D3DDECLUSAGE_FOG:
1528 attribName = "vertex.fogcoord";
1530 case D3DDECLUSAGE_DEPTH:
1531 attribName = "vertex.depth";
1533 case D3DDECLUSAGE_SAMPLE:
1534 attribName = "vertex.sample";
1537 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1542 sprintf(tmpLine, "ATTRIB ");
1543 vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1544 sprintf(tmpChar," = %s", attribName);
1545 strcat(tmpLine, tmpChar);
1546 strcat(tmpLine,";\n");
1548 if (This->namedArrays) {
1549 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1550 PNSTRCAT(pgmStr, tmpLine);
1553 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1557 /* eat the token so it doesn't generate a warning */
1565 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1567 sprintf(tmpChar,"%f ,", *(float *)pToken);
1568 strcat(tmpLine, tmpChar);
1570 sprintf(tmpChar,"%f ,", *(float *)pToken);
1571 strcat(tmpLine, tmpChar);
1573 sprintf(tmpChar,"%f ,", *(float *)pToken);
1574 strcat(tmpLine, tmpChar);
1576 sprintf(tmpChar,"%f}", *(float *)pToken);
1577 strcat(tmpLine, tmpChar);
1579 strcat(tmpLine,";\n");
1581 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1582 PNSTRCAT(pgmStr, tmpLine);
1588 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1589 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1591 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1594 if (curOpcode->num_params > 0) {
1595 vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1598 for (i = 1; i < curOpcode->num_params; ++i) {
1599 strcat(tmpLine, ",");
1600 vshader_program_add_param(*pToken, 1, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1604 strcat(tmpLine,";\n");
1606 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1607 PNSTRCAT(pgmStr, tmpLine);
1611 strcpy(tmpLine, "END\n");
1613 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1614 PNSTRCAT(pgmStr, tmpLine);
1617 /* finally null terminate the pgmStr*/
1618 pgmStr[pgmLength] = 0;
1619 /* Create the hw shader */
1620 /* TODO: change to resource.glObjectHandel or something like that */
1621 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1622 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1624 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1627 /* Create the program and check for errors */
1628 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1629 if (glGetError() == GL_INVALID_OPERATION) {
1631 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1632 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1635 #if 1 /* if were using the data buffer of device then we don't need to free it */
1636 HeapFree(GetProcessHeap(), 0, pgmStr);
1641 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1643 * TODO: use the NV_vertex_program (or 1_1) extension
1644 * and specifics vendors (ARB_vertex_program??) variants for it
1649 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1650 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1652 /** Vertex Shader Temporary Registers */
1653 WINED3DSHADERVECTOR R[12];
1654 /*D3DSHADERSCALAR A0;*/
1655 WINED3DSHADERVECTOR A[1];
1656 /** temporary Vector for modifier management */
1657 WINED3DSHADERVECTOR d;
1658 WINED3DSHADERVECTOR s[3];
1660 const DWORD* pToken = This->function;
1661 const SHADER_OPCODE* curOpcode = NULL;
1662 /** functions parameters */
1663 WINED3DSHADERVECTOR* p[4];
1664 WINED3DSHADERVECTOR* p_send[4];
1667 /** init temporary register */
1668 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1670 /* vshader_program_parse(vshader); */
1671 #if 0 /* Must not be 1 in cvs */
1673 TRACE_VSVECTOR(This->data->C[0]);
1674 TRACE_VSVECTOR(This->data->C[1]);
1675 TRACE_VSVECTOR(This->data->C[2]);
1676 TRACE_VSVECTOR(This->data->C[3]);
1677 TRACE_VSVECTOR(This->data->C[4]);
1678 TRACE_VSVECTOR(This->data->C[5]);
1679 TRACE_VSVECTOR(This->data->C[6]);
1680 TRACE_VSVECTOR(This->data->C[7]);
1681 TRACE_VSVECTOR(This->data->C[8]);
1682 TRACE_VSVECTOR(This->data->C[64]);
1683 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1684 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1685 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1686 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1687 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1688 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1689 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1690 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1691 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1694 TRACE_VSVECTOR(vshader->data->C[64]);
1695 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1697 /* the first dword is the version tag */
1698 /* TODO: parse it */
1700 if (vshader_is_version_token(*pToken)) { /** version */
1703 while (D3DVS_END() != *pToken) {
1704 if (vshader_is_comment_token(*pToken)) { /** comment */
1705 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1707 pToken += comment_len;
1710 curOpcode = vshader_program_get_opcode(*pToken);
1712 if (NULL == curOpcode) {
1714 /* unkown current opcode ... */
1715 /* TODO: Think of a name for 0x80000000 and repalce it's use with a constant */
1716 while (*pToken & 0x80000000) {
1718 TRACE("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1720 TRACE("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1721 vshader_program_dump_param(*pToken, i);
1728 if (curOpcode->num_params > 0) {
1729 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1730 for (i = 0; i < curOpcode->num_params; ++i) {
1731 DWORD reg = pToken[i] & 0x00001FFF;
1732 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1734 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1736 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1740 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1741 p[i] = &input->V[reg];
1744 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1745 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1747 p[i] = &This->data->C[reg];
1750 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1752 ERR("cannot handle address registers != a0, forcing use of a0\n");
1755 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1758 case D3DSPR_RASTOUT:
1760 case D3DSRO_POSITION:
1761 p[i] = &output->oPos;
1764 p[i] = &output->oFog;
1766 case D3DSRO_POINT_SIZE:
1767 p[i] = &output->oPts;
1771 case D3DSPR_ATTROUT:
1772 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1773 p[i] = &output->oD[reg];
1775 case D3DSPR_TEXCRDOUT:
1776 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1777 p[i] = &output->oT[reg];
1779 /* TODO Decls and defs */
1788 if (i > 0) { /* input reg */
1789 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1790 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1792 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1793 /* TRACE("p[%d] not swizzled\n", i); */
1796 DWORD swizzle_x = swizzle & 0x03;
1797 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1798 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1799 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1800 /* TRACE("p[%d] swizzled\n", i); */
1801 float* tt = (float*) p[i];
1802 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1803 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1804 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1805 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1808 } else { /* output reg */
1809 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1812 p_send[i] = &d; /* to be post-processed for modifiers management */
1818 switch (curOpcode->num_params) {
1820 curOpcode->soft_fct();
1823 curOpcode->soft_fct(p_send[0]);
1826 curOpcode->soft_fct(p_send[0], p_send[1]);
1829 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1832 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1835 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1838 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1841 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1844 /* check if output reg modifier post-process */
1845 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1846 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1847 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1848 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1849 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1852 TRACE_VSVECTOR(output->oPos);
1853 TRACE_VSVECTOR(output->oD[0]);
1854 TRACE_VSVECTOR(output->oD[1]);
1855 TRACE_VSVECTOR(output->oT[0]);
1856 TRACE_VSVECTOR(output->oT[1]);
1857 TRACE_VSVECTOR(R[0]);
1858 TRACE_VSVECTOR(R[1]);
1859 TRACE_VSVECTOR(R[2]);
1860 TRACE_VSVECTOR(R[3]);
1861 TRACE_VSVECTOR(R[4]);
1862 TRACE_VSVECTOR(R[5]);
1865 /* to next opcode token */
1866 pToken += curOpcode->num_params;
1869 TRACE("End of current instruction:\n");
1870 TRACE_VSVECTOR(output->oPos);
1871 TRACE_VSVECTOR(output->oD[0]);
1872 TRACE_VSVECTOR(output->oD[1]);
1873 TRACE_VSVECTOR(output->oT[0]);
1874 TRACE_VSVECTOR(output->oT[1]);
1875 TRACE_VSVECTOR(R[0]);
1876 TRACE_VSVECTOR(R[1]);
1877 TRACE_VSVECTOR(R[2]);
1878 TRACE_VSVECTOR(R[3]);
1879 TRACE_VSVECTOR(R[4]);
1880 TRACE_VSVECTOR(R[5]);
1883 #if 0 /* Must not be 1 in cvs */
1885 TRACE_VSVECTOR(output->oPos);
1886 TRACE_VSVECTOR(output->oD[0]);
1887 TRACE_VSVECTOR(output->oD[1]);
1888 TRACE_VSVECTOR(output->oT[0]);
1889 TRACE_VSVECTOR(output->oT[1]);
1894 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1895 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1896 FIXME("(%p) : stub\n", This);
1900 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1901 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1902 FIXME("(%p) : stub\n", This);
1906 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1907 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1908 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1909 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1910 return D3DERR_INVALIDCALL;
1912 if (NULL == pConstantData) {
1913 return D3DERR_INVALIDCALL;
1915 FIXME("(%p) : stub\n", This);
1919 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1920 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1921 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1922 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1923 return D3DERR_INVALIDCALL;
1925 if (NULL == pConstantData) {
1926 return D3DERR_INVALIDCALL;
1928 FIXME("(%p) : stub\n", This);
1932 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1933 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1934 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1935 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1936 return D3DERR_INVALIDCALL;
1938 if (NULL == pConstantData) {
1939 return D3DERR_INVALIDCALL;
1941 FIXME("(%p) : stub\n", This);
1945 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1946 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1947 FIXME("(%p) : stub\n", This);
1953 /* *******************************************
1954 IWineD3DVertexShader IUnknown parts follow
1955 ******************************************* */
1956 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1958 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1959 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1960 if (IsEqualGUID(riid, &IID_IUnknown)
1961 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1962 IUnknown_AddRef(iface);
1966 return E_NOINTERFACE;
1969 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1970 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1971 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1972 return InterlockedIncrement(&This->ref);
1975 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1976 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1978 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1979 ref = InterlockedDecrement(&This->ref);
1981 HeapFree(GetProcessHeap(), 0, This);
1986 /* *******************************************
1987 IWineD3DVertexShader IWineD3DVertexShader parts follow
1988 ******************************************* */
1990 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1991 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1993 *parent = (IUnknown*)This->parent;
1994 IUnknown_AddRef(*parent);
1995 TRACE("(%p) : returning %p\n", This, *parent);
1999 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2000 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2001 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2002 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2003 TRACE("(%p) returning %p\n", This, *pDevice);
2007 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2008 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2009 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2011 if (NULL == pData) {
2012 *pSizeOfData = This->functionLength;
2015 if (*pSizeOfData < This->functionLength) {
2016 *pSizeOfData = This->functionLength;
2017 return D3DERR_MOREDATA;
2019 if (NULL == This->function) { /* no function defined */
2020 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2021 (*(DWORD **) pData) = NULL;
2023 if(This->functionLength == 0){
2026 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2027 memcpy(pData, This->function, This->functionLength);
2032 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2033 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2034 const DWORD* pToken = pFunction;
2035 const SHADER_OPCODE* curOpcode = NULL;
2038 TRACE("(%p) : Parsing programme\n", This);
2040 if (NULL != pToken) {
2041 while (D3DVS_END() != *pToken) {
2042 if (vshader_is_version_token(*pToken)) { /** version */
2043 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2048 if (vshader_is_comment_token(*pToken)) { /** comment */
2049 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2051 TRACE("//%s\n", (char*)pToken);
2052 pToken += comment_len;
2053 len += comment_len + 1;
2056 curOpcode = vshader_program_get_opcode(*pToken);
2059 if (NULL == curOpcode) {
2060 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2061 while (*pToken & 0x80000000) {
2062 /* unkown current opcode ... */
2063 TRACE("unrecognized opcode: %08lx", *pToken);
2070 if (curOpcode->opcode == D3DSIO_DCL) {
2072 switch(*pToken & 0xFFFF) {
2073 case D3DDECLUSAGE_POSITION:
2074 TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2076 case D3DDECLUSAGE_BLENDINDICES:
2077 TRACE("%s ", "blend");
2079 case D3DDECLUSAGE_BLENDWEIGHT:
2080 TRACE("%s ", "weight");
2082 case D3DDECLUSAGE_NORMAL:
2083 TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2085 case D3DDECLUSAGE_PSIZE:
2086 TRACE("%s ", "psize");
2088 case D3DDECLUSAGE_COLOR:
2089 if((*pToken & 0xF0000) >> 16 == 0) {
2090 TRACE("%s ", "color");
2092 TRACE("%s ", "specular");
2095 case D3DDECLUSAGE_TEXCOORD:
2096 TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2098 case D3DDECLUSAGE_TANGENT:
2099 TRACE("%s ", "tangent");
2101 case D3DDECLUSAGE_BINORMAL:
2102 TRACE("%s ", "binormal");
2104 case D3DDECLUSAGE_TESSFACTOR:
2105 TRACE("%s ", "tessfactor");
2107 case D3DDECLUSAGE_POSITIONT:
2108 TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2110 case D3DDECLUSAGE_FOG:
2111 TRACE("%s ", "fog");
2113 case D3DDECLUSAGE_DEPTH:
2114 TRACE("%s ", "depth");
2116 case D3DDECLUSAGE_SAMPLE:
2117 TRACE("%s ", "sample");
2120 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2124 vshader_program_dump_vs_param(*pToken, 0);
2128 if (curOpcode->opcode == D3DSIO_DEF) {
2129 TRACE("def c%lu = ", *pToken & 0xFF);
2132 TRACE("%f ,", *(float *)pToken);
2135 TRACE("%f ,", *(float *)pToken);
2138 TRACE("%f ,", *(float *)pToken);
2141 TRACE("%f", *(float *)pToken);
2145 TRACE("%s ", curOpcode->name);
2146 if (curOpcode->num_params > 0) {
2147 vshader_program_dump_vs_param(*pToken, 0);
2150 for (i = 1; i < curOpcode->num_params; ++i) {
2152 vshader_program_dump_vs_param(*pToken, 1);
2161 This->functionLength = (len + 1) * sizeof(DWORD);
2163 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2166 /* Generate HW shader in needed */
2167 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2169 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2173 /* copy the function ... because it will certainly be released by application */
2174 if (NULL != pFunction) {
2175 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2176 memcpy((void *)This->function, pFunction, This->functionLength);
2178 This->function = NULL;
2183 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2185 /*** IUnknown methods ***/
2186 IWineD3DVertexShaderImpl_QueryInterface,
2187 IWineD3DVertexShaderImpl_AddRef,
2188 IWineD3DVertexShaderImpl_Release,
2189 /*** IWineD3DVertexShader methods ***/
2190 IWineD3DVertexShaderImpl_GetParent,
2191 IWineD3DVertexShaderImpl_GetDevice,
2192 IWineD3DVertexShaderImpl_GetFunction,
2193 IWineD3DVertexShaderImpl_SetFunction