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", 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 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 FIXME("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 address 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 in use 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 FIXME("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;
1620 /* Check that Vertex Shaders are supported */
1621 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1622 /* Create the hw shader */
1623 /* TODO: change to resource.glObjectHandel or something like that */
1624 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1625 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1626 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1628 /* Create the program and check for errors */
1629 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1630 if (glGetError() == GL_INVALID_OPERATION) {
1632 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1633 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1637 #if 1 /* if were using the data buffer of device then we don't need to free it */
1638 HeapFree(GetProcessHeap(), 0, pgmStr);
1643 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1645 * TODO: use the NV_vertex_program (or 1_1) extension
1646 * and specifics vendors (ARB_vertex_program??) variants for it
1651 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1652 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1654 /** Vertex Shader Temporary Registers */
1655 WINED3DSHADERVECTOR R[12];
1656 /*D3DSHADERSCALAR A0;*/
1657 WINED3DSHADERVECTOR A[1];
1658 /** temporary Vector for modifier management */
1659 WINED3DSHADERVECTOR d;
1660 WINED3DSHADERVECTOR s[3];
1662 const DWORD* pToken = This->function;
1663 const SHADER_OPCODE* curOpcode = NULL;
1664 /** functions parameters */
1665 WINED3DSHADERVECTOR* p[4];
1666 WINED3DSHADERVECTOR* p_send[4];
1669 /** init temporary register */
1670 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1672 /* vshader_program_parse(vshader); */
1673 #if 0 /* Must not be 1 in cvs */
1675 TRACE_VSVECTOR(This->data->C[0]);
1676 TRACE_VSVECTOR(This->data->C[1]);
1677 TRACE_VSVECTOR(This->data->C[2]);
1678 TRACE_VSVECTOR(This->data->C[3]);
1679 TRACE_VSVECTOR(This->data->C[4]);
1680 TRACE_VSVECTOR(This->data->C[5]);
1681 TRACE_VSVECTOR(This->data->C[6]);
1682 TRACE_VSVECTOR(This->data->C[7]);
1683 TRACE_VSVECTOR(This->data->C[8]);
1684 TRACE_VSVECTOR(This->data->C[64]);
1685 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1686 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1687 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1688 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1689 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1690 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1691 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1692 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1693 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1696 TRACE_VSVECTOR(vshader->data->C[64]);
1697 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1699 /* the first dword is the version tag */
1700 /* TODO: parse it */
1702 if (vshader_is_version_token(*pToken)) { /** version */
1705 while (D3DVS_END() != *pToken) {
1706 if (vshader_is_comment_token(*pToken)) { /** comment */
1707 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1709 pToken += comment_len;
1712 curOpcode = vshader_program_get_opcode(*pToken);
1714 if (NULL == curOpcode) {
1716 /* unkown current opcode ... */
1717 /* TODO: Think of a name for 0x80000000 and repalce it's use with a constant */
1718 while (*pToken & 0x80000000) {
1720 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1722 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1723 vshader_program_dump_param(*pToken, i);
1730 if (curOpcode->num_params > 0) {
1731 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1732 for (i = 0; i < curOpcode->num_params; ++i) {
1733 DWORD reg = pToken[i] & 0x00001FFF;
1734 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1736 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1738 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1742 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1743 p[i] = &input->V[reg];
1746 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1747 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1749 p[i] = &This->data->C[reg];
1752 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1754 ERR("cannot handle address registers != a0, forcing use of a0\n");
1757 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1760 case D3DSPR_RASTOUT:
1762 case D3DSRO_POSITION:
1763 p[i] = &output->oPos;
1766 p[i] = &output->oFog;
1768 case D3DSRO_POINT_SIZE:
1769 p[i] = &output->oPts;
1773 case D3DSPR_ATTROUT:
1774 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1775 p[i] = &output->oD[reg];
1777 case D3DSPR_TEXCRDOUT:
1778 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1779 p[i] = &output->oT[reg];
1781 /* TODO Decls and defs */
1790 if (i > 0) { /* input reg */
1791 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1792 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1794 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1795 /* TRACE("p[%d] not swizzled\n", i); */
1798 DWORD swizzle_x = swizzle & 0x03;
1799 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1800 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1801 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1802 /* TRACE("p[%d] swizzled\n", i); */
1803 float* tt = (float*) p[i];
1804 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1805 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1806 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1807 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1810 } else { /* output reg */
1811 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1814 p_send[i] = &d; /* to be post-processed for modifiers management */
1820 switch (curOpcode->num_params) {
1822 curOpcode->soft_fct();
1825 curOpcode->soft_fct(p_send[0]);
1828 curOpcode->soft_fct(p_send[0], p_send[1]);
1831 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1834 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1837 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1840 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1843 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1846 /* check if output reg modifier post-process */
1847 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1848 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1849 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1850 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1851 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1854 TRACE_VSVECTOR(output->oPos);
1855 TRACE_VSVECTOR(output->oD[0]);
1856 TRACE_VSVECTOR(output->oD[1]);
1857 TRACE_VSVECTOR(output->oT[0]);
1858 TRACE_VSVECTOR(output->oT[1]);
1859 TRACE_VSVECTOR(R[0]);
1860 TRACE_VSVECTOR(R[1]);
1861 TRACE_VSVECTOR(R[2]);
1862 TRACE_VSVECTOR(R[3]);
1863 TRACE_VSVECTOR(R[4]);
1864 TRACE_VSVECTOR(R[5]);
1867 /* to next opcode token */
1868 pToken += curOpcode->num_params;
1871 TRACE("End of current instruction:\n");
1872 TRACE_VSVECTOR(output->oPos);
1873 TRACE_VSVECTOR(output->oD[0]);
1874 TRACE_VSVECTOR(output->oD[1]);
1875 TRACE_VSVECTOR(output->oT[0]);
1876 TRACE_VSVECTOR(output->oT[1]);
1877 TRACE_VSVECTOR(R[0]);
1878 TRACE_VSVECTOR(R[1]);
1879 TRACE_VSVECTOR(R[2]);
1880 TRACE_VSVECTOR(R[3]);
1881 TRACE_VSVECTOR(R[4]);
1882 TRACE_VSVECTOR(R[5]);
1885 #if 0 /* Must not be 1 in cvs */
1887 TRACE_VSVECTOR(output->oPos);
1888 TRACE_VSVECTOR(output->oD[0]);
1889 TRACE_VSVECTOR(output->oD[1]);
1890 TRACE_VSVECTOR(output->oT[0]);
1891 TRACE_VSVECTOR(output->oT[1]);
1896 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1897 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1898 FIXME("(%p) : stub\n", This);
1902 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1903 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1904 FIXME("(%p) : stub\n", This);
1908 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1909 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1910 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1911 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1912 return D3DERR_INVALIDCALL;
1914 if (NULL == pConstantData) {
1915 return D3DERR_INVALIDCALL;
1917 FIXME("(%p) : stub\n", This);
1921 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1922 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1923 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1924 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1925 return D3DERR_INVALIDCALL;
1927 if (NULL == pConstantData) {
1928 return D3DERR_INVALIDCALL;
1930 FIXME("(%p) : stub\n", This);
1934 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1935 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1936 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1937 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1938 return D3DERR_INVALIDCALL;
1940 if (NULL == pConstantData) {
1941 return D3DERR_INVALIDCALL;
1943 FIXME("(%p) : stub\n", This);
1947 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1948 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1949 FIXME("(%p) : stub\n", This);
1955 /* *******************************************
1956 IWineD3DVertexShader IUnknown parts follow
1957 ******************************************* */
1958 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1960 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1961 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1962 if (IsEqualGUID(riid, &IID_IUnknown)
1963 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1964 IUnknown_AddRef(iface);
1968 return E_NOINTERFACE;
1971 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1972 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1973 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1974 return InterlockedIncrement(&This->ref);
1977 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1978 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1980 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1981 ref = InterlockedDecrement(&This->ref);
1983 HeapFree(GetProcessHeap(), 0, This);
1988 /* *******************************************
1989 IWineD3DVertexShader IWineD3DVertexShader parts follow
1990 ******************************************* */
1992 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1993 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1995 *parent = (IUnknown*)This->parent;
1996 IUnknown_AddRef(*parent);
1997 TRACE("(%p) : returning %p\n", This, *parent);
2001 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2002 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2003 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2004 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2005 TRACE("(%p) returning %p\n", This, *pDevice);
2009 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2010 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2011 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2013 if (NULL == pData) {
2014 *pSizeOfData = This->functionLength;
2017 if (*pSizeOfData < This->functionLength) {
2018 *pSizeOfData = This->functionLength;
2019 return D3DERR_MOREDATA;
2021 if (NULL == This->function) { /* no function defined */
2022 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2023 (*(DWORD **) pData) = NULL;
2025 if(This->functionLength == 0){
2028 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2029 memcpy(pData, This->function, This->functionLength);
2034 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2035 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2036 const DWORD* pToken = pFunction;
2037 const SHADER_OPCODE* curOpcode = NULL;
2040 TRACE("(%p) : Parsing programme\n", This);
2042 if (NULL != pToken) {
2043 while (D3DVS_END() != *pToken) {
2044 if (vshader_is_version_token(*pToken)) { /** version */
2045 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2050 if (vshader_is_comment_token(*pToken)) { /** comment */
2051 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2053 TRACE("//%s\n", (char*)pToken);
2054 pToken += comment_len;
2055 len += comment_len + 1;
2058 curOpcode = vshader_program_get_opcode(*pToken);
2061 if (NULL == curOpcode) {
2062 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2063 while (*pToken & 0x80000000) {
2064 /* unkown current opcode ... */
2065 FIXME("unrecognized opcode: %08lx", *pToken);
2072 if (curOpcode->opcode == D3DSIO_DCL) {
2074 switch(*pToken & 0xFFFF) {
2075 case D3DDECLUSAGE_POSITION:
2076 TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2078 case D3DDECLUSAGE_BLENDINDICES:
2079 TRACE("%s ", "blend");
2081 case D3DDECLUSAGE_BLENDWEIGHT:
2082 TRACE("%s ", "weight");
2084 case D3DDECLUSAGE_NORMAL:
2085 TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2087 case D3DDECLUSAGE_PSIZE:
2088 TRACE("%s ", "psize");
2090 case D3DDECLUSAGE_COLOR:
2091 if((*pToken & 0xF0000) >> 16 == 0) {
2092 TRACE("%s ", "color");
2094 TRACE("%s ", "specular");
2097 case D3DDECLUSAGE_TEXCOORD:
2098 TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2100 case D3DDECLUSAGE_TANGENT:
2101 TRACE("%s ", "tangent");
2103 case D3DDECLUSAGE_BINORMAL:
2104 TRACE("%s ", "binormal");
2106 case D3DDECLUSAGE_TESSFACTOR:
2107 TRACE("%s ", "tessfactor");
2109 case D3DDECLUSAGE_POSITIONT:
2110 TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2112 case D3DDECLUSAGE_FOG:
2113 TRACE("%s ", "fog");
2115 case D3DDECLUSAGE_DEPTH:
2116 TRACE("%s ", "depth");
2118 case D3DDECLUSAGE_SAMPLE:
2119 TRACE("%s ", "sample");
2122 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2126 vshader_program_dump_vs_param(*pToken, 0);
2130 if (curOpcode->opcode == D3DSIO_DEF) {
2131 TRACE("def c%lu = ", *pToken & 0xFF);
2134 TRACE("%f ,", *(float *)pToken);
2137 TRACE("%f ,", *(float *)pToken);
2140 TRACE("%f ,", *(float *)pToken);
2143 TRACE("%f", *(float *)pToken);
2147 TRACE("%s ", curOpcode->name);
2148 if (curOpcode->num_params > 0) {
2149 vshader_program_dump_vs_param(*pToken, 0);
2152 for (i = 1; i < curOpcode->num_params; ++i) {
2154 vshader_program_dump_vs_param(*pToken, 1);
2163 This->functionLength = (len + 1) * sizeof(DWORD);
2165 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2168 /* Generate HW shader in needed */
2169 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2171 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2175 /* copy the function ... because it will certainly be released by application */
2176 if (NULL != pFunction) {
2177 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2178 memcpy((void *)This->function, pFunction, This->functionLength);
2180 This->function = NULL;
2185 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2187 /*** IUnknown methods ***/
2188 IWineD3DVertexShaderImpl_QueryInterface,
2189 IWineD3DVertexShaderImpl_AddRef,
2190 IWineD3DVertexShaderImpl_Release,
2191 /*** IWineD3DVertexShader methods ***/
2192 IWineD3DVertexShaderImpl_GetParent,
2193 IWineD3DVertexShaderImpl_GetDevice,
2194 IWineD3DVertexShaderImpl_GetFunction,
2195 IWineD3DVertexShaderImpl_SetFunction