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(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
952 /* oPos, oFog and oPts in D3D */
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);
958 BOOL is_color = FALSE;
960 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
961 strcat(hwLine, " -");
968 sprintf(tmpReg, "T%lu", reg);
969 strcat(hwLine, tmpReg);
972 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
973 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
976 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
977 if (This->namedArrays) {
978 sprintf(tmpReg, "namedVertex%lu", reg);
980 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
981 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
983 strcat(hwLine, tmpReg);
986 /* FIXME: some constants are named so we need a constants map*/
987 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
988 if (param & D3DVS_ADDRMODE_RELATIVE) {
989 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
991 sprintf(tmpReg, "const%lu", reg);
993 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
995 strcat(hwLine, tmpReg);
997 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
998 sprintf(tmpReg, "A%lu", reg);
999 strcat(hwLine, tmpReg);
1001 case D3DSPR_RASTOUT:
1002 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
1003 strcat(hwLine, tmpReg);
1005 case D3DSPR_ATTROUT:
1007 strcat(hwLine, "result.color.primary");
1009 strcat(hwLine, "result.color.secondary");
1012 case D3DSPR_TEXCRDOUT:
1013 sprintf(tmpReg, "result.texcoord[%lu]", reg);
1014 strcat(hwLine, tmpReg);
1017 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1022 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1024 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1028 DWORD MacroExpansion[4*4];
1030 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1032 int nComponents = 0;
1034 switch(macro_opcode) {
1037 opcode = D3DSIO_DP4;
1041 opcode = D3DSIO_DP4;
1045 opcode = D3DSIO_DP3;
1049 opcode = D3DSIO_DP3;
1053 opcode = D3DSIO_DP3;
1058 for (i = 0; i < nComponents; i++) {
1059 MacroExpansion[i*4+0] = opcode;
1060 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1061 MacroExpansion[i*4+2] = *(args+1);
1062 MacroExpansion[i*4+3] = (*(args+2))+i;
1067 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
1069 switch(usage & 0xFFFF) {
1070 case D3DDECLUSAGE_POSITION:
1071 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1072 TRACE("Setting position to %d\n", arrayNo);
1073 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1074 This->namedArrays = TRUE;
1076 /* TODO: position indexes go from 0-8!!*/
1077 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1078 /* robots uses positions up to 8, the position arrays are just packed.*/
1079 if ((usage & 0xF0000) >> 16 > 1) {
1080 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1082 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1083 This->declaredArrays = TRUE;
1086 case D3DDECLUSAGE_BLENDINDICES:
1087 /* not supported by openGL */
1088 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1089 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1090 This->declaredArrays = TRUE;
1091 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1093 case D3DDECLUSAGE_BLENDWEIGHT:
1094 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1095 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1096 This->namedArrays = TRUE;
1097 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1099 case D3DDECLUSAGE_NORMAL:
1100 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1101 TRACE("Setting normal to %d\n", arrayNo);
1102 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1103 This->namedArrays = TRUE;
1105 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1106 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1107 This->declaredArrays = TRUE;
1110 case D3DDECLUSAGE_PSIZE:
1111 TRACE("Setting PSIZE to %d\n", arrayNo);
1112 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1113 This->namedArrays = TRUE;
1114 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1116 case D3DDECLUSAGE_COLOR:
1117 if((usage & 0xF0000) >> 16 == 0) {
1118 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1119 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1120 This->namedArrays = TRUE;
1122 TRACE("Setting SPECULAR to %d\n", arrayNo);
1123 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1124 This->namedArrays = TRUE;
1127 case D3DDECLUSAGE_TEXCOORD:
1128 This->namedArrays = TRUE;
1129 /* only 7 texture coords have been designed for, so run a quick sanity check */
1130 if ((usage & 0xF0000) >> 16 > 7) {
1131 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1133 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1134 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1137 /* The following aren't supported by openGL,
1138 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1139 this should be caught in the first pass */
1140 case D3DDECLUSAGE_TANGENT:
1141 TRACE("Setting TANGENT to %d\n", arrayNo);
1142 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1143 This->declaredArrays = TRUE;
1145 case D3DDECLUSAGE_BINORMAL:
1146 TRACE("Setting BINORMAL to %d\n", arrayNo);
1147 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1148 This->declaredArrays = TRUE;
1150 case D3DDECLUSAGE_TESSFACTOR:
1151 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1152 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1153 This->declaredArrays = TRUE;
1155 case D3DDECLUSAGE_POSITIONT:
1156 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1157 FIXME("Setting positiont to %d\n", arrayNo);
1158 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1159 This->namedArrays = TRUE;
1161 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1162 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1163 This->declaredArrays = TRUE;
1164 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1167 case D3DDECLUSAGE_FOG:
1168 /* supported by OpenGL */
1169 TRACE("Setting FOG to %d\n", arrayNo);
1170 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1171 This->namedArrays = TRUE;
1173 case D3DDECLUSAGE_DEPTH:
1174 TRACE("Setting DEPTH to %d\n", arrayNo);
1175 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1176 This->declaredArrays = TRUE;
1178 case D3DDECLUSAGE_SAMPLE:
1179 TRACE("Setting SAMPLE to %d\n", arrayNo);
1180 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1181 This->declaredArrays = TRUE;
1184 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1189 * Function parser ...
1192 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1193 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1194 const DWORD* pToken = pFunction;
1195 const DWORD* pSavedToken = NULL;
1196 const SHADER_OPCODE* curOpcode = NULL;
1199 unsigned lineNum = 0;
1200 char *pgmStr = NULL;
1202 DWORD nUseAddressRegister = 0;
1203 DWORD nUseTempRegister = 0;
1207 #if 0 /* TODO: loope register (just another address register ) */
1208 BOOL hasLoops = FALSE;
1211 #define PGMSIZE 65535
1212 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1215 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1216 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1217 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1218 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1219 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1220 This->fixupVertexBufferSize = PGMSIZE;
1221 This->fixupVertexBuffer[0] = 0;
1223 pgmStr = This->device->fixupVertexBuffer;
1225 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1226 int _tmpLineLen = strlen(_tmpLine); \
1227 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1228 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); \
1230 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1232 pgmLength += _tmpLineLen; \
1235 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1236 /* Initialise the shader */
1237 This->namedArrays = FALSE;
1238 This->declaredArrays = FALSE;
1239 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1240 This->arrayUsageMap[i] = -1;
1242 /* set all the tmpsUsed to not used */
1243 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1245 /* 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 */
1246 This->highestConstant = -1;
1249 * First pass to determine what we need to declare:
1250 * - Temporary variables
1251 * - Address variables
1253 if (NULL != pToken) {
1254 while (D3DVS_END() != *pToken) {
1255 if (vshader_is_version_token(*pToken)) {
1260 if (vshader_is_comment_token(*pToken)) { /** comment */
1261 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1263 pToken += comment_len;
1266 curOpcode = vshader_program_get_opcode(*pToken);
1271 if (NULL == curOpcode) {
1272 while (*pToken & 0x80000000) {
1273 FIXME("unrecognized opcode: %08lx\n", *pToken);
1274 /* skip unrecognized opcode */
1278 if (curOpcode->opcode == D3DSIO_DCL){
1279 INT usage = *pToken++;
1280 INT arrayNo = (*pToken++ & 0x00001FFF);
1281 parse_decl_usage(This, usage, arrayNo);
1282 } else if(curOpcode->opcode == D3DSIO_DEF) {
1283 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1284 FIXME("Constant %ld\n", *pToken & 0xFF);
1292 /* Check to see if and tmp or addressing redisters are used */
1293 if (curOpcode->num_params > 0) {
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;
1302 for (i = 1; i < curOpcode->num_params; ++i) {
1303 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1304 reg = ((*pToken) & 0x00001FFF);
1305 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1306 if (D3DSPR_TEMP == regtype){
1307 tmpsUsed[reg] = TRUE;
1308 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1314 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1315 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1316 FIXME("This shader requires gl shader language support\n");
1318 This->shaderLanguage = GLSHADER_GLSL;
1326 #define VSHADER_ALWAYS_NUMBERED
1329 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1330 /* TODO: using numbered arrays for software shaders makes things easier */
1331 This->declaredArrays = TRUE;
1334 /* named arrays and declared arrays are mutually exclusive */
1335 if (This->declaredArrays) {
1336 This->namedArrays = FALSE;
1339 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1340 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1343 /** second pass, now generate */
1346 if (NULL != pToken) {
1349 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1350 /* Macro is finished, continue normal path */
1351 pToken = pSavedToken;
1352 if (D3DVS_END() == *pToken)
1355 if (vshader_is_version_token(*pToken)) { /** version */
1356 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1357 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1361 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1363 /* Each release of vertex shaders has had different numbers of temp registers */
1366 case 11: numTemps=12;
1367 numConstants=96;/* min(GL_LIMITS(constants),96) */
1368 strcpy(tmpLine, "!!ARBvp1.0\n");
1369 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1371 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1372 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1373 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)*/
1374 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1375 numConstants=96; /* min(GL_LIMITS(constants),256) */
1376 strcpy(tmpLine, "!!ARBvp1.0\n");
1377 FIXME("No work done yet to support vs2.0 in hw\n");
1378 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1380 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1381 numConstants=96; /* min(GL_LIMITS(constants),256) */
1382 strcpy(tmpLine, "!!ARBvp1.0\n");
1383 FIXME("No work done yet to support vs2.1 in hw\n");
1384 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1386 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1387 numConstants=96;/* min(GL_LIMITS(constants),256) */
1388 strcpy(tmpLine, "!!ARBvp3.0\n");
1389 FIXME("No work done yet to support vs3.0 in hw\n");
1390 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1393 numTemps=12;/* min(GL_LIMITS(temps),12) */
1394 numConstants=96;/* min(GL_LIMITS(constants),96) */
1395 strcpy(tmpLine, "!!ARBvp1.0\n");
1396 FIXME("Unrecognized vertex shader version %d!\n", version);
1398 PNSTRCAT(pgmStr, tmpLine);
1402 /* This should be a bitmap so that only temp registers that are used are declared. */
1403 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1404 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1405 sprintf(tmpLine, "TEMP T%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);
1412 /* TODO: loop register counts as an address register */
1413 for (i = 0; i < nUseAddressRegister; i++) {
1414 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1416 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1417 PNSTRCAT(pgmStr, tmpLine);
1420 /* Due to the dynamic constants binding mechanism, we need to declare
1421 * all the constants for relative addressing. */
1422 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1423 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1426 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1427 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1429 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1430 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1431 PNSTRCAT(pgmStr, tmpLine);
1438 if (vshader_is_comment_token(*pToken)) { /** comment */
1439 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1441 FIXME("#%s\n", (char*)pToken);
1442 pToken += comment_len;
1446 curOpcode = vshader_program_get_opcode(*pToken);
1448 if (NULL == curOpcode) {
1449 /* unknown current opcode ... (shouldn't be any!) */
1450 while (*pToken & 0x80000000) {
1451 FIXME("unrecognized opcode: %08lx\n", *pToken);
1454 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1455 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1457 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1458 pToken += curOpcode->num_params;
1460 /* Build opcode for GL vertex_program */
1461 switch (curOpcode->opcode) {
1465 /* Address registers must be loaded with the ARL instruction */
1466 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1467 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1468 strcpy(tmpLine, "ARL");
1471 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1493 strcpy(tmpLine, curOpcode->glname);
1500 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1501 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1502 /* Save point to next instruction */
1503 pSavedToken = pToken + 3;
1504 /* Execute expanded macro */
1505 pToken = MacroExpansion;
1507 /* dcl and def are handeled in the first pass */
1509 if (This->namedArrays) {
1510 const char* attribName = "undefined";
1511 switch(*pToken & 0xFFFF) {
1512 case D3DDECLUSAGE_POSITION:
1513 attribName = "vertex.position";
1515 case D3DDECLUSAGE_BLENDINDICES:
1516 /* not supported by openGL */
1517 attribName = "vertex.blend";
1519 case D3DDECLUSAGE_BLENDWEIGHT:
1520 attribName = "vertex.weight";
1522 case D3DDECLUSAGE_NORMAL:
1523 attribName = "vertex.normal";
1525 case D3DDECLUSAGE_PSIZE:
1526 attribName = "vertex.psize";
1528 case D3DDECLUSAGE_COLOR:
1529 if((*pToken & 0xF0000) >> 16 == 0) {
1530 attribName = "vertex.color";
1532 attribName = "vertex.color.secondary";
1535 case D3DDECLUSAGE_TEXCOORD:
1539 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1540 attribName = tmpChar;
1543 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1544 case D3DDECLUSAGE_TANGENT:
1545 attribName = "vertex.tangent";
1547 case D3DDECLUSAGE_BINORMAL:
1548 attribName = "vertex.binormal";
1550 case D3DDECLUSAGE_TESSFACTOR:
1551 attribName = "vertex.tessfactor";
1553 case D3DDECLUSAGE_POSITIONT:
1554 attribName = "vertex.possitionT";
1556 case D3DDECLUSAGE_FOG:
1557 attribName = "vertex.fogcoord";
1559 case D3DDECLUSAGE_DEPTH:
1560 attribName = "vertex.depth";
1562 case D3DDECLUSAGE_SAMPLE:
1563 attribName = "vertex.sample";
1566 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1571 sprintf(tmpLine, "ATTRIB ");
1572 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1573 sprintf(tmpChar," = %s", attribName);
1574 strcat(tmpLine, tmpChar);
1575 strcat(tmpLine,";\n");
1577 if (This->namedArrays) {
1578 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1579 PNSTRCAT(pgmStr, tmpLine);
1582 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1586 /* eat the token so it doesn't generate a warning */
1594 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1596 sprintf(tmpChar,"%f ,", *(float *)pToken);
1597 strcat(tmpLine, tmpChar);
1599 sprintf(tmpChar,"%f ,", *(float *)pToken);
1600 strcat(tmpLine, tmpChar);
1602 sprintf(tmpChar,"%f ,", *(float *)pToken);
1603 strcat(tmpLine, tmpChar);
1605 sprintf(tmpChar,"%f}", *(float *)pToken);
1606 strcat(tmpLine, tmpChar);
1608 strcat(tmpLine,";\n");
1610 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1611 PNSTRCAT(pgmStr, tmpLine);
1617 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1618 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1620 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1623 if (curOpcode->num_params > 0) {
1624 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1627 for (i = 1; i < curOpcode->num_params; ++i) {
1628 strcat(tmpLine, ",");
1629 vshader_program_add_param(This, *pToken, TRUE, tmpLine);
1633 strcat(tmpLine,";\n");
1635 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1636 PNSTRCAT(pgmStr, tmpLine);
1640 strcpy(tmpLine, "END\n");
1642 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1643 PNSTRCAT(pgmStr, tmpLine);
1646 /* finally null terminate the pgmStr*/
1647 pgmStr[pgmLength] = 0;
1649 /* Check that Vertex Shaders are supported */
1650 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1651 /* Create the hw shader */
1652 /* TODO: change to resource.glObjectHandel or something like that */
1653 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1654 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1655 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1657 /* Create the program and check for errors */
1658 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1659 if (glGetError() == GL_INVALID_OPERATION) {
1661 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1662 FIXME("HW VertexShader Error at position %d: %s\n",
1663 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1667 #if 1 /* if were using the data buffer of device then we don't need to free it */
1668 HeapFree(GetProcessHeap(), 0, pgmStr);
1673 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1675 * TODO: use the NV_vertex_program (or 1_1) extension
1676 * and specifics vendors (ARB_vertex_program??) variants for it
1681 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1682 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1684 /** Vertex Shader Temporary Registers */
1685 WINED3DSHADERVECTOR R[12];
1686 /*D3DSHADERSCALAR A0;*/
1687 WINED3DSHADERVECTOR A[1];
1688 /** temporary Vector for modifier management */
1689 WINED3DSHADERVECTOR d;
1690 WINED3DSHADERVECTOR s[3];
1692 const DWORD* pToken = This->function;
1693 const SHADER_OPCODE* curOpcode = NULL;
1694 /** functions parameters */
1695 WINED3DSHADERVECTOR* p[4];
1696 WINED3DSHADERVECTOR* p_send[4];
1699 /** init temporary register */
1700 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1702 /* vshader_program_parse(vshader); */
1703 #if 0 /* Must not be 1 in cvs */
1705 TRACE_VSVECTOR(This->data->C[0]);
1706 TRACE_VSVECTOR(This->data->C[1]);
1707 TRACE_VSVECTOR(This->data->C[2]);
1708 TRACE_VSVECTOR(This->data->C[3]);
1709 TRACE_VSVECTOR(This->data->C[4]);
1710 TRACE_VSVECTOR(This->data->C[5]);
1711 TRACE_VSVECTOR(This->data->C[6]);
1712 TRACE_VSVECTOR(This->data->C[7]);
1713 TRACE_VSVECTOR(This->data->C[8]);
1714 TRACE_VSVECTOR(This->data->C[64]);
1715 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1716 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1717 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1718 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1719 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1720 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1721 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1722 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1723 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1726 TRACE_VSVECTOR(vshader->data->C[64]);
1727 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1729 /* the first dword is the version tag */
1730 /* TODO: parse it */
1732 if (vshader_is_version_token(*pToken)) { /** version */
1735 while (D3DVS_END() != *pToken) {
1736 if (vshader_is_comment_token(*pToken)) { /** comment */
1737 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1739 pToken += comment_len;
1742 curOpcode = vshader_program_get_opcode(*pToken);
1744 if (NULL == curOpcode) {
1746 /* unknown current opcode ... */
1747 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1748 while (*pToken & 0x80000000) {
1750 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1752 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1753 vshader_program_dump_param(*pToken, i);
1760 if (curOpcode->num_params > 0) {
1761 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1762 for (i = 0; i < curOpcode->num_params; ++i) {
1763 DWORD reg = pToken[i] & 0x00001FFF;
1764 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1766 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1768 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1772 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1773 p[i] = &input->V[reg];
1776 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1777 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1779 p[i] = &This->data->C[reg];
1782 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1784 ERR("cannot handle address registers != a0, forcing use of a0\n");
1787 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1790 case D3DSPR_RASTOUT:
1792 case D3DSRO_POSITION:
1793 p[i] = &output->oPos;
1796 p[i] = &output->oFog;
1798 case D3DSRO_POINT_SIZE:
1799 p[i] = &output->oPts;
1803 case D3DSPR_ATTROUT:
1804 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1805 p[i] = &output->oD[reg];
1807 case D3DSPR_TEXCRDOUT:
1808 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1809 p[i] = &output->oT[reg];
1811 /* TODO Decls and defs */
1820 if (i > 0) { /* input reg */
1821 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1822 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1824 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1825 /* TRACE("p[%d] not swizzled\n", i); */
1828 DWORD swizzle_x = swizzle & 0x03;
1829 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1830 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1831 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1832 /* TRACE("p[%d] swizzled\n", i); */
1833 float* tt = (float*) p[i];
1834 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1835 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1836 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1837 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1840 } else { /* output reg */
1841 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1844 p_send[i] = &d; /* to be post-processed for modifiers management */
1850 switch (curOpcode->num_params) {
1852 curOpcode->soft_fct();
1855 curOpcode->soft_fct(p_send[0]);
1858 curOpcode->soft_fct(p_send[0], p_send[1]);
1861 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1864 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1867 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1870 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1873 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1876 /* check if output reg modifier post-process */
1877 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1878 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1879 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1880 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1881 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1884 TRACE_VSVECTOR(output->oPos);
1885 TRACE_VSVECTOR(output->oD[0]);
1886 TRACE_VSVECTOR(output->oD[1]);
1887 TRACE_VSVECTOR(output->oT[0]);
1888 TRACE_VSVECTOR(output->oT[1]);
1889 TRACE_VSVECTOR(R[0]);
1890 TRACE_VSVECTOR(R[1]);
1891 TRACE_VSVECTOR(R[2]);
1892 TRACE_VSVECTOR(R[3]);
1893 TRACE_VSVECTOR(R[4]);
1894 TRACE_VSVECTOR(R[5]);
1897 /* to next opcode token */
1898 pToken += curOpcode->num_params;
1901 TRACE("End of current instruction:\n");
1902 TRACE_VSVECTOR(output->oPos);
1903 TRACE_VSVECTOR(output->oD[0]);
1904 TRACE_VSVECTOR(output->oD[1]);
1905 TRACE_VSVECTOR(output->oT[0]);
1906 TRACE_VSVECTOR(output->oT[1]);
1907 TRACE_VSVECTOR(R[0]);
1908 TRACE_VSVECTOR(R[1]);
1909 TRACE_VSVECTOR(R[2]);
1910 TRACE_VSVECTOR(R[3]);
1911 TRACE_VSVECTOR(R[4]);
1912 TRACE_VSVECTOR(R[5]);
1915 #if 0 /* Must not be 1 in cvs */
1917 TRACE_VSVECTOR(output->oPos);
1918 TRACE_VSVECTOR(output->oD[0]);
1919 TRACE_VSVECTOR(output->oD[1]);
1920 TRACE_VSVECTOR(output->oT[0]);
1921 TRACE_VSVECTOR(output->oT[1]);
1926 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1927 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1928 FIXME("(%p) : stub\n", This);
1932 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1933 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1934 FIXME("(%p) : stub\n", This);
1938 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1939 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1940 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1941 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1942 return D3DERR_INVALIDCALL;
1944 if (NULL == pConstantData) {
1945 return D3DERR_INVALIDCALL;
1947 FIXME("(%p) : stub\n", This);
1951 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1952 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1953 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1954 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1955 return D3DERR_INVALIDCALL;
1957 if (NULL == pConstantData) {
1958 return D3DERR_INVALIDCALL;
1960 FIXME("(%p) : stub\n", This);
1964 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1965 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1966 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1967 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1968 return D3DERR_INVALIDCALL;
1970 if (NULL == pConstantData) {
1971 return D3DERR_INVALIDCALL;
1973 FIXME("(%p) : stub\n", This);
1977 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1978 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1979 FIXME("(%p) : stub\n", This);
1985 /* *******************************************
1986 IWineD3DVertexShader IUnknown parts follow
1987 ******************************************* */
1988 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1990 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1991 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1992 if (IsEqualGUID(riid, &IID_IUnknown)
1993 || IsEqualGUID(riid, &IID_IWineD3DBase)
1994 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1995 IUnknown_AddRef(iface);
1999 return E_NOINTERFACE;
2002 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
2003 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2004 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2005 return InterlockedIncrement(&This->ref);
2008 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
2009 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2011 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2012 ref = InterlockedDecrement(&This->ref);
2014 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2015 HeapFree(GetProcessHeap(), 0, This);
2020 /* *******************************************
2021 IWineD3DVertexShader IWineD3DVertexShader parts follow
2022 ******************************************* */
2024 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2025 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2027 *parent = This->parent;
2028 IUnknown_AddRef(*parent);
2029 TRACE("(%p) : returning %p\n", This, *parent);
2033 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2034 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2035 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2036 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2037 TRACE("(%p) returning %p\n", This, *pDevice);
2041 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2042 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2043 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2045 if (NULL == pData) {
2046 *pSizeOfData = This->functionLength;
2049 if (*pSizeOfData < This->functionLength) {
2050 *pSizeOfData = This->functionLength;
2051 return D3DERR_MOREDATA;
2053 if (NULL == This->function) { /* no function defined */
2054 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2055 (*(DWORD **) pData) = NULL;
2057 if(This->functionLength == 0){
2060 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2061 memcpy(pData, This->function, This->functionLength);
2066 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2067 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2068 const DWORD* pToken = pFunction;
2069 const SHADER_OPCODE* curOpcode = NULL;
2072 TRACE("(%p) : Parsing programme\n", This);
2074 if (NULL != pToken) {
2075 while (D3DVS_END() != *pToken) {
2076 if (vshader_is_version_token(*pToken)) { /** version */
2077 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2082 if (vshader_is_comment_token(*pToken)) { /** comment */
2083 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2085 TRACE("//%s\n", (char*)pToken);
2086 pToken += comment_len;
2087 len += comment_len + 1;
2090 curOpcode = vshader_program_get_opcode(*pToken);
2093 if (NULL == curOpcode) {
2094 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2095 while (*pToken & 0x80000000) {
2096 /* unknown current opcode ... */
2097 FIXME("unrecognized opcode: %08lx", *pToken);
2104 if (curOpcode->opcode == D3DSIO_DCL) {
2106 switch(*pToken & 0xFFFF) {
2107 case D3DDECLUSAGE_POSITION:
2108 TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2110 case D3DDECLUSAGE_BLENDINDICES:
2111 TRACE("%s ", "blend");
2113 case D3DDECLUSAGE_BLENDWEIGHT:
2114 TRACE("%s ", "weight");
2116 case D3DDECLUSAGE_NORMAL:
2117 TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2119 case D3DDECLUSAGE_PSIZE:
2120 TRACE("%s ", "psize");
2122 case D3DDECLUSAGE_COLOR:
2123 if((*pToken & 0xF0000) >> 16 == 0) {
2124 TRACE("%s ", "color");
2126 TRACE("%s ", "specular");
2129 case D3DDECLUSAGE_TEXCOORD:
2130 TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2132 case D3DDECLUSAGE_TANGENT:
2133 TRACE("%s ", "tangent");
2135 case D3DDECLUSAGE_BINORMAL:
2136 TRACE("%s ", "binormal");
2138 case D3DDECLUSAGE_TESSFACTOR:
2139 TRACE("%s ", "tessfactor");
2141 case D3DDECLUSAGE_POSITIONT:
2142 TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2144 case D3DDECLUSAGE_FOG:
2145 TRACE("%s ", "fog");
2147 case D3DDECLUSAGE_DEPTH:
2148 TRACE("%s ", "depth");
2150 case D3DDECLUSAGE_SAMPLE:
2151 TRACE("%s ", "sample");
2154 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2158 vshader_program_dump_vs_param(*pToken, 0);
2162 if (curOpcode->opcode == D3DSIO_DEF) {
2163 TRACE("def c%lu = ", *pToken & 0xFF);
2166 TRACE("%f ,", *(float *)pToken);
2169 TRACE("%f ,", *(float *)pToken);
2172 TRACE("%f ,", *(float *)pToken);
2175 TRACE("%f", *(float *)pToken);
2179 TRACE("%s ", curOpcode->name);
2180 if (curOpcode->num_params > 0) {
2181 vshader_program_dump_vs_param(*pToken, 0);
2184 for (i = 1; i < curOpcode->num_params; ++i) {
2186 vshader_program_dump_vs_param(*pToken, 1);
2195 This->functionLength = (len + 1) * sizeof(DWORD);
2197 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2200 /* Generate HW shader in needed */
2201 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2203 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2207 /* copy the function ... because it will certainly be released by application */
2208 if (NULL != pFunction) {
2209 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2210 memcpy((void *)This->function, pFunction, This->functionLength);
2212 This->function = NULL;
2217 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2219 /*** IUnknown methods ***/
2220 IWineD3DVertexShaderImpl_QueryInterface,
2221 IWineD3DVertexShaderImpl_AddRef,
2222 IWineD3DVertexShaderImpl_Release,
2223 /*** IWineD3DVertexShader methods ***/
2224 IWineD3DVertexShaderImpl_GetParent,
2225 IWineD3DVertexShaderImpl_GetDevice,
2226 IWineD3DVertexShaderImpl_GetFunction,
2227 IWineD3DVertexShaderImpl_SetFunction