wined3d: Move the D3DSIO_DCL dumping code into its own function.
[wine/multimedia.git] / dlls / wined3d / vertexshader.c
blob13da61cdef5994e284c1f59914646adf99b7a534
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[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;
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, 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;
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, D3DMATRIX23 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) {
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) {
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", 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
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 as VS_ARB using one temporary 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 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) {
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 void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl *This, DWORD token) {
883 TRACE("dcl_");
884 switch(token & 0xFFFF) {
885 case D3DDECLUSAGE_POSITION:
886 TRACE("%s%ld ", "position",(token & 0xF0000) >> 16);
887 break;
888 case D3DDECLUSAGE_BLENDINDICES:
889 TRACE("%s ", "blend");
890 break;
891 case D3DDECLUSAGE_BLENDWEIGHT:
892 TRACE("%s ", "weight");
893 break;
894 case D3DDECLUSAGE_NORMAL:
895 TRACE("%s%ld ", "normal",(token & 0xF0000) >> 16);
896 break;
897 case D3DDECLUSAGE_PSIZE:
898 TRACE("%s ", "psize");
899 break;
900 case D3DDECLUSAGE_COLOR:
901 if((token & 0xF0000) >> 16 == 0) {
902 TRACE("%s ", "color");
903 } else {
904 TRACE("%s ", "specular");
906 break;
907 case D3DDECLUSAGE_TEXCOORD:
908 TRACE("%s%ld ", "texture", (token & 0xF0000) >> 16);
909 break;
910 case D3DDECLUSAGE_TANGENT:
911 TRACE("%s ", "tangent");
912 break;
913 case D3DDECLUSAGE_BINORMAL:
914 TRACE("%s ", "binormal");
915 break;
916 case D3DDECLUSAGE_TESSFACTOR:
917 TRACE("%s ", "tessfactor");
918 break;
919 case D3DDECLUSAGE_POSITIONT:
920 TRACE("%s%ld ", "positionT",(token & 0xF0000) >> 16);
921 break;
922 case D3DDECLUSAGE_FOG:
923 TRACE("%s ", "fog");
924 break;
925 case D3DDECLUSAGE_DEPTH:
926 TRACE("%s ", "depth");
927 break;
928 case D3DDECLUSAGE_SAMPLE:
929 TRACE("%s ", "sample");
930 break;
931 default:
932 FIXME("Unrecognised dcl %08lx", token & 0xFFFF);
936 inline static BOOL vshader_is_version_token(DWORD token) {
937 return 0xFFFE0000 == (token & 0xFFFE0000);
940 inline static BOOL vshader_is_comment_token(DWORD token) {
941 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
944 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
945 /** operand output */
946 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
947 strcat(hwLine, ".");
948 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
949 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
950 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
951 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
955 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
956 static const char swizzle_reg_chars_color_fix[] = "zyxw";
957 static const char swizzle_reg_chars[] = "xyzw";
958 const char* swizzle_regs = NULL;
959 char tmpReg[255];
961 /** operand input */
962 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
963 DWORD swizzle_x = swizzle & 0x03;
964 DWORD swizzle_y = (swizzle >> 2) & 0x03;
965 DWORD swizzle_z = (swizzle >> 4) & 0x03;
966 DWORD swizzle_w = (swizzle >> 6) & 0x03;
968 if (is_color) {
969 swizzle_regs = swizzle_reg_chars_color_fix;
970 } else {
971 swizzle_regs = swizzle_reg_chars;
975 * swizzle bits fields:
976 * WWZZYYXX
978 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
979 if (is_color) {
980 sprintf(tmpReg, ".%c%c%c%c",
981 swizzle_regs[swizzle_x],
982 swizzle_regs[swizzle_y],
983 swizzle_regs[swizzle_z],
984 swizzle_regs[swizzle_w]);
985 strcat(hwLine, tmpReg);
987 return ;
989 if (swizzle_x == swizzle_y &&
990 swizzle_x == swizzle_z &&
991 swizzle_x == swizzle_w)
993 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
994 strcat(hwLine, tmpReg);
995 } else {
996 sprintf(tmpReg, ".%c%c%c%c",
997 swizzle_regs[swizzle_x],
998 swizzle_regs[swizzle_y],
999 swizzle_regs[swizzle_z],
1000 swizzle_regs[swizzle_w]);
1001 strcat(hwLine, tmpReg);
1005 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
1006 /* oPos, oFog and oPts in D3D */
1007 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
1009 DWORD reg = param & 0x00001FFF;
1010 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1011 char tmpReg[255];
1012 BOOL is_color = FALSE;
1014 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
1015 strcat(hwLine, " -");
1016 } else {
1017 strcat(hwLine, " ");
1020 switch (regtype) {
1021 case D3DSPR_TEMP:
1022 sprintf(tmpReg, "T%lu", reg);
1023 strcat(hwLine, tmpReg);
1024 break;
1025 case D3DSPR_INPUT:
1026 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
1027 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
1028 is_color = TRUE;
1030 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1031 if (This->namedArrays) {
1032 sprintf(tmpReg, "namedVertex%lu", reg);
1033 } else {
1034 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1035 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
1037 strcat(hwLine, tmpReg);
1038 break;
1039 case D3DSPR_CONST:
1040 /* FIXME: some constants are named so we need a constants map*/
1041 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
1042 if (param & D3DVS_ADDRMODE_RELATIVE) {
1043 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
1045 sprintf(tmpReg, "const%lu", reg);
1046 } else {
1047 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
1049 strcat(hwLine, tmpReg);
1050 break;
1051 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
1052 sprintf(tmpReg, "A%lu", reg);
1053 strcat(hwLine, tmpReg);
1054 break;
1055 case D3DSPR_RASTOUT:
1056 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
1057 strcat(hwLine, tmpReg);
1058 break;
1059 case D3DSPR_ATTROUT:
1060 if (reg==0) {
1061 strcat(hwLine, "result.color.primary");
1062 } else {
1063 strcat(hwLine, "result.color.secondary");
1065 break;
1066 case D3DSPR_TEXCRDOUT:
1067 sprintf(tmpReg, "result.texcoord[%lu]", reg);
1068 strcat(hwLine, tmpReg);
1069 break;
1070 default:
1071 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1072 break;
1075 if (!is_input) {
1076 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1077 } else {
1078 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1082 DWORD MacroExpansion[4*4];
1084 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1085 int i;
1086 int nComponents = 0;
1087 DWORD opcode =0;
1088 switch(macro_opcode) {
1089 case D3DSIO_M4x4:
1090 nComponents = 4;
1091 opcode = D3DSIO_DP4;
1092 break;
1093 case D3DSIO_M4x3:
1094 nComponents = 3;
1095 opcode = D3DSIO_DP4;
1096 break;
1097 case D3DSIO_M3x4:
1098 nComponents = 4;
1099 opcode = D3DSIO_DP3;
1100 break;
1101 case D3DSIO_M3x3:
1102 nComponents = 3;
1103 opcode = D3DSIO_DP3;
1104 break;
1105 case D3DSIO_M3x2:
1106 nComponents = 2;
1107 opcode = D3DSIO_DP3;
1108 break;
1109 default:
1110 break;
1112 for (i = 0; i < nComponents; i++) {
1113 MacroExpansion[i*4+0] = opcode;
1114 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1115 MacroExpansion[i*4+2] = *(args+1);
1116 MacroExpansion[i*4+3] = (*(args+2))+i;
1118 return nComponents;
1121 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
1123 switch(usage & 0xFFFF) {
1124 case D3DDECLUSAGE_POSITION:
1125 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1126 TRACE("Setting position to %d\n", arrayNo);
1127 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1128 This->namedArrays = TRUE;
1129 } else {
1130 /* TODO: position indexes go from 0-8!!*/
1131 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1132 /* robots uses positions up to 8, the position arrays are just packed.*/
1133 if ((usage & 0xF0000) >> 16 > 1) {
1134 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1136 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1137 This->declaredArrays = TRUE;
1139 break;
1140 case D3DDECLUSAGE_BLENDINDICES:
1141 /* not supported by openGL */
1142 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1143 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1144 This->declaredArrays = TRUE;
1145 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1146 break;
1147 case D3DDECLUSAGE_BLENDWEIGHT:
1148 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1149 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1150 This->namedArrays = TRUE;
1151 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1152 break;
1153 case D3DDECLUSAGE_NORMAL:
1154 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1155 TRACE("Setting normal to %d\n", arrayNo);
1156 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1157 This->namedArrays = TRUE;
1158 } else {
1159 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1160 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1161 This->declaredArrays = TRUE;
1163 break;
1164 case D3DDECLUSAGE_PSIZE:
1165 TRACE("Setting PSIZE to %d\n", arrayNo);
1166 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1167 This->namedArrays = TRUE;
1168 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1169 break;
1170 case D3DDECLUSAGE_COLOR:
1171 if((usage & 0xF0000) >> 16 == 0) {
1172 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1173 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1174 This->namedArrays = TRUE;
1175 } else {
1176 TRACE("Setting SPECULAR to %d\n", arrayNo);
1177 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1178 This->namedArrays = TRUE;
1180 break;
1181 case D3DDECLUSAGE_TEXCOORD:
1182 This->namedArrays = TRUE;
1183 /* only 7 texture coords have been designed for, so run a quick sanity check */
1184 if ((usage & 0xF0000) >> 16 > 7) {
1185 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1186 } else {
1187 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1188 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1190 break;
1191 /* The following aren't supported by openGL,
1192 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1193 this should be caught in the first pass */
1194 case D3DDECLUSAGE_TANGENT:
1195 TRACE("Setting TANGENT to %d\n", arrayNo);
1196 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1197 This->declaredArrays = TRUE;
1198 break;
1199 case D3DDECLUSAGE_BINORMAL:
1200 TRACE("Setting BINORMAL to %d\n", arrayNo);
1201 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1202 This->declaredArrays = TRUE;
1203 break;
1204 case D3DDECLUSAGE_TESSFACTOR:
1205 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1206 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1207 This->declaredArrays = TRUE;
1208 break;
1209 case D3DDECLUSAGE_POSITIONT:
1210 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1211 FIXME("Setting positiont to %d\n", arrayNo);
1212 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1213 This->namedArrays = TRUE;
1214 } else {
1215 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1216 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1217 This->declaredArrays = TRUE;
1218 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1220 break;
1221 case D3DDECLUSAGE_FOG:
1222 /* supported by OpenGL */
1223 TRACE("Setting FOG to %d\n", arrayNo);
1224 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1225 This->namedArrays = TRUE;
1226 break;
1227 case D3DDECLUSAGE_DEPTH:
1228 TRACE("Setting DEPTH to %d\n", arrayNo);
1229 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1230 This->declaredArrays = TRUE;
1231 break;
1232 case D3DDECLUSAGE_SAMPLE:
1233 TRACE("Setting SAMPLE to %d\n", arrayNo);
1234 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1235 This->declaredArrays = TRUE;
1236 break;
1237 default:
1238 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1243 * Function parser ...
1246 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1247 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1248 const DWORD* pToken = pFunction;
1249 const DWORD* pSavedToken = NULL;
1250 const SHADER_OPCODE* curOpcode = NULL;
1251 int nRemInstr = -1;
1252 DWORD i;
1253 unsigned lineNum = 0;
1254 char *pgmStr = NULL;
1255 char tmpLine[255];
1256 DWORD nUseAddressRegister = 0;
1257 DWORD nUseTempRegister = 0;
1258 DWORD regtype;
1259 DWORD reg;
1260 BOOL tmpsUsed[32];
1261 #if 0 /* TODO: loope register (just another address register ) */
1262 BOOL hasLoops = FALSE;
1263 #endif
1265 #define PGMSIZE 65535
1266 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1267 int pgmLength = 0;
1269 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1270 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1271 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1272 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1273 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1274 This->fixupVertexBufferSize = PGMSIZE;
1275 This->fixupVertexBuffer[0] = 0;
1277 pgmStr = This->device->fixupVertexBuffer;
1278 #endif
1279 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1280 int _tmpLineLen = strlen(_tmpLine); \
1281 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1282 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); \
1283 } else { \
1284 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1286 pgmLength += _tmpLineLen; \
1289 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1290 /* Initialise the shader */
1291 This->namedArrays = FALSE;
1292 This->declaredArrays = FALSE;
1293 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1294 This->arrayUsageMap[i] = -1;
1296 /* set all the tmpsUsed to not used */
1297 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1299 /* 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 */
1300 This->highestConstant = -1;
1303 * First pass to determine what we need to declare:
1304 * - Temporary variables
1305 * - Address variables
1307 if (NULL != pToken) {
1308 while (D3DVS_END() != *pToken) {
1309 if (vshader_is_version_token(*pToken)) {
1310 /** skip version */
1311 ++pToken;
1312 continue;
1314 if (vshader_is_comment_token(*pToken)) { /** comment */
1315 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1316 ++pToken;
1317 pToken += comment_len;
1318 continue;
1320 curOpcode = vshader_program_get_opcode(*pToken);
1321 ++pToken;
1322 /* TODO: dcl's */
1323 /* TODO: Consts */
1325 if (NULL == curOpcode) {
1326 while (*pToken & 0x80000000) {
1327 FIXME("unrecognized opcode: %08lx\n", *pToken);
1328 /* skip unrecognized opcode */
1329 ++pToken;
1331 } else {
1332 if (curOpcode->opcode == D3DSIO_DCL){
1333 INT usage = *pToken++;
1334 INT arrayNo = (*pToken++ & 0x00001FFF);
1335 parse_decl_usage(This, usage, arrayNo);
1336 } else if(curOpcode->opcode == D3DSIO_DEF) {
1337 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1338 FIXME("Constant %ld\n", *pToken & 0xFF);
1339 ++pToken;
1340 ++pToken;
1341 ++pToken;
1342 ++pToken;
1343 ++pToken;
1345 } else {
1346 /* Check to see if and tmp or addressing redisters are used */
1347 if (curOpcode->num_params > 0) {
1348 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1349 reg = ((*pToken) & 0x00001FFF);
1350 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1351 if (D3DSPR_TEMP == regtype){
1352 tmpsUsed[reg] = TRUE;
1353 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1355 ++pToken;
1356 for (i = 1; i < curOpcode->num_params; ++i) {
1357 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1358 reg = ((*pToken) & 0x00001FFF);
1359 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1360 if (D3DSPR_TEMP == regtype){
1361 tmpsUsed[reg] = TRUE;
1362 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1364 ++pToken;
1368 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1369 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1370 FIXME("This shader requires gl shader language support\n");
1371 #if 0
1372 This->shaderLanguage = GLSHADER_GLSL;
1373 #endif
1375 #endif
1379 #if 1
1380 #define VSHADER_ALWAYS_NUMBERED
1381 #endif
1383 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1384 /* TODO: using numbered arrays for software shaders makes things easier */
1385 This->declaredArrays = TRUE;
1386 #endif
1388 /* named arrays and declared arrays are mutually exclusive */
1389 if (This->declaredArrays) {
1390 This->namedArrays = FALSE;
1392 /* TODO: validate
1393 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1394 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1397 /** second pass, now generate */
1398 pToken = pFunction;
1400 if (NULL != pToken) {
1401 while (1) {
1402 tmpLine[0] = 0;
1403 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1404 /* Macro is finished, continue normal path */
1405 pToken = pSavedToken;
1406 if (D3DVS_END() == *pToken)
1407 break;
1409 if (vshader_is_version_token(*pToken)) { /** version */
1410 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1411 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1412 int numTemps;
1413 int numConstants;
1415 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1417 /* Each release of vertex shaders has had different numbers of temp registers */
1418 switch (version) {
1419 case 10:
1420 case 11: numTemps=12;
1421 numConstants=96;/* min(GL_LIMITS(constants),96) */
1422 strcpy(tmpLine, "!!ARBvp1.0\n");
1423 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1424 break;
1425 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1426 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1427 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)*/
1428 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1429 numConstants=96; /* min(GL_LIMITS(constants),256) */
1430 strcpy(tmpLine, "!!ARBvp1.0\n");
1431 FIXME("No work done yet to support vs2.0 in hw\n");
1432 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1433 break;
1434 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1435 numConstants=96; /* min(GL_LIMITS(constants),256) */
1436 strcpy(tmpLine, "!!ARBvp1.0\n");
1437 FIXME("No work done yet to support vs2.1 in hw\n");
1438 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1439 break;
1440 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1441 numConstants=96;/* min(GL_LIMITS(constants),256) */
1442 strcpy(tmpLine, "!!ARBvp3.0\n");
1443 FIXME("No work done yet to support vs3.0 in hw\n");
1444 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1445 break;
1446 default:
1447 numTemps=12;/* min(GL_LIMITS(temps),12) */
1448 numConstants=96;/* min(GL_LIMITS(constants),96) */
1449 strcpy(tmpLine, "!!ARBvp1.0\n");
1450 FIXME("Unrecognized vertex shader version %d!\n", version);
1452 PNSTRCAT(pgmStr, tmpLine);
1454 ++lineNum;
1456 /* This should be a bitmap so that only temp registers that are used are declared. */
1457 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1458 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1459 sprintf(tmpLine, "TEMP T%ld;\n", i);
1460 ++lineNum;
1461 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1462 PNSTRCAT(pgmStr, tmpLine);
1466 /* TODO: loop register counts as an address register */
1467 for (i = 0; i < nUseAddressRegister; i++) {
1468 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1469 ++lineNum;
1470 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1471 PNSTRCAT(pgmStr, tmpLine);
1474 /* Due to the dynamic constants binding mechanism, we need to declare
1475 * all the constants for relative addressing. */
1476 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1477 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1478 numConstants = 95;
1480 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1481 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1483 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1484 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1485 PNSTRCAT(pgmStr, tmpLine);
1487 ++lineNum;
1489 ++pToken;
1490 continue;
1492 if (vshader_is_comment_token(*pToken)) { /** comment */
1493 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1494 ++pToken;
1495 FIXME("#%s\n", (char*)pToken);
1496 pToken += comment_len;
1497 continue;
1500 curOpcode = vshader_program_get_opcode(*pToken);
1501 ++pToken;
1502 if (NULL == curOpcode) {
1503 /* unknown current opcode ... (shouldn't be any!) */
1504 while (*pToken & 0x80000000) {
1505 FIXME("unrecognized opcode: %08lx\n", *pToken);
1506 ++pToken;
1508 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1509 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1511 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1512 pToken += curOpcode->num_params;
1513 } else {
1514 /* Build opcode for GL vertex_program */
1515 switch (curOpcode->opcode) {
1516 case D3DSIO_NOP:
1517 continue;
1518 case D3DSIO_MOV:
1519 /* Address registers must be loaded with the ARL instruction */
1520 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1521 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1522 strcpy(tmpLine, "ARL");
1523 break;
1524 } else
1525 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1527 /* fall through */
1528 case D3DSIO_ADD:
1529 case D3DSIO_SUB:
1530 case D3DSIO_MAD:
1531 case D3DSIO_MUL:
1532 case D3DSIO_RCP:
1533 case D3DSIO_RSQ:
1534 case D3DSIO_DP3:
1535 case D3DSIO_DP4:
1536 case D3DSIO_MIN:
1537 case D3DSIO_MAX:
1538 case D3DSIO_SLT:
1539 case D3DSIO_SGE:
1540 case D3DSIO_LIT:
1541 case D3DSIO_DST:
1542 case D3DSIO_FRC:
1543 case D3DSIO_EXPP:
1544 case D3DSIO_LOGP:
1545 case D3DSIO_EXP:
1546 case D3DSIO_LOG:
1547 strcpy(tmpLine, curOpcode->glname);
1548 break;
1549 case D3DSIO_M4x4:
1550 case D3DSIO_M4x3:
1551 case D3DSIO_M3x4:
1552 case D3DSIO_M3x3:
1553 case D3DSIO_M3x2:
1554 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1555 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1556 /* Save point to next instruction */
1557 pSavedToken = pToken + 3;
1558 /* Execute expanded macro */
1559 pToken = MacroExpansion;
1560 continue;
1561 /* dcl and def are handeled in the first pass */
1562 case D3DSIO_DCL:
1563 if (This->namedArrays) {
1564 const char* attribName = "undefined";
1565 switch(*pToken & 0xFFFF) {
1566 case D3DDECLUSAGE_POSITION:
1567 attribName = "vertex.position";
1568 break;
1569 case D3DDECLUSAGE_BLENDINDICES:
1570 /* not supported by openGL */
1571 attribName = "vertex.blend";
1572 break;
1573 case D3DDECLUSAGE_BLENDWEIGHT:
1574 attribName = "vertex.weight";
1575 break;
1576 case D3DDECLUSAGE_NORMAL:
1577 attribName = "vertex.normal";
1578 break;
1579 case D3DDECLUSAGE_PSIZE:
1580 attribName = "vertex.psize";
1581 break;
1582 case D3DDECLUSAGE_COLOR:
1583 if((*pToken & 0xF0000) >> 16 == 0) {
1584 attribName = "vertex.color";
1585 } else {
1586 attribName = "vertex.color.secondary";
1588 break;
1589 case D3DDECLUSAGE_TEXCOORD:
1591 char tmpChar[100];
1592 tmpChar[0] = 0;
1593 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1594 attribName = tmpChar;
1595 break;
1597 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1598 case D3DDECLUSAGE_TANGENT:
1599 attribName = "vertex.tangent";
1600 break;
1601 case D3DDECLUSAGE_BINORMAL:
1602 attribName = "vertex.binormal";
1603 break;
1604 case D3DDECLUSAGE_TESSFACTOR:
1605 attribName = "vertex.tessfactor";
1606 break;
1607 case D3DDECLUSAGE_POSITIONT:
1608 attribName = "vertex.possitionT";
1609 break;
1610 case D3DDECLUSAGE_FOG:
1611 attribName = "vertex.fogcoord";
1612 break;
1613 case D3DDECLUSAGE_DEPTH:
1614 attribName = "vertex.depth";
1615 break;
1616 case D3DDECLUSAGE_SAMPLE:
1617 attribName = "vertex.sample";
1618 break;
1619 default:
1620 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1623 char tmpChar[80];
1624 ++pToken;
1625 sprintf(tmpLine, "ATTRIB ");
1626 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1627 sprintf(tmpChar," = %s", attribName);
1628 strcat(tmpLine, tmpChar);
1629 strcat(tmpLine,";\n");
1630 ++lineNum;
1631 if (This->namedArrays) {
1632 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1633 PNSTRCAT(pgmStr, tmpLine);
1635 } else {
1636 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1639 } else {
1640 /* eat the token so it doesn't generate a warning */
1641 ++pToken;
1643 ++pToken;
1644 continue;
1645 case D3DSIO_DEF:
1647 char tmpChar[80];
1648 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1649 ++pToken;
1650 sprintf(tmpChar,"%f ,", *(float *)pToken);
1651 strcat(tmpLine, tmpChar);
1652 ++pToken;
1653 sprintf(tmpChar,"%f ,", *(float *)pToken);
1654 strcat(tmpLine, tmpChar);
1655 ++pToken;
1656 sprintf(tmpChar,"%f ,", *(float *)pToken);
1657 strcat(tmpLine, tmpChar);
1658 ++pToken;
1659 sprintf(tmpChar,"%f}", *(float *)pToken);
1660 strcat(tmpLine, tmpChar);
1662 strcat(tmpLine,";\n");
1663 ++lineNum;
1664 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1665 PNSTRCAT(pgmStr, tmpLine);
1667 ++pToken;
1668 continue;
1670 default:
1671 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1672 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1673 } else {
1674 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1677 if (curOpcode->num_params > 0) {
1678 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1680 ++pToken;
1681 for (i = 1; i < curOpcode->num_params; ++i) {
1682 strcat(tmpLine, ",");
1683 vshader_program_add_param(This, *pToken, TRUE, tmpLine);
1684 ++pToken;
1687 strcat(tmpLine,";\n");
1688 ++lineNum;
1689 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1690 PNSTRCAT(pgmStr, tmpLine);
1694 strcpy(tmpLine, "END\n");
1695 ++lineNum;
1696 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1697 PNSTRCAT(pgmStr, tmpLine);
1700 /* finally null terminate the pgmStr*/
1701 pgmStr[pgmLength] = 0;
1703 /* Check that Vertex Shaders are supported */
1704 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1705 /* Create the hw shader */
1706 /* TODO: change to resource.glObjectHandel or something like that */
1707 GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
1708 TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
1709 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
1711 /* Create the program and check for errors */
1712 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1713 if (glGetError() == GL_INVALID_OPERATION) {
1714 GLint errPos;
1715 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1716 FIXME("HW VertexShader Error at position %d: %s\n",
1717 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1718 This->prgId = -1;
1721 #if 1 /* if were using the data buffer of device then we don't need to free it */
1722 HeapFree(GetProcessHeap(), 0, pgmStr);
1723 #endif
1724 #undef PNSTRCAT
1727 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1729 * TODO: use the NV_vertex_program (or 1_1) extension
1730 * and specifics vendors (ARB_vertex_program??) variants for it
1732 return TRUE;
1735 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1736 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1738 /** Vertex Shader Temporary Registers */
1739 WINED3DSHADERVECTOR R[12];
1740 /*D3DSHADERSCALAR A0;*/
1741 WINED3DSHADERVECTOR A[1];
1742 /** temporary Vector for modifier management */
1743 WINED3DSHADERVECTOR d;
1744 WINED3DSHADERVECTOR s[3];
1745 /** parser datas */
1746 const DWORD* pToken = This->function;
1747 const SHADER_OPCODE* curOpcode = NULL;
1748 /** functions parameters */
1749 WINED3DSHADERVECTOR* p[4];
1750 WINED3DSHADERVECTOR* p_send[4];
1751 DWORD i;
1753 /** init temporary register */
1754 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1756 /* vshader_program_parse(vshader); */
1757 #if 0 /* Must not be 1 in cvs */
1758 TRACE("Input:\n");
1759 TRACE_VSVECTOR(This->data->C[0]);
1760 TRACE_VSVECTOR(This->data->C[1]);
1761 TRACE_VSVECTOR(This->data->C[2]);
1762 TRACE_VSVECTOR(This->data->C[3]);
1763 TRACE_VSVECTOR(This->data->C[4]);
1764 TRACE_VSVECTOR(This->data->C[5]);
1765 TRACE_VSVECTOR(This->data->C[6]);
1766 TRACE_VSVECTOR(This->data->C[7]);
1767 TRACE_VSVECTOR(This->data->C[8]);
1768 TRACE_VSVECTOR(This->data->C[64]);
1769 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1770 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1771 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1772 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1773 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1774 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1775 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1776 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1777 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1778 #endif
1780 TRACE_VSVECTOR(vshader->data->C[64]);
1781 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1783 /* the first dword is the version tag */
1784 /* TODO: parse it */
1786 if (vshader_is_version_token(*pToken)) { /** version */
1787 ++pToken;
1789 while (D3DVS_END() != *pToken) {
1790 if (vshader_is_comment_token(*pToken)) { /** comment */
1791 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1792 ++pToken;
1793 pToken += comment_len;
1794 continue ;
1796 curOpcode = vshader_program_get_opcode(*pToken);
1797 ++pToken;
1798 if (NULL == curOpcode) {
1799 i = 0;
1800 /* unknown current opcode ... */
1801 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1802 while (*pToken & 0x80000000) {
1803 if (i == 0) {
1804 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->function, *(pToken - 1));
1806 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->function, *pToken);
1807 vshader_program_dump_param(*pToken, i);
1808 TRACE("\n");
1809 ++i;
1810 ++pToken;
1812 /* return FALSE; */
1813 } else {
1814 if (curOpcode->num_params > 0) {
1815 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1816 for (i = 0; i < curOpcode->num_params; ++i) {
1817 DWORD reg = pToken[i] & 0x00001FFF;
1818 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1820 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1821 case D3DSPR_TEMP:
1822 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1823 p[i] = &R[reg];
1824 break;
1825 case D3DSPR_INPUT:
1826 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1827 p[i] = &input->V[reg];
1828 break;
1829 case D3DSPR_CONST:
1830 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1831 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1832 } else {
1833 p[i] = &This->data->C[reg];
1835 break;
1836 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1837 if (0 != reg) {
1838 ERR("cannot handle address registers != a0, forcing use of a0\n");
1839 reg = 0;
1841 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1842 p[i] = &A[reg];
1843 break;
1844 case D3DSPR_RASTOUT:
1845 switch (reg) {
1846 case D3DSRO_POSITION:
1847 p[i] = &output->oPos;
1848 break;
1849 case D3DSRO_FOG:
1850 p[i] = &output->oFog;
1851 break;
1852 case D3DSRO_POINT_SIZE:
1853 p[i] = &output->oPts;
1854 break;
1856 break;
1857 case D3DSPR_ATTROUT:
1858 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1859 p[i] = &output->oD[reg];
1860 break;
1861 case D3DSPR_TEXCRDOUT:
1862 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1863 p[i] = &output->oT[reg];
1864 break;
1865 /* TODO Decls and defs */
1866 #if 0
1867 case D3DSPR_DCL:
1868 case D3DSPR_DEF:
1869 #endif
1870 default:
1871 break;
1874 if (i > 0) { /* input reg */
1875 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1876 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1878 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1879 /* TRACE("p[%d] not swizzled\n", i); */
1880 p_send[i] = p[i];
1881 } else {
1882 DWORD swizzle_x = swizzle & 0x03;
1883 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1884 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1885 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1886 /* TRACE("p[%d] swizzled\n", i); */
1887 float* tt = (float*) p[i];
1888 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1889 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1890 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1891 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1892 p_send[i] = &s[i];
1894 } else { /* output reg */
1895 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1896 p_send[i] = p[i];
1897 } else {
1898 p_send[i] = &d; /* to be post-processed for modifiers management */
1904 switch (curOpcode->num_params) {
1905 case 0:
1906 curOpcode->soft_fct();
1907 break;
1908 case 1:
1909 curOpcode->soft_fct(p_send[0]);
1910 break;
1911 case 2:
1912 curOpcode->soft_fct(p_send[0], p_send[1]);
1913 break;
1914 case 3:
1915 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1916 break;
1917 case 4:
1918 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1919 break;
1920 case 5:
1921 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1922 break;
1923 case 6:
1924 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1925 break;
1926 default:
1927 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1930 /* check if output reg modifier post-process */
1931 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1932 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1933 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1934 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1935 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1937 #if 0
1938 TRACE_VSVECTOR(output->oPos);
1939 TRACE_VSVECTOR(output->oD[0]);
1940 TRACE_VSVECTOR(output->oD[1]);
1941 TRACE_VSVECTOR(output->oT[0]);
1942 TRACE_VSVECTOR(output->oT[1]);
1943 TRACE_VSVECTOR(R[0]);
1944 TRACE_VSVECTOR(R[1]);
1945 TRACE_VSVECTOR(R[2]);
1946 TRACE_VSVECTOR(R[3]);
1947 TRACE_VSVECTOR(R[4]);
1948 TRACE_VSVECTOR(R[5]);
1949 #endif
1951 /* to next opcode token */
1952 pToken += curOpcode->num_params;
1954 #if 0
1955 TRACE("End of current instruction:\n");
1956 TRACE_VSVECTOR(output->oPos);
1957 TRACE_VSVECTOR(output->oD[0]);
1958 TRACE_VSVECTOR(output->oD[1]);
1959 TRACE_VSVECTOR(output->oT[0]);
1960 TRACE_VSVECTOR(output->oT[1]);
1961 TRACE_VSVECTOR(R[0]);
1962 TRACE_VSVECTOR(R[1]);
1963 TRACE_VSVECTOR(R[2]);
1964 TRACE_VSVECTOR(R[3]);
1965 TRACE_VSVECTOR(R[4]);
1966 TRACE_VSVECTOR(R[5]);
1967 #endif
1969 #if 0 /* Must not be 1 in cvs */
1970 TRACE("Output:\n");
1971 TRACE_VSVECTOR(output->oPos);
1972 TRACE_VSVECTOR(output->oD[0]);
1973 TRACE_VSVECTOR(output->oD[1]);
1974 TRACE_VSVECTOR(output->oT[0]);
1975 TRACE_VSVECTOR(output->oT[1]);
1976 #endif
1977 return D3D_OK;
1980 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1981 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1982 FIXME("(%p) : stub\n", This);
1983 return D3D_OK;
1986 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1987 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1988 FIXME("(%p) : stub\n", This);
1989 return D3D_OK;
1992 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1993 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1994 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1995 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1996 return D3DERR_INVALIDCALL;
1998 if (NULL == pConstantData) {
1999 return D3DERR_INVALIDCALL;
2001 FIXME("(%p) : stub\n", This);
2002 return D3D_OK;
2005 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
2006 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2007 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
2008 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2009 return D3DERR_INVALIDCALL;
2011 if (NULL == pConstantData) {
2012 return D3DERR_INVALIDCALL;
2014 FIXME("(%p) : stub\n", This);
2015 return D3D_OK;
2018 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
2019 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2020 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2021 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
2022 return D3DERR_INVALIDCALL;
2024 if (NULL == pConstantData) {
2025 return D3DERR_INVALIDCALL;
2027 FIXME("(%p) : stub\n", This);
2028 return D3D_OK;
2031 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
2032 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
2033 FIXME("(%p) : stub\n", This);
2034 return D3D_OK;
2037 #endif
2039 /* *******************************************
2040 IWineD3DVertexShader IUnknown parts follow
2041 ******************************************* */
2042 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
2044 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2045 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
2046 if (IsEqualGUID(riid, &IID_IUnknown)
2047 || IsEqualGUID(riid, &IID_IWineD3DBase)
2048 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
2049 IUnknown_AddRef(iface);
2050 *ppobj = This;
2051 return D3D_OK;
2053 return E_NOINTERFACE;
2056 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
2057 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2058 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2059 return InterlockedIncrement(&This->ref);
2062 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
2063 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2064 ULONG ref;
2065 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2066 ref = InterlockedDecrement(&This->ref);
2067 if (ref == 0) {
2068 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2069 HeapFree(GetProcessHeap(), 0, This);
2071 return ref;
2074 /* *******************************************
2075 IWineD3DVertexShader IWineD3DVertexShader parts follow
2076 ******************************************* */
2078 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2079 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2081 *parent = This->parent;
2082 IUnknown_AddRef(*parent);
2083 TRACE("(%p) : returning %p\n", This, *parent);
2084 return D3D_OK;
2087 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2088 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2089 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2090 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2091 TRACE("(%p) returning %p\n", This, *pDevice);
2092 return D3D_OK;
2095 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2096 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2097 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2099 if (NULL == pData) {
2100 *pSizeOfData = This->functionLength;
2101 return D3D_OK;
2103 if (*pSizeOfData < This->functionLength) {
2104 *pSizeOfData = This->functionLength;
2105 return D3DERR_MOREDATA;
2107 if (NULL == This->function) { /* no function defined */
2108 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2109 (*(DWORD **) pData) = NULL;
2110 } else {
2111 if(This->functionLength == 0){
2114 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2115 memcpy(pData, This->function, This->functionLength);
2117 return D3D_OK;
2120 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2121 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2122 const DWORD* pToken = pFunction;
2123 const SHADER_OPCODE* curOpcode = NULL;
2124 DWORD len = 0;
2125 DWORD i;
2126 TRACE("(%p) : Parsing programme\n", This);
2128 if (NULL != pToken) {
2129 while (D3DVS_END() != *pToken) {
2130 if (vshader_is_version_token(*pToken)) { /** version */
2131 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2132 ++pToken;
2133 ++len;
2134 continue;
2136 if (vshader_is_comment_token(*pToken)) { /** comment */
2137 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2138 ++pToken;
2139 TRACE("//%s\n", (char*)pToken);
2140 pToken += comment_len;
2141 len += comment_len + 1;
2142 continue;
2144 curOpcode = vshader_program_get_opcode(*pToken);
2145 ++pToken;
2146 ++len;
2147 if (NULL == curOpcode) {
2148 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2149 while (*pToken & 0x80000000) {
2150 /* unknown current opcode ... */
2151 FIXME("unrecognized opcode: %08lx", *pToken);
2152 ++pToken;
2153 ++len;
2154 TRACE("\n");
2157 } else {
2158 if (curOpcode->opcode == D3DSIO_DCL) {
2159 vshader_program_dump_decl_usage(This, *pToken);
2160 ++pToken;
2161 ++len;
2162 vshader_program_dump_vs_param(*pToken, 0);
2163 ++pToken;
2164 ++len;
2165 } else
2166 if (curOpcode->opcode == D3DSIO_DEF) {
2167 TRACE("def c%lu = ", *pToken & 0xFF);
2168 ++pToken;
2169 ++len;
2170 TRACE("%f ,", *(float *)pToken);
2171 ++pToken;
2172 ++len;
2173 TRACE("%f ,", *(float *)pToken);
2174 ++pToken;
2175 ++len;
2176 TRACE("%f ,", *(float *)pToken);
2177 ++pToken;
2178 ++len;
2179 TRACE("%f", *(float *)pToken);
2180 ++pToken;
2181 ++len;
2182 } else {
2183 TRACE("%s ", curOpcode->name);
2184 if (curOpcode->num_params > 0) {
2185 vshader_program_dump_vs_param(*pToken, 0);
2186 ++pToken;
2187 ++len;
2188 for (i = 1; i < curOpcode->num_params; ++i) {
2189 TRACE(", ");
2190 vshader_program_dump_vs_param(*pToken, 1);
2191 ++pToken;
2192 ++len;
2196 TRACE("\n");
2199 This->functionLength = (len + 1) * sizeof(DWORD);
2200 } else {
2201 This->functionLength = 1; /* no Function defined use fixed function vertex processing */
2204 /* Generate HW shader in needed */
2205 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2206 #if 1
2207 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2208 #endif
2211 /* copy the function ... because it will certainly be released by application */
2212 if (NULL != pFunction) {
2213 This->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->functionLength);
2214 memcpy((void *)This->function, pFunction, This->functionLength);
2215 } else {
2216 This->function = NULL;
2218 return D3D_OK;
2221 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2223 /*** IUnknown methods ***/
2224 IWineD3DVertexShaderImpl_QueryInterface,
2225 IWineD3DVertexShaderImpl_AddRef,
2226 IWineD3DVertexShaderImpl_Release,
2227 /*** IWineD3DVertexShader methods ***/
2228 IWineD3DVertexShaderImpl_GetParent,
2229 IWineD3DVertexShaderImpl_GetDevice,
2230 IWineD3DVertexShaderImpl_GetFunction,
2231 IWineD3DVertexShaderImpl_SetFunction