Fixed installation rules for Wine-specific IDL files.
[wine/testsucceed.git] / dlls / wined3d / vertexshader.c
blob0006846bf1241a2a9f403d99f676a3b875049c7d
1 /*
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
23 #include "config.h"
25 #include <math.h>
26 #include <stdio.h>
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
35 vertex shaders */
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)
39 #else
40 # define VSTRACE(A)
41 # define TRACE_VSVECTOR(name)
42 #endif
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
46 /**
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
50 * Exploring D3DX
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
56 * Dx9 New
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
59 * Dx9 Shaders
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
65 * Dx9 D3DX
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
68 * FVF
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 {
84 unsigned int opcode;
85 const char* name;
86 const char* glname;
87 CONST UINT num_params;
88 shader_fct_t soft_fct;
89 DWORD min_version;
90 DWORD max_version;
91 } SHADER_OPCODE;
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) {
121 d->x = 1.0f;
122 d->y = s0->y * s1->y;
123 d->z = s0->z;
124 d->w = s1->w;
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) {
130 union {
131 float f;
132 DWORD d;
133 } tmp;
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;
140 d->z = tmp.f;
141 d->w = 1.0f;
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) {
147 d->x = 1.0f;
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;
150 d->w = 1.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) {
190 d->x = s0->x;
191 d->y = s0->y;
192 d->z = s0->z;
193 d->w = s0->w;
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);
272 d->z = 0.0f;
273 d->w = 1.0f;
274 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
275 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
278 typedef FLOAT D3DMATRIX44[4][4];
279 typedef FLOAT D3DMATRIX43[4][3];
280 typedef FLOAT D3DMATRIX34[4][4];
281 typedef FLOAT D3DMATRIX33[4][3];
282 typedef FLOAT D3DMATRIX32[4][2];
284 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
286 * Buggy CODE: here only if cast not work for copy/paste
287 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
288 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
289 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
290 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
291 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
292 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
293 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
295 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
298 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
299 VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
300 VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
301 VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
302 VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
305 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
307 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
308 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
309 d->w = 1.0f;
310 VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
311 VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
312 VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
313 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
316 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[2][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
320 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
321 VSTRACE(("executing m3x4(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
322 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
324 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
327 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
328 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[2][2] * s0->z;
329 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[2][2] * s0->z;
330 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
331 d->w = 1.0f;
332 VSTRACE(("executing m3x3(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
333 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
334 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
335 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
338 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX32 mat) {
339 FIXME("check\n");
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;
342 d->z = 0.0f;
343 d->w = 1.0f;
347 * Version 2.0 specific
349 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
350 d->x = s0->x * (s1->x - s2->x) + s2->x;
351 d->y = s0->y * (s1->y - s2->y) + s2->y;
352 d->z = s0->z * (s1->z - s2->z) + s2->z;
353 d->w = s0->w * (s1->w - s2->w) + s2->x;
356 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
357 d->x = s0->y * s1->z - s0->z * s1->y;
358 d->y = s0->z * s1->x - s0->x * s1->z;
359 d->z = s0->x * s1->y - s0->y * s1->x;
360 d->w = 0.9f; /* w is undefined, so set it to something safeish */
362 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
363 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
366 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
368 d->x = fabsf(s0->x);
369 d->y = fabsf(s0->y);
370 d->z = fabsf(s0->z);
371 d->w = fabsf(s0->w);
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));
376 /* Stubs */
377 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
378 FIXME(" : Stub\n");
381 void vshader_texkill(WINED3DSHADERVECTOR* d) {
382 FIXME(" : Stub\n");
385 void vshader_tex(WINED3DSHADERVECTOR* d) {
386 FIXME(" : Stub\n");
388 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
389 FIXME(" : Stub\n");
392 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393 FIXME(" : Stub\n");
396 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
397 FIXME(" : Stub\n");
400 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401 FIXME(" : Stub\n");
404 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405 FIXME(" : Stub\n");
408 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409 FIXME(" : Stub\n");
412 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
413 FIXME(" : Stub\n");
416 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
417 FIXME(" : Stub\n");
420 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421 FIXME(" : Stub\n");
424 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
425 FIXME(" : Stub\n");
428 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
429 FIXME(" : Stub\n");
432 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
433 FIXME(" : Stub\n");
436 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
437 FIXME(" : Stub\n");
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) {
442 FIXME(" : Stub\n");
445 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
446 FIXME(" : Stub\n");
449 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
450 FIXME(" : Stub\n");
453 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
454 FIXME(" : Stub\n");
457 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
458 FIXME(" : Stub\n");
461 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
462 FIXME(" : Stub\n");
465 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
466 FIXME(" : Stub\n");
469 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
470 FIXME(" : Stub\n");
473 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
474 FIXME(" : Stub\n");
477 void vshader_call(WINED3DSHADERVECTOR* d) {
478 FIXME(" : Stub\n");
481 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
482 FIXME(" : Stub\n");
485 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486 FIXME(" : Stub\n");
489 void vshader_ret(WINED3DSHADERVECTOR* d) {
490 FIXME(" : Stub\n");
493 void vshader_endloop(WINED3DSHADERVECTOR* d) {
494 FIXME(" : Stub\n");
497 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
498 FIXME(" : Stub\n");
501 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
502 FIXME(" : Stub\n");
505 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
506 FIXME(" : Stub\n");
509 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
510 FIXME(" : Stub\n");
513 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514 FIXME(" : Stub\n");
517 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
518 FIXME(" : Stub\n");
521 void vshader_endrep(void) {
522 FIXME(" : Stub\n");
525 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
526 FIXME(" : Stub\n");
529 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
530 FIXME(" : Stub\n");
533 void vshader_else(WINED3DSHADERVECTOR* d) {
534 FIXME(" : Stub\n");
537 void vshader_label(WINED3DSHADERVECTOR* d) {
538 FIXME(" : Stub\n");
541 void vshader_endif(WINED3DSHADERVECTOR* d) {
542 FIXME(" : Stub\n");
545 void vshader_break(WINED3DSHADERVECTOR* d) {
546 FIXME(" : Stub\n");
549 void vshader_breakc(WINED3DSHADERVECTOR* d) {
550 FIXME(" : Stub\n");
553 void vshader_mova(WINED3DSHADERVECTOR* d) {
554 FIXME(" : Stub\n");
557 void vshader_defb(WINED3DSHADERVECTOR* d) {
558 FIXME(" : Stub\n");
561 void vshader_defi(WINED3DSHADERVECTOR* d) {
562 FIXME(" : Stub\n");
565 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
566 FIXME(" : Stub\n");
569 void vshader_dsx(WINED3DSHADERVECTOR* d) {
570 FIXME(" : Stub\n");
573 void vshader_dsy(WINED3DSHADERVECTOR* d) {
574 FIXME(" : Stub\n");
577 void vshader_texldd(WINED3DSHADERVECTOR* d) {
578 FIXME(" : Stub\n");
581 void vshader_setp(WINED3DSHADERVECTOR* d) {
582 FIXME(" : Stub\n");
585 void vshader_texldl(WINED3DSHADERVECTOR* d) {
586 FIXME(" : Stub\n");
589 void vshader_breakp(WINED3DSHADERVECTOR* d) {
590 FIXME(" : Stub\n");
595 * log, exp, frc, m*x* seems to be macros ins ... to see
597 static CONST SHADER_OPCODE vshader_ins [] = {
598 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, 0, 0},
599 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, 0, 0},
600 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, 0, 0},
601 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, 0, 0},
602 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, 0, 0},
603 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, 0, 0},
604 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, 0, 0},
605 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, 0, 0},
606 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, 0, 0},
607 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, 0, 0},
608 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, 0, 0},
609 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, 0, 0},
610 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, 0, 0},
611 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, 0, 0},
612 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, 0, 0},
613 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, 0, 0},
614 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, 0, 0},
615 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, 0, 0},
616 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, 0, 0},
617 {D3DSIO_LRP, "lrp", "LRP", 5, vshader_lrp, 0, 0},
618 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, 0, 0},
619 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
620 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
621 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
622 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
623 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
624 /** FIXME: use direct access so add the others opcodes as stubs */
625 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
626 They can be easly managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
627 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, 0, 0},
628 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, 0, 0},
629 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, 0, 0},
630 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, 0, 0},
631 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, 0, 0},
632 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, 0, 0},
633 /* DCL is a specil operation */
634 {D3DSIO_DCL, "dcl", NULL, 1, vshader_dcl, 0, 0},
635 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, 0, 0},
636 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, 0, 0},
637 /* TODO: sng can possibly be performed as
638 RCP tmp, vec
639 MUL out, tmp, vec*/
640 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, 0, 0},
641 /* TODO: xyz normalise can be performed is VS_ARB using one tempory register,
642 DP3 tmp , vec, vec;
643 RSQ tmp, tmp.x;
644 MUL vec.xyz, vec, tmp;
645 but I think this is better because it accounts for w properly.
646 DP3 tmp , vec, vec;
647 RSQ tmp, tmp.x;
648 MUL vec, vec, tmp;
651 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, 0, 0},
652 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, 0, 0},
653 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 2, vshader_rep, 0, 0},
654 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, 0, 0},
655 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 2, vshader_if, 0, 0},
656 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, 0, 0},
657 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 2, vshader_else, 0, 0},
658 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 2, vshader_endif, 0, 0},
659 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 2, vshader_break, 0, 0},
660 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, 0, 0},
661 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, 0, 0},
662 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, 0, 0},
663 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, 0, 0},
665 {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL, 1, vshader_texcoord, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXCOORD, "texcrd", GLNAME_REQUIRE_GLSL, 2, vshader_texcoord, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
667 {D3DSIO_TEXKILL, "texkill", GLNAME_REQUIRE_GLSL, 1, vshader_texkill, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
668 {D3DSIO_TEX, "tex", GLNAME_REQUIRE_GLSL, 1, vshader_tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
669 {D3DSIO_TEX, "texld", GLNAME_REQUIRE_GLSL, 2, vshader_texld, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
670 {D3DSIO_TEXBEM, "texbem", GLNAME_REQUIRE_GLSL, 2, vshader_texbem, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
671 {D3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 2, vshader_texbeml, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
672 {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2ar, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
673 {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2gb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXM3x2PAD, "texm3x2pad", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2pad, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2TEX, "texm3x2tex", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3diff, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
677 {D3DSIO_TEXM3x3SPEC, "texm3x3spec", GLNAME_REQUIRE_GLSL, 3, vshader_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
680 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, 0, 0},
681 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, 0, 0},
682 {D3DSIO_CND, "cnd", GLNAME_REQUIRE_GLSL, 4, vshader_cnd, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
683 /* def is a special opperation */
684 {D3DSIO_DEF, "def", NULL, 5, vshader_def, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
685 {D3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 2, vshader_texreg2rgb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
686 {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
687 {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
688 {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
689 {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
690 {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
691 {D3DSIO_CMP, "cmp", GLNAME_REQUIRE_GLSL, 4, vshader_cmp, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
692 {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 3, vshader_bem, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
693 /* TODO: dp2add can be made out of multiple instuctions */
694 {D3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 2, vshader_dp2add, 0, 0},
695 {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 2, vshader_dsx, 0, 0},
696 {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 2, vshader_dsy, 0, 0},
697 {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 2, vshader_texldd, 0, 0},
698 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, 0, 0},
699 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, 0, 0},
700 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 2, vshader_breakp, 0, 0},
701 {D3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, vshader_nop, 0, 0},
702 {0, NULL, NULL, 0, NULL, 0, 0}
706 inline static const SHADER_OPCODE* vshader_program_get_opcode(const DWORD code) {
707 DWORD i = 0;
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];
713 ++i;
715 FIXME("Unsupported opcode %lx\n",code);
716 return NULL;
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("-");
728 switch (regtype) {
729 case D3DSPR_TEMP:
730 TRACE("R[%lu]", reg);
731 break;
732 case D3DSPR_INPUT:
733 TRACE("v%lu", reg);
734 break;
735 case D3DSPR_CONST:
736 TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
737 break;
738 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
739 TRACE("a[%lu]", reg);
740 break;
741 case D3DSPR_RASTOUT:
742 TRACE("%s", rastout_reg_names[reg]);
743 break;
744 case D3DSPR_ATTROUT:
745 TRACE("oD[%lu]", reg);
746 break;
747 case D3DSPR_TEXCRDOUT:
748 TRACE("oT[%lu]", reg);
749 break;
750 default:
751 FIXME("Unknown %lu %u reg %lu\n",regtype, D3DSPR_ATTROUT, reg);
752 break;
755 if (!input) {
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");
763 } else {
764 /** operand input */
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:
772 * WWZZYYXX
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]);
779 } else {
780 TRACE(".%c%c%c%c",
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*/) {
809 case D3DSPR_TEMP:
810 TRACE("r%lu", reg);
811 break;
812 case D3DSPR_INPUT:
813 TRACE("v%lu", reg);
814 break;
815 case D3DSPR_CONST:
816 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
817 break;
818 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
819 TRACE("a%lu", reg);
820 break;
821 case D3DSPR_RASTOUT:
822 TRACE("%s", rastout_reg_names[reg]);
823 break;
824 case D3DSPR_ATTROUT:
825 TRACE("oD%lu", reg);
826 break;
827 case D3DSPR_TEXCRDOUT:
828 TRACE("oT%lu", reg);
829 break;
830 case D3DSPR_CONSTINT:
831 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
832 break;
833 case D3DSPR_CONSTBOOL:
834 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
835 break;
836 case D3DSPR_LABEL:
837 TRACE("l%lu", reg);
838 break;
839 case D3DSPR_LOOP:
840 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
841 break;
842 default:
843 FIXME("Unknown %lu reg %lu\n",regtype, reg);
844 break;
847 if (!input) {
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");
855 } else {
856 /** operand input */
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:
864 * WWZZYYXX
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]);
871 } else {
872 TRACE(".%c%c%c%c",
873 swizzle_reg_chars[swizzle_x],
874 swizzle_reg_chars[swizzle_y],
875 swizzle_reg_chars[swizzle_z],
876 swizzle_reg_chars[swizzle_w]);
882 inline static BOOL vshader_is_version_token(DWORD token) {
883 return 0xFFFE0000 == (token & 0xFFFE0000);
886 inline static BOOL vshader_is_comment_token(DWORD token) {
887 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
890 inline static void vshader_program_add_param(const DWORD param, int input, char *hwLine, BOOL namedArrays, CHAR constantsUsedBitmap[]) {
891 /*static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" }; */
892 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
893 static const char swizzle_reg_chars[] = "xyzw";
895 DWORD reg = param & 0x00001FFF;
896 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
897 char tmpReg[255];
899 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
900 strcat(hwLine, " -");
901 } else {
902 strcat(hwLine, " ");
905 switch (regtype) {
906 case D3DSPR_TEMP:
907 sprintf(tmpReg, "T%lu", reg);
908 strcat(hwLine, tmpReg);
909 break;
910 case D3DSPR_INPUT:
911 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
912 if (namedArrays) {
913 sprintf(tmpReg, "namedVertex%lu", reg);
914 } else {
915 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
916 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
918 strcat(hwLine, tmpReg);
919 break;
920 case D3DSPR_CONST:
921 /* FIXME: some constants are named so we need a constants map*/
922 if (constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
923 if (param & D3DVS_ADDRMODE_RELATIVE) {
924 FIXME("Relitive addressing not expected for a named constant %lu\n", reg);
926 sprintf(tmpReg, "const%lu", reg);
927 } else {
928 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
930 strcat(hwLine, tmpReg);
931 break;
932 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
933 sprintf(tmpReg, "A%lu", reg);
934 strcat(hwLine, tmpReg);
935 break;
936 case D3DSPR_RASTOUT:
937 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
938 strcat(hwLine, tmpReg);
939 break;
940 case D3DSPR_ATTROUT:
941 if (reg==0) {
942 strcat(hwLine, "result.color.primary");
943 } else {
944 strcat(hwLine, "result.color.secondary");
946 break;
947 case D3DSPR_TEXCRDOUT:
948 sprintf(tmpReg, "result.texcoord[%lu]", reg);
949 strcat(hwLine, tmpReg);
950 break;
951 default:
952 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
953 break;
956 if (!input) {
957 /** operand output */
958 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
959 strcat(hwLine, ".");
960 if (param & D3DSP_WRITEMASK_0) {
961 strcat(hwLine, "x");
963 if (param & D3DSP_WRITEMASK_1) {
964 strcat(hwLine, "y");
966 if (param & D3DSP_WRITEMASK_2) {
967 strcat(hwLine, "z");
969 if (param & D3DSP_WRITEMASK_3) {
970 strcat(hwLine, "w");
973 } else {
974 /** operand input */
975 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
976 DWORD swizzle_x = swizzle & 0x03;
977 DWORD swizzle_y = (swizzle >> 2) & 0x03;
978 DWORD swizzle_z = (swizzle >> 4) & 0x03;
979 DWORD swizzle_w = (swizzle >> 6) & 0x03;
981 * swizzle bits fields:
982 * WWZZYYXX
984 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
985 if (swizzle_x == swizzle_y &&
986 swizzle_x == swizzle_z &&
987 swizzle_x == swizzle_w)
989 sprintf(tmpReg, ".%c", swizzle_reg_chars[swizzle_x]);
990 strcat(hwLine, tmpReg);
991 } else {
992 sprintf(tmpReg, ".%c%c%c%c",
993 swizzle_reg_chars[swizzle_x],
994 swizzle_reg_chars[swizzle_y],
995 swizzle_reg_chars[swizzle_z],
996 swizzle_reg_chars[swizzle_w]);
997 strcat(hwLine, tmpReg);
1003 DWORD MacroExpansion[4*4];
1005 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1006 int i;
1007 int nComponents = 0;
1008 DWORD opcode =0;
1009 switch(macro_opcode) {
1010 case D3DSIO_M4x4:
1011 nComponents = 4;
1012 opcode = D3DSIO_DP4;
1013 break;
1014 case D3DSIO_M4x3:
1015 nComponents = 3;
1016 opcode = D3DSIO_DP4;
1017 break;
1018 case D3DSIO_M3x4:
1019 nComponents = 4;
1020 opcode = D3DSIO_DP3;
1021 break;
1022 case D3DSIO_M3x3:
1023 nComponents = 3;
1024 opcode = D3DSIO_DP3;
1025 break;
1026 case D3DSIO_M3x2:
1027 nComponents = 2;
1028 opcode = D3DSIO_DP3;
1029 break;
1030 default:
1031 break;
1033 for (i = 0; i < nComponents; i++) {
1034 MacroExpansion[i*4+0] = opcode;
1035 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1036 MacroExpansion[i*4+2] = *(args+1);
1037 MacroExpansion[i*4+3] = (*(args+2))+i;
1039 return nComponents;
1043 * Function parser ...
1046 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1047 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1048 const DWORD* pToken = pFunction;
1049 const DWORD* pSavedToken = NULL;
1050 const SHADER_OPCODE* curOpcode = NULL;
1051 int nRemInstr = -1;
1052 DWORD i;
1053 unsigned lineNum = 0;
1054 char *pgmStr = NULL;
1055 char tmpLine[255];
1056 DWORD nUseAddressRegister = 0;
1057 DWORD nUseTempRegister = 0;
1058 DWORD regtype;
1059 DWORD reg;
1060 BOOL tmpsUsed[32];
1061 #if 0 /* TODO: loope register (just another address register ) */
1062 BOOL hasLoops = FALSE;
1063 #endif
1065 #define PGMSIZE 65535
1066 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1067 int pgmLength = 0;
1069 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1070 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occure... */
1071 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1072 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1073 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1074 This->fixupVertexBufferSize = PGMSIZE;
1075 This->fixupVertexBuffer[0] = 0;
1077 pgmStr = This->device->fixupVertexBuffer;
1078 #endif
1079 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1080 int _tmpLineLen = strlen(_tmpLine); \
1081 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1082 ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1083 } else { \
1084 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1086 pgmLength += _tmpLineLen; \
1089 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1090 /* Initilise the shader */
1091 This->namedArrays = FALSE;
1092 This->declaredArrays = FALSE;
1093 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1094 This->arrayUsageMap[i] = -1;
1096 /* set all the tmpsUsed to not used */
1097 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1099 /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1100 This->highestConstant = -1;
1104 * First pass to determine what we need to declare:
1105 * - Temporary variables
1106 * - Address variables
1108 if (NULL != pToken) {
1109 while (D3DVS_END() != *pToken) {
1110 if (vshader_is_version_token(*pToken)) {
1111 /** skip version */
1112 ++pToken;
1113 continue;
1115 if (vshader_is_comment_token(*pToken)) { /** comment */
1116 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1117 ++pToken;
1118 pToken += comment_len;
1119 continue;
1121 curOpcode = vshader_program_get_opcode(*pToken);
1122 ++pToken;
1123 /* TODO: dcl's */
1124 /* TODO: Consts */
1126 if (NULL == curOpcode) {
1127 while (*pToken & 0x80000000) {
1128 TRACE("unrecognized opcode: %08lx\n", *pToken);
1129 /* skip unrecognized opcode */
1130 ++pToken;
1132 } else {
1133 if (curOpcode->opcode == D3DSIO_DCL){
1134 INT usage = *pToken++;
1135 INT arrayNo = (*pToken++ & 0x00001FFF);
1136 switch(usage & 0xFFFF) {
1137 case D3DDECLUSAGE_POSITION:
1138 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1139 TRACE("Setting position to %d\n", arrayNo);
1140 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1141 This->namedArrays = TRUE;
1142 } else {
1143 /* TODO: position indexes go fro 0-8!!*/
1144 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1145 /* robots uses positions upto 8, the position arrays are just packed.*/
1146 if ((usage & 0xF0000) >> 16 > 1) {
1147 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1149 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1150 This->declaredArrays = TRUE;
1152 break;
1153 case D3DDECLUSAGE_BLENDINDICES:
1154 /* not supported by openGL */
1155 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1156 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1157 This->declaredArrays = TRUE;
1158 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1159 break;
1160 case D3DDECLUSAGE_BLENDWEIGHT:
1161 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1162 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1163 This->namedArrays = TRUE;
1164 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1165 break;
1166 case D3DDECLUSAGE_NORMAL:
1167 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1168 TRACE("Setting normal to %d\n", arrayNo);
1169 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1170 This->namedArrays = TRUE;
1171 } else {
1172 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1173 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1174 This->declaredArrays = TRUE;
1176 break;
1177 case D3DDECLUSAGE_PSIZE:
1178 TRACE("Setting PSIZE to %d\n", arrayNo);
1179 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1180 This->namedArrays = TRUE;
1181 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1182 break;
1183 case D3DDECLUSAGE_COLOR:
1184 if((usage & 0xF0000) >> 16 == 0) {
1185 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1186 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1187 This->namedArrays = TRUE;
1188 } else {
1189 TRACE("Setting SPECULAR to %d\n", arrayNo);
1190 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1191 This->namedArrays = TRUE;
1193 break;
1194 case D3DDECLUSAGE_TEXCOORD:
1195 This->namedArrays = TRUE;
1196 /* only 7 texture coords have been designed for, so run a quick sanity check */
1197 if ((usage & 0xF0000) >> 16 > 7) {
1198 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1199 } else {
1200 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1201 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1203 break;
1204 /* The following aren't supported by openGL,
1205 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1206 this should be caught in the first pass */
1207 case D3DDECLUSAGE_TANGENT:
1208 TRACE("Setting TANGENT to %d\n", arrayNo);
1209 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1210 This->declaredArrays = TRUE;
1211 break;
1212 case D3DDECLUSAGE_BINORMAL:
1213 TRACE("Setting BINORMAL to %d\n", arrayNo);
1214 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1215 This->declaredArrays = TRUE;
1216 break;
1217 case D3DDECLUSAGE_TESSFACTOR:
1218 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1219 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1220 This->declaredArrays = TRUE;
1221 break;
1222 case D3DDECLUSAGE_POSITIONT:
1223 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1224 FIXME("Setting positiont to %d\n", arrayNo);
1225 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1226 This->namedArrays = TRUE;
1227 } else {
1228 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1229 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1230 This->declaredArrays = TRUE;
1231 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1233 break;
1234 case D3DDECLUSAGE_FOG:
1235 /* supported by OpenGL */
1236 TRACE("Setting FOG to %d\n", arrayNo);
1237 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1238 This->namedArrays = TRUE;
1239 break;
1240 case D3DDECLUSAGE_DEPTH:
1241 TRACE("Setting DEPTH to %d\n", arrayNo);
1242 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1243 This->declaredArrays = TRUE;
1244 break;
1245 case D3DDECLUSAGE_SAMPLE:
1246 TRACE("Setting SAMPLE to %d\n", arrayNo);
1247 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1248 This->declaredArrays = TRUE;
1249 break;
1250 default:
1251 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1253 } else if(curOpcode->opcode == D3DSIO_DEF) {
1254 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1255 FIXME("Constant %ld\n", *pToken & 0xFF);
1256 ++pToken;
1257 ++pToken;
1258 ++pToken;
1259 ++pToken;
1260 ++pToken;
1262 } else {
1263 /* Check to see if and tmp or addressing redisters are used */
1264 if (curOpcode->num_params > 0) {
1265 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1266 reg = ((*pToken) & 0x00001FFF);
1267 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1268 if (D3DSPR_TEMP == regtype){
1269 tmpsUsed[reg] = TRUE;
1270 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1272 ++pToken;
1273 for (i = 1; i < curOpcode->num_params; ++i) {
1274 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1275 reg = ((*pToken) & 0x00001FFF);
1276 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1277 if (D3DSPR_TEMP == regtype){
1278 tmpsUsed[reg] = TRUE;
1279 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1281 ++pToken;
1285 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1286 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1287 FIXME("This shader requires gl shader language support\n");
1288 #if 0
1289 This->shaderLanguage = GLSHADER_GLSL;
1290 #endif
1292 #endif
1296 #if 1
1297 #define VSHADER_ALWAYS_NUMBERED
1298 #endif
1300 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1301 /* TODO: using numbered arrays for software shaders makes things easier */
1302 This->declaredArrays = TRUE;
1303 #endif
1305 /* named arrays and declared arrays are mutually exclusive */
1306 if (This->declaredArrays) {
1307 This->namedArrays = FALSE;
1309 /* TODO: validate
1310 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1311 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1314 /** second pass, now generate */
1315 pToken = pFunction;
1317 if (NULL != pToken) {
1318 while (1) {
1319 tmpLine[0] = 0;
1320 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1321 /* Macro is finished, continue normal path */
1322 pToken = pSavedToken;
1323 if (D3DVS_END() == *pToken)
1324 break;
1326 if (vshader_is_version_token(*pToken)) { /** version */
1327 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1328 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1329 int numTemps;
1330 int numConstants;
1332 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1334 /* Each release of vertex shaders has had different numbers of temp registers */
1335 switch (version) {
1336 case 10:
1337 case 11: numTemps=12;
1338 numConstants=96;/* min(GL_LIMITS(constants),96) */
1339 strcpy(tmpLine, "!!ARBvp1.0\n");
1340 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1341 break;
1342 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1343 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1344 TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1345 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1346 numConstants=96; /* min(GL_LIMITS(constants),256) */
1347 strcpy(tmpLine, "!!ARBvp1.0\n");
1348 FIXME("No work done yet to support vs2.0 in hw\n");
1349 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1350 break;
1351 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1352 numConstants=96; /* min(GL_LIMITS(constants),256) */
1353 strcpy(tmpLine, "!!ARBvp1.0\n");
1354 FIXME("No work done yet to support vs2.1 in hw\n");
1355 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1356 break;
1357 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1358 numConstants=96;/* min(GL_LIMITS(constants),256) */
1359 strcpy(tmpLine, "!!ARBvp3.0\n");
1360 FIXME("No work done yet to support vs3.0 in hw\n");
1361 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1362 break;
1363 default:
1364 numTemps=12;/* min(GL_LIMITS(temps),12) */
1365 numConstants=96;/* min(GL_LIMITS(constants),96) */
1366 strcpy(tmpLine, "!!ARBvp1.0\n");
1367 FIXME("Unrecognized vertex shader version %d!\n", version);
1369 PNSTRCAT(pgmStr, tmpLine);
1371 ++lineNum;
1373 /* This should be a bitmap so that only temp registers that are used are declared. */
1374 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1375 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1376 sprintf(tmpLine, "TEMP T%ld;\n", i);
1377 ++lineNum;
1378 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1379 PNSTRCAT(pgmStr, tmpLine);
1383 /* TODO: loop register counts as an addres register */
1384 for (i = 0; i < nUseAddressRegister; i++) {
1385 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1386 ++lineNum;
1387 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1388 PNSTRCAT(pgmStr, tmpLine);
1391 /* Due to the dynamic constants binding mechanism, we need to declare
1392 * all the constants for relative addressing. */
1393 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1394 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1395 numConstants = 95;
1397 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1398 Looking at some of the shaders inuse by applications we'd need to create a list of all used env variables
1400 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1401 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1402 PNSTRCAT(pgmStr, tmpLine);
1404 ++lineNum;
1406 ++pToken;
1407 continue;
1409 if (vshader_is_comment_token(*pToken)) { /** comment */
1410 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1411 ++pToken;
1412 FIXME("#%s\n", (char*)pToken);
1413 pToken += comment_len;
1414 continue;
1417 curOpcode = vshader_program_get_opcode(*pToken);
1418 ++pToken;
1419 if (NULL == curOpcode) {
1420 /* unkown current opcode ... (shouldn't be any!) */
1421 while (*pToken & 0x80000000) {
1422 TRACE("unrecognized opcode: %08lx\n", *pToken);
1423 ++pToken;
1425 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1426 /* if the token isn't supported by this cross compiler then skip it and it's parameters */
1428 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1429 pToken += curOpcode->num_params;
1430 } else {
1431 /* Build opcode for GL vertex_program */
1432 switch (curOpcode->opcode) {
1433 case D3DSIO_NOP:
1434 continue;
1435 case D3DSIO_MOV:
1436 /* Address registers must be loaded with the ARL instruction */
1437 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1438 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1439 strcpy(tmpLine, "ARL");
1440 break;
1441 } else
1442 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1444 /* fall through */
1445 case D3DSIO_ADD:
1446 case D3DSIO_SUB:
1447 case D3DSIO_MAD:
1448 case D3DSIO_MUL:
1449 case D3DSIO_RCP:
1450 case D3DSIO_RSQ:
1451 case D3DSIO_DP3:
1452 case D3DSIO_DP4:
1453 case D3DSIO_MIN:
1454 case D3DSIO_MAX:
1455 case D3DSIO_SLT:
1456 case D3DSIO_SGE:
1457 case D3DSIO_LIT:
1458 case D3DSIO_DST:
1459 case D3DSIO_FRC:
1460 case D3DSIO_EXPP:
1461 case D3DSIO_LOGP:
1462 case D3DSIO_EXP:
1463 case D3DSIO_LOG:
1464 strcpy(tmpLine, curOpcode->glname);
1465 break;
1466 case D3DSIO_M4x4:
1467 case D3DSIO_M4x3:
1468 case D3DSIO_M3x4:
1469 case D3DSIO_M3x3:
1470 case D3DSIO_M3x2:
1471 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1472 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1473 /* Save point to next instruction */
1474 pSavedToken = pToken + 3;
1475 /* Execute expanded macro */
1476 pToken = MacroExpansion;
1477 continue;
1478 /* dcl and def are handeled in the first pass */
1479 case D3DSIO_DCL:
1480 if (This->namedArrays) {
1481 const char* attribName = "undefined";
1482 switch(*pToken & 0xFFFF) {
1483 case D3DDECLUSAGE_POSITION:
1484 attribName = "vertex.position";
1485 break;
1486 case D3DDECLUSAGE_BLENDINDICES:
1487 /* not supported by openGL */
1488 attribName = "vertex.blend";
1489 break;
1490 case D3DDECLUSAGE_BLENDWEIGHT:
1491 attribName = "vertex.weight";
1492 break;
1493 case D3DDECLUSAGE_NORMAL:
1494 attribName = "vertex.normal";
1495 break;
1496 case D3DDECLUSAGE_PSIZE:
1497 attribName = "vertex.psize";
1498 break;
1499 case D3DDECLUSAGE_COLOR:
1500 if((*pToken & 0xF0000) >> 16 == 0) {
1501 attribName = "vertex.color";
1502 } else {
1503 attribName = "vertex.color.secondary";
1505 break;
1506 case D3DDECLUSAGE_TEXCOORD:
1508 char tmpChar[100];
1509 tmpChar[0] = 0;
1510 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1511 attribName = tmpChar;
1512 break;
1514 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1515 case D3DDECLUSAGE_TANGENT:
1516 attribName = "vertex.tangent";
1517 break;
1518 case D3DDECLUSAGE_BINORMAL:
1519 attribName = "vertex.binormal";
1520 break;
1521 case D3DDECLUSAGE_TESSFACTOR:
1522 attribName = "vertex.tessfactor";
1523 break;
1524 case D3DDECLUSAGE_POSITIONT:
1525 attribName = "vertex.possitionT";
1526 break;
1527 case D3DDECLUSAGE_FOG:
1528 attribName = "vertex.fogcoord";
1529 break;
1530 case D3DDECLUSAGE_DEPTH:
1531 attribName = "vertex.depth";
1532 break;
1533 case D3DDECLUSAGE_SAMPLE:
1534 attribName = "vertex.sample";
1535 break;
1536 default:
1537 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1540 char tmpChar[80];
1541 ++pToken;
1542 sprintf(tmpLine, "ATTRIB ");
1543 vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1544 sprintf(tmpChar," = %s", attribName);
1545 strcat(tmpLine, tmpChar);
1546 strcat(tmpLine,";\n");
1547 ++lineNum;
1548 if (This->namedArrays) {
1549 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1550 PNSTRCAT(pgmStr, tmpLine);
1552 } else {
1553 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1556 } else {
1557 /* eat the token so it doesn't generate a warning */
1558 ++pToken;
1560 ++pToken;
1561 continue;
1562 case D3DSIO_DEF:
1564 char tmpChar[80];
1565 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1566 ++pToken;
1567 sprintf(tmpChar,"%f ,", *(float *)pToken);
1568 strcat(tmpLine, tmpChar);
1569 ++pToken;
1570 sprintf(tmpChar,"%f ,", *(float *)pToken);
1571 strcat(tmpLine, tmpChar);
1572 ++pToken;
1573 sprintf(tmpChar,"%f ,", *(float *)pToken);
1574 strcat(tmpLine, tmpChar);
1575 ++pToken;
1576 sprintf(tmpChar,"%f}", *(float *)pToken);
1577 strcat(tmpLine, tmpChar);
1579 strcat(tmpLine,";\n");
1580 ++lineNum;
1581 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1582 PNSTRCAT(pgmStr, tmpLine);
1584 ++pToken;
1585 continue;
1587 default:
1588 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1589 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1590 } else {
1591 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1594 if (curOpcode->num_params > 0) {
1595 vshader_program_add_param(*pToken, 0, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1597 ++pToken;
1598 for (i = 1; i < curOpcode->num_params; ++i) {
1599 strcat(tmpLine, ",");
1600 vshader_program_add_param(*pToken, 1, tmpLine, This->namedArrays, This->constantsUsedBitmap);
1601 ++pToken;
1604 strcat(tmpLine,";\n");
1605 ++lineNum;
1606 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1607 PNSTRCAT(pgmStr, tmpLine);
1611 strcpy(tmpLine, "END\n");
1612 ++lineNum;
1613 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1614 PNSTRCAT(pgmStr, tmpLine);
1617 /* finally null terminate the pgmStr*/
1618 pgmStr[pgmLength] = 0;
1619 /* Create the hw shader */
1620 /* TODO: change to resource.glObjectHandel or something like that */
1621 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1622 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1624 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1627 /* Create the program and check for errors */
1628 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1629 if (glGetError() == GL_INVALID_OPERATION) {
1630 GLint errPos;
1631 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1632 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
1633 This->prgId = -1;
1635 #if 1 /* if were using the data buffer of device then we don't need to free it */
1636 HeapFree(GetProcessHeap(), 0, pgmStr);
1637 #endif
1638 #undef PNSTRCAT
1641 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1643 * TODO: use the NV_vertex_program (or 1_1) extension
1644 * and specifics vendors (ARB_vertex_program??) variants for it
1646 return TRUE;
1649 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1650 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1652 /** Vertex Shader Temporary Registers */
1653 WINED3DSHADERVECTOR R[12];
1654 /*D3DSHADERSCALAR A0;*/
1655 WINED3DSHADERVECTOR A[1];
1656 /** temporary Vector for modifier management */
1657 WINED3DSHADERVECTOR d;
1658 WINED3DSHADERVECTOR s[3];
1659 /** parser datas */
1660 const DWORD* pToken = This->function;
1661 const SHADER_OPCODE* curOpcode = NULL;
1662 /** functions parameters */
1663 WINED3DSHADERVECTOR* p[4];
1664 WINED3DSHADERVECTOR* p_send[4];
1665 DWORD i;
1667 /** init temporary register */
1668 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1670 /* vshader_program_parse(vshader); */
1671 #if 0 /* Must not be 1 in cvs */
1672 TRACE("Input:\n");
1673 TRACE_VSVECTOR(This->data->C[0]);
1674 TRACE_VSVECTOR(This->data->C[1]);
1675 TRACE_VSVECTOR(This->data->C[2]);
1676 TRACE_VSVECTOR(This->data->C[3]);
1677 TRACE_VSVECTOR(This->data->C[4]);
1678 TRACE_VSVECTOR(This->data->C[5]);
1679 TRACE_VSVECTOR(This->data->C[6]);
1680 TRACE_VSVECTOR(This->data->C[7]);
1681 TRACE_VSVECTOR(This->data->C[8]);
1682 TRACE_VSVECTOR(This->data->C[64]);
1683 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1684 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1685 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1686 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1687 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1688 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1689 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1690 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1691 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1692 #endif
1694 TRACE_VSVECTOR(vshader->data->C[64]);
1695 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1697 /* the first dword is the version tag */
1698 /* TODO: parse it */
1700 if (vshader_is_version_token(*pToken)) { /** version */
1701 ++pToken;
1703 while (D3DVS_END() != *pToken) {
1704 if (vshader_is_comment_token(*pToken)) { /** comment */
1705 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1706 ++pToken;
1707 pToken += comment_len;
1708 continue ;
1710 curOpcode = vshader_program_get_opcode(*pToken);
1711 ++pToken;
1712 if (NULL == curOpcode) {
1713 i = 0;
1714 /* unkown current opcode ... */
1715 /* TODO: Think of a name for 0x80000000 and repalce it's use with a constant */
1716 while (*pToken & 0x80000000) {
1717 if (i == 0) {
1718 TRACE("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1720 TRACE("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1721 vshader_program_dump_param(*pToken, i);
1722 TRACE("\n");
1723 ++i;
1724 ++pToken;
1726 /* return FALSE; */
1727 } else {
1728 if (curOpcode->num_params > 0) {
1729 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1730 for (i = 0; i < curOpcode->num_params; ++i) {
1731 DWORD reg = pToken[i] & 0x00001FFF;
1732 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1734 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1735 case D3DSPR_TEMP:
1736 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1737 p[i] = &R[reg];
1738 break;
1739 case D3DSPR_INPUT:
1740 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1741 p[i] = &input->V[reg];
1742 break;
1743 case D3DSPR_CONST:
1744 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1745 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1746 } else {
1747 p[i] = &This->data->C[reg];
1749 break;
1750 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1751 if (0 != reg) {
1752 ERR("cannot handle address registers != a0, forcing use of a0\n");
1753 reg = 0;
1755 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1756 p[i] = &A[reg];
1757 break;
1758 case D3DSPR_RASTOUT:
1759 switch (reg) {
1760 case D3DSRO_POSITION:
1761 p[i] = &output->oPos;
1762 break;
1763 case D3DSRO_FOG:
1764 p[i] = &output->oFog;
1765 break;
1766 case D3DSRO_POINT_SIZE:
1767 p[i] = &output->oPts;
1768 break;
1770 break;
1771 case D3DSPR_ATTROUT:
1772 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1773 p[i] = &output->oD[reg];
1774 break;
1775 case D3DSPR_TEXCRDOUT:
1776 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1777 p[i] = &output->oT[reg];
1778 break;
1779 /* TODO Decls and defs */
1780 #if 0
1781 case D3DSPR_DCL:
1782 case D3DSPR_DEF:
1783 #endif
1784 default:
1785 break;
1788 if (i > 0) { /* input reg */
1789 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1790 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1792 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1793 /* TRACE("p[%d] not swizzled\n", i); */
1794 p_send[i] = p[i];
1795 } else {
1796 DWORD swizzle_x = swizzle & 0x03;
1797 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1798 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1799 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1800 /* TRACE("p[%d] swizzled\n", i); */
1801 float* tt = (float*) p[i];
1802 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1803 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1804 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1805 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1806 p_send[i] = &s[i];
1808 } else { /* output reg */
1809 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1810 p_send[i] = p[i];
1811 } else {
1812 p_send[i] = &d; /* to be post-processed for modifiers management */
1818 switch (curOpcode->num_params) {
1819 case 0:
1820 curOpcode->soft_fct();
1821 break;
1822 case 1:
1823 curOpcode->soft_fct(p_send[0]);
1824 break;
1825 case 2:
1826 curOpcode->soft_fct(p_send[0], p_send[1]);
1827 break;
1828 case 3:
1829 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1830 break;
1831 case 4:
1832 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1833 break;
1834 case 5:
1835 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1836 break;
1837 case 6:
1838 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1839 break;
1840 default:
1841 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1844 /* check if output reg modifier post-process */
1845 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1846 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1847 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1848 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1849 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1851 #if 0
1852 TRACE_VSVECTOR(output->oPos);
1853 TRACE_VSVECTOR(output->oD[0]);
1854 TRACE_VSVECTOR(output->oD[1]);
1855 TRACE_VSVECTOR(output->oT[0]);
1856 TRACE_VSVECTOR(output->oT[1]);
1857 TRACE_VSVECTOR(R[0]);
1858 TRACE_VSVECTOR(R[1]);
1859 TRACE_VSVECTOR(R[2]);
1860 TRACE_VSVECTOR(R[3]);
1861 TRACE_VSVECTOR(R[4]);
1862 TRACE_VSVECTOR(R[5]);
1863 #endif
1865 /* to next opcode token */
1866 pToken += curOpcode->num_params;
1868 #if 0
1869 TRACE("End of current instruction:\n");
1870 TRACE_VSVECTOR(output->oPos);
1871 TRACE_VSVECTOR(output->oD[0]);
1872 TRACE_VSVECTOR(output->oD[1]);
1873 TRACE_VSVECTOR(output->oT[0]);
1874 TRACE_VSVECTOR(output->oT[1]);
1875 TRACE_VSVECTOR(R[0]);
1876 TRACE_VSVECTOR(R[1]);
1877 TRACE_VSVECTOR(R[2]);
1878 TRACE_VSVECTOR(R[3]);
1879 TRACE_VSVECTOR(R[4]);
1880 TRACE_VSVECTOR(R[5]);
1881 #endif
1883 #if 0 /* Must not be 1 in cvs */
1884 TRACE("Output:\n");
1885 TRACE_VSVECTOR(output->oPos);
1886 TRACE_VSVECTOR(output->oD[0]);
1887 TRACE_VSVECTOR(output->oD[1]);
1888 TRACE_VSVECTOR(output->oT[0]);
1889 TRACE_VSVECTOR(output->oT[1]);
1890 #endif
1891 return D3D_OK;
1894 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1895 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1896 FIXME("(%p) : stub\n", This);
1897 return D3D_OK;
1900 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1901 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1902 FIXME("(%p) : stub\n", This);
1903 return D3D_OK;
1906 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1907 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1908 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1909 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1910 return D3DERR_INVALIDCALL;
1912 if (NULL == pConstantData) {
1913 return D3DERR_INVALIDCALL;
1915 FIXME("(%p) : stub\n", This);
1916 return D3D_OK;
1919 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1920 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1921 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1922 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1923 return D3DERR_INVALIDCALL;
1925 if (NULL == pConstantData) {
1926 return D3DERR_INVALIDCALL;
1928 FIXME("(%p) : stub\n", This);
1929 return D3D_OK;
1932 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1933 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1934 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1935 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1936 return D3DERR_INVALIDCALL;
1938 if (NULL == pConstantData) {
1939 return D3DERR_INVALIDCALL;
1941 FIXME("(%p) : stub\n", This);
1942 return D3D_OK;
1945 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1946 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1947 FIXME("(%p) : stub\n", This);
1948 return D3D_OK;
1951 #endif
1953 /* *******************************************
1954 IWineD3DVertexShader IUnknown parts follow
1955 ******************************************* */
1956 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1958 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1959 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1960 if (IsEqualGUID(riid, &IID_IUnknown)
1961 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1962 IUnknown_AddRef(iface);
1963 *ppobj = This;
1964 return D3D_OK;
1966 return E_NOINTERFACE;
1969 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1970 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1971 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1972 return InterlockedIncrement(&This->ref);
1975 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1976 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1977 ULONG ref;
1978 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1979 ref = InterlockedDecrement(&This->ref);
1980 if (ref == 0) {
1981 HeapFree(GetProcessHeap(), 0, This);
1983 return ref;
1986 /* *******************************************
1987 IWineD3DVertexShader IWineD3DVertexShader parts follow
1988 ******************************************* */
1990 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1991 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1993 *parent = (IUnknown*)This->parent;
1994 IUnknown_AddRef(*parent);
1995 TRACE("(%p) : returning %p\n", This, *parent);
1996 return D3D_OK;
1999 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2000 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2001 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2002 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2003 TRACE("(%p) returning %p\n", This, *pDevice);
2004 return D3D_OK;
2007 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2008 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2009 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2011 if (NULL == pData) {
2012 *pSizeOfData = This->functionLength;
2013 return D3D_OK;
2015 if (*pSizeOfData < This->functionLength) {
2016 *pSizeOfData = This->functionLength;
2017 return D3DERR_MOREDATA;
2019 if (NULL == This->function) { /* no function defined */
2020 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2021 (*(DWORD **) pData) = NULL;
2022 } else {
2023 if(This->functionLength == 0){
2026 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2027 memcpy(pData, This->function, This->functionLength);
2029 return D3D_OK;
2032 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2033 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2034 const DWORD* pToken = pFunction;
2035 const SHADER_OPCODE* curOpcode = NULL;
2036 DWORD len = 0;
2037 DWORD i;
2038 TRACE("(%p) : Parsing programme\n", This);
2040 if (NULL != pToken) {
2041 while (D3DVS_END() != *pToken) {
2042 if (vshader_is_version_token(*pToken)) { /** version */
2043 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2044 ++pToken;
2045 ++len;
2046 continue;
2048 if (vshader_is_comment_token(*pToken)) { /** comment */
2049 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2050 ++pToken;
2051 TRACE("//%s\n", (char*)pToken);
2052 pToken += comment_len;
2053 len += comment_len + 1;
2054 continue;
2056 curOpcode = vshader_program_get_opcode(*pToken);
2057 ++pToken;
2058 ++len;
2059 if (NULL == curOpcode) {
2060 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2061 while (*pToken & 0x80000000) {
2062 /* unkown current opcode ... */
2063 TRACE("unrecognized opcode: %08lx", *pToken);
2064 ++pToken;
2065 ++len;
2066 TRACE("\n");
2069 } else {
2070 if (curOpcode->opcode == D3DSIO_DCL) {
2071 TRACE("dcl_");
2072 switch(*pToken & 0xFFFF) {
2073 case D3DDECLUSAGE_POSITION:
2074 TRACE("%s%ld ", "position",(*pToken & 0xF0000) >> 16);
2075 break;
2076 case D3DDECLUSAGE_BLENDINDICES:
2077 TRACE("%s ", "blend");
2078 break;
2079 case D3DDECLUSAGE_BLENDWEIGHT:
2080 TRACE("%s ", "weight");
2081 break;
2082 case D3DDECLUSAGE_NORMAL:
2083 TRACE("%s%ld ", "normal",(*pToken & 0xF0000) >> 16);
2084 break;
2085 case D3DDECLUSAGE_PSIZE:
2086 TRACE("%s ", "psize");
2087 break;
2088 case D3DDECLUSAGE_COLOR:
2089 if((*pToken & 0xF0000) >> 16 == 0) {
2090 TRACE("%s ", "color");
2091 } else {
2092 TRACE("%s ", "specular");
2094 break;
2095 case D3DDECLUSAGE_TEXCOORD:
2096 TRACE("%s%ld ", "texture", (*pToken & 0xF0000) >> 16);
2097 break;
2098 case D3DDECLUSAGE_TANGENT:
2099 TRACE("%s ", "tangent");
2100 break;
2101 case D3DDECLUSAGE_BINORMAL:
2102 TRACE("%s ", "binormal");
2103 break;
2104 case D3DDECLUSAGE_TESSFACTOR:
2105 TRACE("%s ", "tessfactor");
2106 break;
2107 case D3DDECLUSAGE_POSITIONT:
2108 TRACE("%s%ld ", "positionT",(*pToken & 0xF0000) >> 16);
2109 break;
2110 case D3DDECLUSAGE_FOG:
2111 TRACE("%s ", "fog");
2112 break;
2113 case D3DDECLUSAGE_DEPTH:
2114 TRACE("%s ", "depth");
2115 break;
2116 case D3DDECLUSAGE_SAMPLE:
2117 TRACE("%s ", "sample");
2118 break;
2119 default:
2120 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
2122 ++pToken;
2123 ++len;
2124 vshader_program_dump_vs_param(*pToken, 0);
2125 ++pToken;
2126 ++len;
2127 } else
2128 if (curOpcode->opcode == D3DSIO_DEF) {
2129 TRACE("def c%lu = ", *pToken & 0xFF);
2130 ++pToken;
2131 ++len;
2132 TRACE("%f ,", *(float *)pToken);
2133 ++pToken;
2134 ++len;
2135 TRACE("%f ,", *(float *)pToken);
2136 ++pToken;
2137 ++len;
2138 TRACE("%f ,", *(float *)pToken);
2139 ++pToken;
2140 ++len;
2141 TRACE("%f", *(float *)pToken);
2142 ++pToken;
2143 ++len;
2144 } else {
2145 TRACE("%s ", curOpcode->name);
2146 if (curOpcode->num_params > 0) {
2147 vshader_program_dump_vs_param(*pToken, 0);
2148 ++pToken;
2149 ++len;
2150 for (i = 1; i < curOpcode->num_params; ++i) {
2151 TRACE(", ");
2152 vshader_program_dump_vs_param(*pToken, 1);
2153 ++pToken;
2154 ++len;
2158 TRACE("\n");
2161 This->functionLength = (len + 1) * sizeof(DWORD);
2162 } else {
2163 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2166 /* Generate HW shader in needed */
2167 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2168 #if 1
2169 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2170 #endif
2173 /* copy the function ... because it will certainly be released by application */
2174 if (NULL != pFunction) {
2175 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2176 memcpy((void *)This->function, pFunction, This->functionLength);
2177 } else {
2178 This->function = NULL;
2180 return D3D_OK;
2183 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2185 /*** IUnknown methods ***/
2186 IWineD3DVertexShaderImpl_QueryInterface,
2187 IWineD3DVertexShaderImpl_AddRef,
2188 IWineD3DVertexShaderImpl_Release,
2189 /*** IWineD3DVertexShader methods ***/
2190 IWineD3DVertexShaderImpl_GetParent,
2191 IWineD3DVertexShaderImpl_GetDevice,
2192 IWineD3DVertexShaderImpl_GetFunction,
2193 IWineD3DVertexShaderImpl_SetFunction