2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
34 /* Shader debugging - Change the following line to enable debugging of software
36 #if 0 /* Musxt not be 1 in cvs version */
37 # define VSTRACE(A) TRACE A
38 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
41 # define TRACE_VSVECTOR(name)
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
51 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
53 * Using Vertex Shaders
54 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
60 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
69 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
71 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
72 * http://developer.nvidia.com/view.asp?IO=vstovp
74 * NVIDIA: Memory Management with VAR
75 * http://developer.nvidia.com/view.asp?IO=var_memory_management
78 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
79 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
81 typedef void (*shader_fct_t)();
83 typedef struct SHADER_OPCODE {
87 CONST UINT num_params;
88 shader_fct_t soft_fct;
93 #define GLNAME_REQUIRE_GLSL ((const char *)1)
95 /*******************************
96 * vshader functions software VM
99 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
100 d->x = s0->x + s1->x;
101 d->y = s0->y + s1->y;
102 d->z = s0->z + s1->z;
103 d->w = s0->w + s1->w;
104 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
105 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
108 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
109 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
110 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
111 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
114 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
115 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
116 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
117 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
120 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
122 d->y = s0->y * s1->y;
125 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
126 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
129 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
135 tmp.f = floorf(s0->w);
136 d->x = powf(2.0f, tmp.f);
137 d->y = s0->w - tmp.f;
138 tmp.f = powf(2.0f, s0->w);
139 tmp.d &= 0xFFFFFF00U;
142 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
143 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
146 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
148 d->y = (0.0f < s0->x) ? s0->x : 0.0f;
149 d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
151 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
152 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
155 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
156 float tmp_f = fabsf(s0->w);
157 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
158 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
159 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
162 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
163 d->x = s0->x * s1->x + s2->x;
164 d->y = s0->y * s1->y + s2->y;
165 d->z = s0->z * s1->z + s2->z;
166 d->w = s0->w * s1->w + s2->w;
167 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
168 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, s2->x, s2->y, s2->z, s2->w, d->x, d->y, d->z, d->w));
171 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
172 d->x = (s0->x >= s1->x) ? s0->x : s1->x;
173 d->y = (s0->y >= s1->y) ? s0->y : s1->y;
174 d->z = (s0->z >= s1->z) ? s0->z : s1->z;
175 d->w = (s0->w >= s1->w) ? s0->w : s1->w;
176 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
177 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
180 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
181 d->x = (s0->x < s1->x) ? s0->x : s1->x;
182 d->y = (s0->y < s1->y) ? s0->y : s1->y;
183 d->z = (s0->z < s1->z) ? s0->z : s1->z;
184 d->w = (s0->w < s1->w) ? s0->w : s1->w;
185 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
186 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
189 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
194 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
195 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
198 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
199 d->x = s0->x * s1->x;
200 d->y = s0->y * s1->y;
201 d->z = s0->z * s1->z;
202 d->w = s0->w * s1->w;
203 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
207 void vshader_nop(void) {
208 /* NOPPPP ahhh too easy ;) */
209 VSTRACE(("executing nop\n"));
212 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
213 d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
214 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
215 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
218 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
219 float tmp_f = fabsf(s0->w);
220 d->x = d->y = d->z = d->w = (0.0f == tmp_f) ? HUGE_VAL : ((1.0f != tmp_f) ? 1.0f / sqrtf(tmp_f) : 1.0f);
221 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
222 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
225 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
226 d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
227 d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
228 d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
229 d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
230 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
231 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
234 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
235 d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
236 d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
237 d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
238 d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
239 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
240 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
243 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
244 d->x = s0->x - s1->x;
245 d->y = s0->y - s1->y;
246 d->z = s0->z - s1->z;
247 d->w = s0->w - s1->w;
248 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
249 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
253 * Version 1.1 specific
256 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
257 d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
258 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
259 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
262 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
263 float tmp_f = fabsf(s0->w);
264 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
265 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
266 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
269 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
270 d->x = s0->x - floorf(s0->x);
271 d->y = s0->y - floorf(s0->y);
274 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
275 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
278 typedef FLOAT D3DMATRIX44[4][4];
279 typedef FLOAT D3DMATRIX43[4][3];
280 typedef FLOAT D3DMATRIX34[3][4];
281 typedef FLOAT D3DMATRIX33[3][3];
282 typedef FLOAT D3DMATRIX23[2][3];
284 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
286 * Buggy CODE: here only if cast not work for copy/paste
287 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
288 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
289 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
290 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
291 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
292 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
293 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
295 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
298 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
299 VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
300 VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
301 VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
302 VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
305 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
306 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
307 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
308 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
310 VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
311 VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
312 VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
313 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
316 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
320 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
321 VSTRACE(("executing m3x4(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
322 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
324 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
327 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
328 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
329 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
330 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
332 VSTRACE(("executing m3x3(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
333 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
334 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
335 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
338 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
340 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
341 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
347 * Version 2.0 specific
349 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
350 d->x = s0->x * (s1->x - s2->x) + s2->x;
351 d->y = s0->y * (s1->y - s2->y) + s2->y;
352 d->z = s0->z * (s1->z - s2->z) + s2->z;
353 d->w = s0->w * (s1->w - s2->w) + s2->w;
356 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
357 d->x = s0->y * s1->z - s0->z * s1->y;
358 d->y = s0->z * s1->x - s0->x * s1->z;
359 d->z = s0->x * s1->y - s0->y * s1->x;
360 d->w = 0.9f; /* w is undefined, so set it to something safeish */
362 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
363 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
366 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
372 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
373 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
377 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
381 void vshader_texkill(WINED3DSHADERVECTOR* d) {
385 void vshader_tex(WINED3DSHADERVECTOR* d) {
388 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
392 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
396 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
400 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
412 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
416 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
420 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
428 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
432 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
436 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
440 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
441 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
445 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
453 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
457 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
461 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
465 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
469 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
473 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
477 void vshader_call(WINED3DSHADERVECTOR* d) {
481 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
485 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
489 void vshader_ret(WINED3DSHADERVECTOR* d) {
493 void vshader_endloop(WINED3DSHADERVECTOR* d) {
497 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
501 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
505 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
509 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
513 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
517 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
521 void vshader_endrep(void) {
525 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
529 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
533 void vshader_else(WINED3DSHADERVECTOR* d) {
537 void vshader_label(WINED3DSHADERVECTOR* d) {
541 void vshader_endif(WINED3DSHADERVECTOR* d) {
545 void vshader_break(WINED3DSHADERVECTOR* d) {
549 void vshader_breakc(WINED3DSHADERVECTOR* d) {
553 void vshader_mova(WINED3DSHADERVECTOR* d) {
557 void vshader_defb(WINED3DSHADERVECTOR* d) {
561 void vshader_defi(WINED3DSHADERVECTOR* d) {
565 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
569 void vshader_dsx(WINED3DSHADERVECTOR* d) {
573 void vshader_dsy(WINED3DSHADERVECTOR* d) {
577 void vshader_texldd(WINED3DSHADERVECTOR* d) {
581 void vshader_setp(WINED3DSHADERVECTOR* d) {
585 void vshader_texldl(WINED3DSHADERVECTOR* d) {
589 void vshader_breakp(WINED3DSHADERVECTOR* d) {
595 * log, exp, frc, m*x* seems to be macros ins ... to see
597 static CONST SHADER_OPCODE vshader_ins [] = {
598 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, 0, 0},
599 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, 0, 0},
600 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, 0, 0},
601 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, 0, 0},
602 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, 0, 0},
603 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, 0, 0},
604 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, 0, 0},
605 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, 0, 0},
606 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, 0, 0},
607 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, 0, 0},
608 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, 0, 0},
609 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, 0, 0},
610 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, 0, 0},
611 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, 0, 0},
612 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, 0, 0},
613 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, 0, 0},
614 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, 0, 0},
615 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, 0, 0},
616 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, 0, 0},
617 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, 0, 0},
618 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, 0, 0},
619 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
620 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
621 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
622 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
623 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
624 /** FIXME: use direct access so add the others opcodes as stubs */
625 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
626 They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
627 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, 0, 0},
628 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, 0, 0},
629 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, 0, 0},
630 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, 0, 0},
631 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, 0, 0},
632 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, 0, 0},
633 /* DCL is a specil operation */
634 {D3DSIO_DCL, "dcl", NULL, 1, vshader_dcl, 0, 0},
635 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, 0, 0},
636 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, 0, 0},
637 /* TODO: sng can possibly be performed as
640 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, 0, 0},
641 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
644 MUL vec.xyz, vec, tmp;
645 but I think this is better because it accounts for w properly.
651 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, 0, 0},
652 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, 0, 0},
653 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 2, vshader_rep, 0, 0},
654 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, 0, 0},
655 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 2, vshader_if, 0, 0},
656 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, 0, 0},
657 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 2, vshader_else, 0, 0},
658 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 2, vshader_endif, 0, 0},
659 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 2, vshader_break, 0, 0},
660 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, 0, 0},
661 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, 0, 0},
662 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, 0, 0},
663 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, 0, 0},
665 {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL, 1, vshader_texcoord, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXCOORD, "texcrd", GLNAME_REQUIRE_GLSL, 2, vshader_texcoord, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
667 {D3DSIO_TEXKILL, "texkill", GLNAME_REQUIRE_GLSL, 1, vshader_texkill, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
668 {D3DSIO_TEX, "tex", GLNAME_REQUIRE_GLSL, 1, vshader_tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
669 {D3DSIO_TEX, "texld", GLNAME_REQUIRE_GLSL, 2, vshader_texld, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
670 {D3DSIO_TEXBEM, "texbem", GLNAME_REQUIRE_GLSL, 2, vshader_texbem, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
671 {D3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 2, vshader_texbeml, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
672 {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2ar, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
673 {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2gb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXM3x2PAD, "texm3x2pad", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2pad, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2TEX, "texm3x2tex", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3diff, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
677 {D3DSIO_TEXM3x3SPEC, "texm3x3spec", GLNAME_REQUIRE_GLSL, 3, vshader_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
680 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, 0, 0},
681 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, 0, 0},
682 {D3DSIO_CND, "cnd", GLNAME_REQUIRE_GLSL, 4, vshader_cnd, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
683 /* def is a special operation */
684 {D3DSIO_DEF, "def", NULL, 5, vshader_def, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
685 {D3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 2, vshader_texreg2rgb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
686 {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
687 {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
688 {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
689 {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
690 {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
691 {D3DSIO_CMP, "cmp", GLNAME_REQUIRE_GLSL, 4, vshader_cmp, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
692 {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 3, vshader_bem, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
693 /* TODO: dp2add can be made out of multiple instuctions */
694 {D3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 2, vshader_dp2add, 0, 0},
695 {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 2, vshader_dsx, 0, 0},
696 {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 2, vshader_dsy, 0, 0},
697 {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 2, vshader_texldd, 0, 0},
698 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, 0, 0},
699 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, 0, 0},
700 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 2, vshader_breakp, 0, 0},
701 {D3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, vshader_nop, 0, 0},
702 {0, NULL, NULL, 0, NULL, 0, 0}
706 inline static const SHADER_OPCODE* vshader_program_get_opcode(const DWORD code) {
708 /** TODO: use dichotomic search or hash table */
709 while (NULL != vshader_ins[i].name) {
710 if ((code & D3DSI_OPCODE_MASK) == vshader_ins[i].opcode) {
711 return &vshader_ins[i];
715 FIXME("Unsupported opcode %lx\n",code);
719 inline static void vshader_program_dump_param(const DWORD param, int input) {
720 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
721 static const char swizzle_reg_chars[] = "xyzw";
723 DWORD reg = param & 0x00001FFF;
724 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
726 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
730 TRACE("R[%lu]", reg);
736 TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
738 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
739 TRACE("a[%lu]", reg);
742 TRACE("%s", rastout_reg_names[reg]);
745 TRACE("oD[%lu]", reg);
747 case D3DSPR_TEXCRDOUT:
748 TRACE("oT[%lu]", reg);
751 FIXME("Unknown %lu %u reg %lu\n",regtype, D3DSPR_ATTROUT, reg);
756 /** operand output */
757 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
758 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
759 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
760 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
761 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
765 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
766 DWORD swizzle_x = swizzle & 0x03;
767 DWORD swizzle_y = (swizzle >> 2) & 0x03;
768 DWORD swizzle_z = (swizzle >> 4) & 0x03;
769 DWORD swizzle_w = (swizzle >> 6) & 0x03;
771 * swizzle bits fields:
774 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
775 if (swizzle_x == swizzle_y &&
776 swizzle_x == swizzle_z &&
777 swizzle_x == swizzle_w) {
778 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
781 swizzle_reg_chars[swizzle_x],
782 swizzle_reg_chars[swizzle_y],
783 swizzle_reg_chars[swizzle_z],
784 swizzle_reg_chars[swizzle_w]);
790 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
791 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
792 static const char swizzle_reg_chars[] = "xyzw";
793 /* the unknown mask is for bits not yet accounted for by any other mask... */
794 #define UNKNOWN_MASK 0xC000
796 /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
797 #define EXTENDED_REG 0x1800
799 DWORD reg = param & D3DSP_REGNUM_MASK; /* 0x00001FFF; isn't this D3DSP_REGNUM_MASK? */
800 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
802 if(param & UNKNOWN_MASK) { /* if this register has any of the unknown bits set then report them*/
803 FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype, (param & EXTENDED_REG), param & UNKNOWN_MASK);
806 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
808 switch (regtype /*<< D3DSP_REGTYPE_SHIFT*/) {
816 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
818 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
822 TRACE("%s", rastout_reg_names[reg]);
827 case D3DSPR_TEXCRDOUT:
830 case D3DSPR_CONSTINT:
831 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
833 case D3DSPR_CONSTBOOL:
834 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
840 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
843 FIXME("Unknown %lu reg %lu\n",regtype, reg);
848 /** operand output */
849 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
850 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
851 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
852 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
853 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
857 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
858 DWORD swizzle_x = swizzle & 0x03;
859 DWORD swizzle_y = (swizzle >> 2) & 0x03;
860 DWORD swizzle_z = (swizzle >> 4) & 0x03;
861 DWORD swizzle_w = (swizzle >> 6) & 0x03;
863 * swizzle bits fields:
866 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
867 if (swizzle_x == swizzle_y &&
868 swizzle_x == swizzle_z &&
869 swizzle_x == swizzle_w) {
870 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
873 swizzle_reg_chars[swizzle_x],
874 swizzle_reg_chars[swizzle_y],
875 swizzle_reg_chars[swizzle_z],
876 swizzle_reg_chars[swizzle_w]);
882 inline static 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_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
891 /** operand output */
892 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
894 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
895 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
896 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
897 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
901 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
902 static const char swizzle_reg_chars_color_fix[] = "zyxw";
903 static const char swizzle_reg_chars[] = "xyzw";
904 const char* swizzle_regs = NULL;
908 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
909 DWORD swizzle_x = swizzle & 0x03;
910 DWORD swizzle_y = (swizzle >> 2) & 0x03;
911 DWORD swizzle_z = (swizzle >> 4) & 0x03;
912 DWORD swizzle_w = (swizzle >> 6) & 0x03;
915 swizzle_regs = swizzle_reg_chars_color_fix;
917 swizzle_regs = swizzle_reg_chars;
921 * swizzle bits fields:
924 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
926 sprintf(tmpReg, ".%c%c%c%c",
927 swizzle_regs[swizzle_x],
928 swizzle_regs[swizzle_y],
929 swizzle_regs[swizzle_z],
930 swizzle_regs[swizzle_w]);
931 strcat(hwLine, tmpReg);
935 if (swizzle_x == swizzle_y &&
936 swizzle_x == swizzle_z &&
937 swizzle_x == swizzle_w)
939 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
940 strcat(hwLine, tmpReg);
942 sprintf(tmpReg, ".%c%c%c%c",
943 swizzle_regs[swizzle_x],
944 swizzle_regs[swizzle_y],
945 swizzle_regs[swizzle_z],
946 swizzle_regs[swizzle_w]);
947 strcat(hwLine, tmpReg);
951 inline static void vshader_program_add_param(const DWORD param, int input, int is_color, char *hwLine, BOOL namedArrays, CHAR constantsUsedBitmap[]) {
952 /*static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" }; */
953 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
955 DWORD reg = param & 0x00001FFF;
956 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
959 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
960 strcat(hwLine, " -");
967 sprintf(tmpReg, "T%lu", reg);
968 strcat(hwLine, tmpReg);
971 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
973 sprintf(tmpReg, "namedVertex%lu", reg);
975 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
976 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
978 strcat(hwLine, tmpReg);
981 /* FIXME: some constants are named so we need a constants map*/
982 if (constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
983 if (param & D3DVS_ADDRMODE_RELATIVE) {
984 FIXME("Relitive addressing not expected for a named constant %lu\n", reg);
986 sprintf(tmpReg, "const%lu", reg);
988 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
990 strcat(hwLine, tmpReg);
992 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
993 sprintf(tmpReg, "A%lu", reg);
994 strcat(hwLine, tmpReg);
997 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
998 strcat(hwLine, tmpReg);
1000 case D3DSPR_ATTROUT:
1002 strcat(hwLine, "result.color.primary");
1004 strcat(hwLine, "result.color.secondary");
1007 case D3DSPR_TEXCRDOUT:
1008 sprintf(tmpReg, "result.texcoord[%lu]", reg);
1009 strcat(hwLine, tmpReg);
1012 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1017 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1019 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1023 DWORD MacroExpansion[4*4];
1025 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1027 int nComponents = 0;
1029 switch(macro_opcode) {
1032 opcode = D3DSIO_DP4;
1036 opcode = D3DSIO_DP4;
1040 opcode = D3DSIO_DP3;
1044 opcode = D3DSIO_DP3;
1048 opcode = D3DSIO_DP3;
1053 for (i = 0; i < nComponents; i++) {
1054 MacroExpansion[i*4+0] = opcode;
1055 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1056 MacroExpansion[i*4+2] = *(args+1);
1057 MacroExpansion[i*4+3] = (*(args+2))+i;
1063 * Function parser ...
1066 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1067 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1068 const DWORD* pToken = pFunction;
1069 const DWORD* pSavedToken = NULL;
1070 const SHADER_OPCODE* curOpcode = NULL;
1073 unsigned lineNum = 0;
1074 char *pgmStr = NULL;
1076 DWORD nUseAddressRegister = 0;
1077 DWORD nUseTempRegister = 0;
1081 #if 0 /* TODO: loope register (just another address register ) */
1082 BOOL hasLoops = FALSE;
1085 #define PGMSIZE 65535
1086 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1089 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1090 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1091 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1092 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1093 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1094 This->fixupVertexBufferSize = PGMSIZE;
1095 This->fixupVertexBuffer[0] = 0;
1097 pgmStr = This->device->fixupVertexBuffer;
1099 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1100 int _tmpLineLen = strlen(_tmpLine); \
1101 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1102 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); \
1104 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1106 pgmLength += _tmpLineLen; \
1109 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1110 /* Initialise the shader */
1111 This->namedArrays = FALSE;
1112 This->declaredArrays = FALSE;
1113 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1114 This->arrayUsageMap[i] = -1;
1116 /* set all the tmpsUsed to not used */
1117 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1119 /* 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 */
1120 This->highestConstant = -1;
1124 * First pass to determine what we need to declare:
1125 * - Temporary variables
1126 * - Address variables
1128 if (NULL != pToken) {
1129 while (D3DVS_END() != *pToken) {
1130 if (vshader_is_version_token(*pToken)) {
1135 if (vshader_is_comment_token(*pToken)) { /** comment */
1136 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1138 pToken += comment_len;
1141 curOpcode = vshader_program_get_opcode(*pToken);
1146 if (NULL == curOpcode) {
1147 while (*pToken & 0x80000000) {
1148 FIXME("unrecognized opcode: %08lx\n", *pToken);
1149 /* skip unrecognized opcode */
1153 if (curOpcode->opcode == D3DSIO_DCL){
1154 INT usage = *pToken++;
1155 INT arrayNo = (*pToken++ & 0x00001FFF);
1156 switch(usage & 0xFFFF) {
1157 case D3DDECLUSAGE_POSITION:
1158 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1159 TRACE("Setting position to %d\n", arrayNo);
1160 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1161 This->namedArrays = TRUE;
1163 /* TODO: position indexes go from 0-8!!*/
1164 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1165 /* robots uses positions up to 8, the position arrays are just packed.*/
1166 if ((usage & 0xF0000) >> 16 > 1) {
1167 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1169 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1170 This->declaredArrays = TRUE;
1173 case D3DDECLUSAGE_BLENDINDICES:
1174 /* not supported by openGL */
1175 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1176 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1177 This->declaredArrays = TRUE;
1178 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1180 case D3DDECLUSAGE_BLENDWEIGHT:
1181 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1182 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1183 This->namedArrays = TRUE;
1184 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1186 case D3DDECLUSAGE_NORMAL:
1187 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1188 TRACE("Setting normal to %d\n", arrayNo);
1189 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1190 This->namedArrays = TRUE;
1192 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1193 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1194 This->declaredArrays = TRUE;
1197 case D3DDECLUSAGE_PSIZE:
1198 TRACE("Setting PSIZE to %d\n", arrayNo);
1199 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1200 This->namedArrays = TRUE;
1201 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1203 case D3DDECLUSAGE_COLOR:
1204 if((usage & 0xF0000) >> 16 == 0) {
1205 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1206 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1207 This->namedArrays = TRUE;
1209 TRACE("Setting SPECULAR to %d\n", arrayNo);
1210 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1211 This->namedArrays = TRUE;
1214 case D3DDECLUSAGE_TEXCOORD:
1215 This->namedArrays = TRUE;
1216 /* only 7 texture coords have been designed for, so run a quick sanity check */
1217 if ((usage & 0xF0000) >> 16 > 7) {
1218 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1220 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1221 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1224 /* The following aren't supported by openGL,
1225 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1226 this should be caught in the first pass */
1227 case D3DDECLUSAGE_TANGENT:
1228 TRACE("Setting TANGENT to %d\n", arrayNo);
1229 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1230 This->declaredArrays = TRUE;
1232 case D3DDECLUSAGE_BINORMAL:
1233 TRACE("Setting BINORMAL to %d\n", arrayNo);
1234 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1235 This->declaredArrays = TRUE;
1237 case D3DDECLUSAGE_TESSFACTOR:
1238 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1239 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1240 This->declaredArrays = TRUE;
1242 case D3DDECLUSAGE_POSITIONT:
1243 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1244 FIXME("Setting positiont to %d\n", arrayNo);
1245 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1246 This->namedArrays = TRUE;
1248 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1249 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1250 This->declaredArrays = TRUE;
1251 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1254 case D3DDECLUSAGE_FOG:
1255 /* supported by OpenGL */
1256 TRACE("Setting FOG to %d\n", arrayNo);
1257 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1258 This->namedArrays = TRUE;
1260 case D3DDECLUSAGE_DEPTH:
1261 TRACE("Setting DEPTH to %d\n", arrayNo);
1262 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1263 This->declaredArrays = TRUE;
1265 case D3DDECLUSAGE_SAMPLE:
1266 TRACE("Setting SAMPLE to %d\n", arrayNo);
1267 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1268 This->declaredArrays = TRUE;
1271 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1273 } else if(curOpcode->opcode == D3DSIO_DEF) {
1274 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1275 FIXME("Constant %ld\n", *pToken & 0xFF);
1283 /* Check to see if and tmp or addressing redisters are used */
1284 if (curOpcode->num_params > 0) {
1285 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1286 reg = ((*pToken) & 0x00001FFF);
1287 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1288 if (D3DSPR_TEMP == regtype){
1289 tmpsUsed[reg] = TRUE;
1290 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1293 for (i = 1; i < curOpcode->num_params; ++i) {
1294 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1295 reg = ((*pToken) & 0x00001FFF);
1296 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1297 if (D3DSPR_TEMP == regtype){
1298 tmpsUsed[reg] = TRUE;
1299 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1305 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1306 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1307 FIXME("This shader requires gl shader language support\n");
1309 This->shaderLanguage = GLSHADER_GLSL;
1317 #define VSHADER_ALWAYS_NUMBERED
1320 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1321 /* TODO: using numbered arrays for software shaders makes things easier */
1322 This->declaredArrays = TRUE;
1325 /* named arrays and declared arrays are mutually exclusive */
1326 if (This->declaredArrays) {
1327 This->namedArrays = FALSE;
1330 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1331 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1334 /** second pass, now generate */
1337 if (NULL != pToken) {
1340 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1341 /* Macro is finished, continue normal path */
1342 pToken = pSavedToken;
1343 if (D3DVS_END() == *pToken)
1346 if (vshader_is_version_token(*pToken)) { /** version */
1347 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1348 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1352 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1354 /* Each release of vertex shaders has had different numbers of temp registers */
1357 case 11: numTemps=12;
1358 numConstants=96;/* min(GL_LIMITS(constants),96) */
1359 strcpy(tmpLine, "!!ARBvp1.0\n");
1360 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1362 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1363 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1364 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)*/
1365 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1366 numConstants=96; /* min(GL_LIMITS(constants),256) */
1367 strcpy(tmpLine, "!!ARBvp1.0\n");
1368 FIXME("No work done yet to support vs2.0 in hw\n");
1369 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1371 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1372 numConstants=96; /* min(GL_LIMITS(constants),256) */
1373 strcpy(tmpLine, "!!ARBvp1.0\n");
1374 FIXME("No work done yet to support vs2.1 in hw\n");
1375 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1377 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1378 numConstants=96;/* min(GL_LIMITS(constants),256) */
1379 strcpy(tmpLine, "!!ARBvp3.0\n");
1380 FIXME("No work done yet to support vs3.0 in hw\n");
1381 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1384 numTemps=12;/* min(GL_LIMITS(temps),12) */
1385 numConstants=96;/* min(GL_LIMITS(constants),96) */
1386 strcpy(tmpLine, "!!ARBvp1.0\n");
1387 FIXME("Unrecognized vertex shader version %d!\n", version);
1389 PNSTRCAT(pgmStr, tmpLine);
1393 /* This should be a bitmap so that only temp registers that are used are declared. */
1394 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1395 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1396 sprintf(tmpLine, "TEMP T%ld;\n", i);
1398 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1399 PNSTRCAT(pgmStr, tmpLine);
1403 /* TODO: loop register counts as an address register */
1404 for (i = 0; i < nUseAddressRegister; i++) {
1405 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1407 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1408 PNSTRCAT(pgmStr, tmpLine);
1411 /* Due to the dynamic constants binding mechanism, we need to declare
1412 * all the constants for relative addressing. */
1413 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1414 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1417 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1418 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1420 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1421 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1422 PNSTRCAT(pgmStr, tmpLine);
1429 if (vshader_is_comment_token(*pToken)) { /** comment */
1430 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1432 FIXME("#%s\n", (char*)pToken);
1433 pToken += comment_len;
1437 curOpcode = vshader_program_get_opcode(*pToken);
1439 if (NULL == curOpcode) {
1440 /* unknown current opcode ... (shouldn't be any!) */
1441 while (*pToken & 0x80000000) {
1442 FIXME("unrecognized opcode: %08lx\n", *pToken);
1445 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1446 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1448 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1449 pToken += curOpcode->num_params;
1451 /* Build opcode for GL vertex_program */
1452 switch (curOpcode->opcode) {
1456 /* Address registers must be loaded with the ARL instruction */
1457 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1458 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1459 strcpy(tmpLine, "ARL");
1462 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1484 strcpy(tmpLine, curOpcode->glname);
1491 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1492 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1493 /* Save point to next instruction */
1494 pSavedToken = pToken + 3;
1495 /* Execute expanded macro */
1496 pToken = MacroExpansion;
1498 /* dcl and def are handeled in the first pass */
1500 if (This->namedArrays) {
1501 const char* attribName = "undefined";
1502 switch(*pToken & 0xFFFF) {
1503 case D3DDECLUSAGE_POSITION:
1504 attribName = "vertex.position";
1506 case D3DDECLUSAGE_BLENDINDICES:
1507 /* not supported by openGL */
1508 attribName = "vertex.blend";
1510 case D3DDECLUSAGE_BLENDWEIGHT:
1511 attribName = "vertex.weight";
1513 case D3DDECLUSAGE_NORMAL:
1514 attribName = "vertex.normal";
1516 case D3DDECLUSAGE_PSIZE:
1517 attribName = "vertex.psize";
1519 case D3DDECLUSAGE_COLOR:
1520 if((*pToken & 0xF0000) >> 16 == 0) {
1521 attribName = "vertex.color";
1523 attribName = "vertex.color.secondary";
1526 case D3DDECLUSAGE_TEXCOORD:
1530 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1531 attribName = tmpChar;
1534 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1535 case D3DDECLUSAGE_TANGENT:
1536 attribName = "vertex.tangent";
1538 case D3DDECLUSAGE_BINORMAL:
1539 attribName = "vertex.binormal";
1541 case D3DDECLUSAGE_TESSFACTOR:
1542 attribName = "vertex.tessfactor";
1544 case D3DDECLUSAGE_POSITIONT:
1545 attribName = "vertex.possitionT";
1547 case D3DDECLUSAGE_FOG:
1548 attribName = "vertex.fogcoord";
1550 case D3DDECLUSAGE_DEPTH:
1551 attribName = "vertex.depth";
1553 case D3DDECLUSAGE_SAMPLE:
1554 attribName = "vertex.sample";
1557 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1562 sprintf(tmpLine, "ATTRIB ");
1563 vshader_program_add_param(*pToken, 0, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1564 sprintf(tmpChar," = %s", attribName);
1565 strcat(tmpLine, tmpChar);
1566 strcat(tmpLine,";\n");
1568 if (This->namedArrays) {
1569 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1570 PNSTRCAT(pgmStr, tmpLine);
1573 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1577 /* eat the token so it doesn't generate a warning */
1585 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1587 sprintf(tmpChar,"%f ,", *(float *)pToken);
1588 strcat(tmpLine, tmpChar);
1590 sprintf(tmpChar,"%f ,", *(float *)pToken);
1591 strcat(tmpLine, tmpChar);
1593 sprintf(tmpChar,"%f ,", *(float *)pToken);
1594 strcat(tmpLine, tmpChar);
1596 sprintf(tmpChar,"%f}", *(float *)pToken);
1597 strcat(tmpLine, tmpChar);
1599 strcat(tmpLine,";\n");
1601 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1602 PNSTRCAT(pgmStr, tmpLine);
1608 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1609 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1611 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1614 if (curOpcode->num_params > 0) {
1615 vshader_program_add_param(*pToken, 0, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1618 for (i = 1; i < curOpcode->num_params; ++i) {
1619 strcat(tmpLine, ",");
1620 vshader_program_add_param(*pToken, 1, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1624 strcat(tmpLine,";\n");
1626 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1627 PNSTRCAT(pgmStr, tmpLine);
1631 strcpy(tmpLine, "END\n");
1633 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1634 PNSTRCAT(pgmStr, tmpLine);
1637 /* finally null terminate the pgmStr*/
1638 pgmStr[pgmLength] = 0;
1640 /* Check that Vertex Shaders are supported */
1641 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1642 /* Create the hw shader */
1643 /* TODO: change to resource.glObjectHandel or something like that */
1644 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1645 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1646 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1648 /* Create the program and check for errors */
1649 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1650 if (glGetError() == GL_INVALID_OPERATION) {
1652 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1653 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1657 #if 1 /* if were using the data buffer of device then we don't need to free it */
1658 HeapFree(GetProcessHeap(), 0, pgmStr);
1663 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1665 * TODO: use the NV_vertex_program (or 1_1) extension
1666 * and specifics vendors (ARB_vertex_program??) variants for it
1671 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1672 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1674 /** Vertex Shader Temporary Registers */
1675 WINED3DSHADERVECTOR R[12];
1676 /*D3DSHADERSCALAR A0;*/
1677 WINED3DSHADERVECTOR A[1];
1678 /** temporary Vector for modifier management */
1679 WINED3DSHADERVECTOR d;
1680 WINED3DSHADERVECTOR s[3];
1682 const DWORD* pToken = This->function;
1683 const SHADER_OPCODE* curOpcode = NULL;
1684 /** functions parameters */
1685 WINED3DSHADERVECTOR* p[4];
1686 WINED3DSHADERVECTOR* p_send[4];
1689 /** init temporary register */
1690 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1692 /* vshader_program_parse(vshader); */
1693 #if 0 /* Must not be 1 in cvs */
1695 TRACE_VSVECTOR(This->data->C[0]);
1696 TRACE_VSVECTOR(This->data->C[1]);
1697 TRACE_VSVECTOR(This->data->C[2]);
1698 TRACE_VSVECTOR(This->data->C[3]);
1699 TRACE_VSVECTOR(This->data->C[4]);
1700 TRACE_VSVECTOR(This->data->C[5]);
1701 TRACE_VSVECTOR(This->data->C[6]);
1702 TRACE_VSVECTOR(This->data->C[7]);
1703 TRACE_VSVECTOR(This->data->C[8]);
1704 TRACE_VSVECTOR(This->data->C[64]);
1705 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1706 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1707 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1708 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1709 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1710 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1711 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1712 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1713 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1716 TRACE_VSVECTOR(vshader->data->C[64]);
1717 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1719 /* the first dword is the version tag */
1720 /* TODO: parse it */
1722 if (vshader_is_version_token(*pToken)) { /** version */
1725 while (D3DVS_END() != *pToken) {
1726 if (vshader_is_comment_token(*pToken)) { /** comment */
1727 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1729 pToken += comment_len;
1732 curOpcode = vshader_program_get_opcode(*pToken);
1734 if (NULL == curOpcode) {
1736 /* unknown current opcode ... */
1737 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1738 while (*pToken & 0x80000000) {
1740 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1742 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1743 vshader_program_dump_param(*pToken, i);
1750 if (curOpcode->num_params > 0) {
1751 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1752 for (i = 0; i < curOpcode->num_params; ++i) {
1753 DWORD reg = pToken[i] & 0x00001FFF;
1754 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1756 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1758 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1762 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1763 p[i] = &input->V[reg];
1766 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1767 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1769 p[i] = &This->data->C[reg];
1772 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1774 ERR("cannot handle address registers != a0, forcing use of a0\n");
1777 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1780 case D3DSPR_RASTOUT:
1782 case D3DSRO_POSITION:
1783 p[i] = &output->oPos;
1786 p[i] = &output->oFog;
1788 case D3DSRO_POINT_SIZE:
1789 p[i] = &output->oPts;
1793 case D3DSPR_ATTROUT:
1794 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1795 p[i] = &output->oD[reg];
1797 case D3DSPR_TEXCRDOUT:
1798 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1799 p[i] = &output->oT[reg];
1801 /* TODO Decls and defs */
1810 if (i > 0) { /* input reg */
1811 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1812 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1814 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1815 /* TRACE("p[%d] not swizzled\n", i); */
1818 DWORD swizzle_x = swizzle & 0x03;
1819 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1820 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1821 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1822 /* TRACE("p[%d] swizzled\n", i); */
1823 float* tt = (float*) p[i];
1824 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1825 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1826 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1827 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1830 } else { /* output reg */
1831 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1834 p_send[i] = &d; /* to be post-processed for modifiers management */
1840 switch (curOpcode->num_params) {
1842 curOpcode->soft_fct();
1845 curOpcode->soft_fct(p_send[0]);
1848 curOpcode->soft_fct(p_send[0], p_send[1]);
1851 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1854 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1857 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1860 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1863 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1866 /* check if output reg modifier post-process */
1867 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1868 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1869 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1870 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1871 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1874 TRACE_VSVECTOR(output->oPos);
1875 TRACE_VSVECTOR(output->oD[0]);
1876 TRACE_VSVECTOR(output->oD[1]);
1877 TRACE_VSVECTOR(output->oT[0]);
1878 TRACE_VSVECTOR(output->oT[1]);
1879 TRACE_VSVECTOR(R[0]);
1880 TRACE_VSVECTOR(R[1]);
1881 TRACE_VSVECTOR(R[2]);
1882 TRACE_VSVECTOR(R[3]);
1883 TRACE_VSVECTOR(R[4]);
1884 TRACE_VSVECTOR(R[5]);
1887 /* to next opcode token */
1888 pToken += curOpcode->num_params;
1891 TRACE("End of current instruction:\n");
1892 TRACE_VSVECTOR(output->oPos);
1893 TRACE_VSVECTOR(output->oD[0]);
1894 TRACE_VSVECTOR(output->oD[1]);
1895 TRACE_VSVECTOR(output->oT[0]);
1896 TRACE_VSVECTOR(output->oT[1]);
1897 TRACE_VSVECTOR(R[0]);
1898 TRACE_VSVECTOR(R[1]);
1899 TRACE_VSVECTOR(R[2]);
1900 TRACE_VSVECTOR(R[3]);
1901 TRACE_VSVECTOR(R[4]);
1902 TRACE_VSVECTOR(R[5]);
1905 #if 0 /* Must not be 1 in cvs */
1907 TRACE_VSVECTOR(output->oPos);
1908 TRACE_VSVECTOR(output->oD[0]);
1909 TRACE_VSVECTOR(output->oD[1]);
1910 TRACE_VSVECTOR(output->oT[0]);
1911 TRACE_VSVECTOR(output->oT[1]);
1916 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1917 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1918 FIXME("(%p) : stub\n", This);
1922 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1923 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1924 FIXME("(%p) : stub\n", This);
1928 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1929 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1930 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1931 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1932 return D3DERR_INVALIDCALL;
1934 if (NULL == pConstantData) {
1935 return D3DERR_INVALIDCALL;
1937 FIXME("(%p) : stub\n", This);
1941 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1942 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1943 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1944 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1945 return D3DERR_INVALIDCALL;
1947 if (NULL == pConstantData) {
1948 return D3DERR_INVALIDCALL;
1950 FIXME("(%p) : stub\n", This);
1954 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1955 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1956 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1957 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1958 return D3DERR_INVALIDCALL;
1960 if (NULL == pConstantData) {
1961 return D3DERR_INVALIDCALL;
1963 FIXME("(%p) : stub\n", This);
1967 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1968 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1969 FIXME("(%p) : stub\n", This);
1975 /* *******************************************
1976 IWineD3DVertexShader IUnknown parts follow
1977 ******************************************* */
1978 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1980 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1981 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1982 if (IsEqualGUID(riid, &IID_IUnknown)
1983 || IsEqualGUID(riid, &IID_IWineD3DBase)
1984 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1985 IUnknown_AddRef(iface);
1989 return E_NOINTERFACE;
1992 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1993 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1994 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1995 return InterlockedIncrement(&This->ref);
1998 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1999 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2001 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2002 ref = InterlockedDecrement(&This->ref);
2004 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2005 HeapFree(GetProcessHeap(), 0, This);
2010 /* *******************************************
2011 IWineD3DVertexShader IWineD3DVertexShader parts follow
2012 ******************************************* */
2014 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2015 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2017 *parent = This->parent;
2018 IUnknown_AddRef(*parent);
2019 TRACE("(%p) : returning %p\n", This, *parent);
2023 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2024 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2025 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2026 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2027 TRACE("(%p) returning %p\n", This, *pDevice);
2031 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2032 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2033 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2035 if (NULL == pData) {
2036 *pSizeOfData = This->functionLength;
2039 if (*pSizeOfData < This->functionLength) {
2040 *pSizeOfData = This->functionLength;
2041 return D3DERR_MOREDATA;
2043 if (NULL == This->function) { /* no function defined */
2044 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2045 (*(DWORD **) pData) = NULL;
2047 if(This->functionLength == 0){
2050 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2051 memcpy(pData, This->function, This->functionLength);
2056 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2057 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2058 const DWORD* pToken = pFunction;
2059 const SHADER_OPCODE* curOpcode = NULL;
2062 TRACE("(%p) : Parsing programme\n", This);
2064 if (NULL != pToken) {
2065 while (D3DVS_END() != *pToken) {
2066 if (vshader_is_version_token(*pToken)) { /** version */
2067 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2072 if (vshader_is_comment_token(*pToken)) { /** comment */
2073 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2075 TRACE("//%s\n", (char*)pToken);
2076 pToken += comment_len;
2077 len += comment_len + 1;
2080 curOpcode = vshader_program_get_opcode(*pToken);
2083 if (NULL == curOpcode) {
2084 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2085 while (*pToken & 0x80000000) {
2086 /* unknown current opcode ... */
2087 FIXME("unrecognized opcode: %08lx", *pToken);
2094 if (curOpcode->opcode == D3DSIO_DCL) {
2096 switch(*pToken & 0xFFFF) {
2097 case D3DDECLUSAGE_POSITION:
2098 TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2100 case D3DDECLUSAGE_BLENDINDICES:
2101 TRACE("%s ", "blend");
2103 case D3DDECLUSAGE_BLENDWEIGHT:
2104 TRACE("%s ", "weight");
2106 case D3DDECLUSAGE_NORMAL:
2107 TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2109 case D3DDECLUSAGE_PSIZE:
2110 TRACE("%s ", "psize");
2112 case D3DDECLUSAGE_COLOR:
2113 if((*pToken & 0xF0000) >> 16 == 0) {
2114 TRACE("%s ", "color");
2116 TRACE("%s ", "specular");
2119 case D3DDECLUSAGE_TEXCOORD:
2120 TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2122 case D3DDECLUSAGE_TANGENT:
2123 TRACE("%s ", "tangent");
2125 case D3DDECLUSAGE_BINORMAL:
2126 TRACE("%s ", "binormal");
2128 case D3DDECLUSAGE_TESSFACTOR:
2129 TRACE("%s ", "tessfactor");
2131 case D3DDECLUSAGE_POSITIONT:
2132 TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2134 case D3DDECLUSAGE_FOG:
2135 TRACE("%s ", "fog");
2137 case D3DDECLUSAGE_DEPTH:
2138 TRACE("%s ", "depth");
2140 case D3DDECLUSAGE_SAMPLE:
2141 TRACE("%s ", "sample");
2144 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2148 vshader_program_dump_vs_param(*pToken, 0);
2152 if (curOpcode->opcode == D3DSIO_DEF) {
2153 TRACE("def c%lu = ", *pToken & 0xFF);
2156 TRACE("%f ,", *(float *)pToken);
2159 TRACE("%f ,", *(float *)pToken);
2162 TRACE("%f ,", *(float *)pToken);
2165 TRACE("%f", *(float *)pToken);
2169 TRACE("%s ", curOpcode->name);
2170 if (curOpcode->num_params > 0) {
2171 vshader_program_dump_vs_param(*pToken, 0);
2174 for (i = 1; i < curOpcode->num_params; ++i) {
2176 vshader_program_dump_vs_param(*pToken, 1);
2185 This->functionLength = (len + 1) * sizeof(DWORD);
2187 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2190 /* Generate HW shader in needed */
2191 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2193 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2197 /* copy the function ... because it will certainly be released by application */
2198 if (NULL != pFunction) {
2199 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2200 memcpy((void *)This->function, pFunction, This->functionLength);
2202 This->function = NULL;
2207 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2209 /*** IUnknown methods ***/
2210 IWineD3DVertexShaderImpl_QueryInterface,
2211 IWineD3DVertexShaderImpl_AddRef,
2212 IWineD3DVertexShaderImpl_Release,
2213 /*** IWineD3DVertexShader methods ***/
2214 IWineD3DVertexShaderImpl_GetParent,
2215 IWineD3DVertexShaderImpl_GetDevice,
2216 IWineD3DVertexShaderImpl_GetFunction,
2217 IWineD3DVertexShaderImpl_SetFunction