wined3d: Share shader_dump_ins_modifiers().
[wine/gsoc_dplay.git] / dlls / wined3d / vertexshader.c
blobc578d38ad257ef0574463de497775fb0f36fc4ae
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 #define GLNAME_REQUIRE_GLSL ((const char *)1)
83 /*******************************
84 * vshader functions software VM
87 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
88 d->x = s0->x + s1->x;
89 d->y = s0->y + s1->y;
90 d->z = s0->z + s1->z;
91 d->w = s0->w + s1->w;
92 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
93 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
96 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
97 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
98 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
99 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
102 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
103 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
104 VSTRACE(("executing dp4: 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_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
109 d->x = 1.0f;
110 d->y = s0->y * s1->y;
111 d->z = s0->z;
112 d->w = s1->w;
113 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
114 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
117 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
118 union {
119 float f;
120 DWORD d;
121 } tmp;
123 tmp.f = floorf(s0->w);
124 d->x = powf(2.0f, tmp.f);
125 d->y = s0->w - tmp.f;
126 tmp.f = powf(2.0f, s0->w);
127 tmp.d &= 0xFFFFFF00U;
128 d->z = tmp.f;
129 d->w = 1.0f;
130 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
131 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
134 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
135 d->x = 1.0f;
136 d->y = (0.0f < s0->x) ? s0->x : 0.0f;
137 d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
138 d->w = 1.0f;
139 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
140 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
143 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
144 float tmp_f = fabsf(s0->w);
145 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
146 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
147 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
150 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
151 d->x = s0->x * s1->x + s2->x;
152 d->y = s0->y * s1->y + s2->y;
153 d->z = s0->z * s1->z + s2->z;
154 d->w = s0->w * s1->w + s2->w;
155 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
156 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));
159 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
160 d->x = (s0->x >= s1->x) ? s0->x : s1->x;
161 d->y = (s0->y >= s1->y) ? s0->y : s1->y;
162 d->z = (s0->z >= s1->z) ? s0->z : s1->z;
163 d->w = (s0->w >= s1->w) ? s0->w : s1->w;
164 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
165 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
168 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
169 d->x = (s0->x < s1->x) ? s0->x : s1->x;
170 d->y = (s0->y < s1->y) ? s0->y : s1->y;
171 d->z = (s0->z < s1->z) ? s0->z : s1->z;
172 d->w = (s0->w < s1->w) ? s0->w : s1->w;
173 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
174 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
177 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
178 d->x = s0->x;
179 d->y = s0->y;
180 d->z = s0->z;
181 d->w = s0->w;
182 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
183 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
186 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
187 d->x = s0->x * s1->x;
188 d->y = s0->y * s1->y;
189 d->z = s0->z * s1->z;
190 d->w = s0->w * s1->w;
191 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
192 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
195 void vshader_nop(void) {
196 /* NOPPPP ahhh too easy ;) */
197 VSTRACE(("executing nop\n"));
200 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
201 d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
202 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
203 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
206 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
207 float tmp_f = fabsf(s0->w);
208 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);
209 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
210 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
213 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
214 d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
215 d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
216 d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
217 d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
218 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
219 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
222 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
223 d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
224 d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
225 d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
226 d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
227 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
228 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
231 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
232 d->x = s0->x - s1->x;
233 d->y = s0->y - s1->y;
234 d->z = s0->z - s1->z;
235 d->w = s0->w - s1->w;
236 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
237 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
241 * Version 1.1 specific
244 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
245 d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
246 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
247 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
250 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
251 float tmp_f = fabsf(s0->w);
252 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
253 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
254 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
257 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
258 d->x = s0->x - floorf(s0->x);
259 d->y = s0->y - floorf(s0->y);
260 d->z = 0.0f;
261 d->w = 1.0f;
262 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
263 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
266 typedef FLOAT D3DMATRIX44[4][4];
267 typedef FLOAT D3DMATRIX43[4][3];
268 typedef FLOAT D3DMATRIX34[3][4];
269 typedef FLOAT D3DMATRIX33[3][3];
270 typedef FLOAT D3DMATRIX23[2][3];
272 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
274 * Buggy CODE: here only if cast not work for copy/paste
275 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
276 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
277 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
278 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
279 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
280 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
281 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
283 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
284 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
285 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
286 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
287 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));
288 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));
289 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));
290 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));
293 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
294 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
295 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
296 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
297 d->w = 1.0f;
298 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));
299 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));
300 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));
301 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
304 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
305 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
306 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
307 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
308 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
309 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));
310 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
311 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));
312 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
315 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
316 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
317 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
318 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
319 d->w = 1.0f;
320 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));
321 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
322 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));
323 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
326 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
327 FIXME("check\n");
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 = 0.0f;
331 d->w = 1.0f;
335 * Version 2.0 specific
337 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
338 d->x = s0->x * (s1->x - s2->x) + s2->x;
339 d->y = s0->y * (s1->y - s2->y) + s2->y;
340 d->z = s0->z * (s1->z - s2->z) + s2->z;
341 d->w = s0->w * (s1->w - s2->w) + s2->w;
344 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
345 d->x = s0->y * s1->z - s0->z * s1->y;
346 d->y = s0->z * s1->x - s0->x * s1->z;
347 d->z = s0->x * s1->y - s0->y * s1->x;
348 d->w = 0.9f; /* w is undefined, so set it to something safeish */
350 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
351 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
354 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
356 d->x = fabsf(s0->x);
357 d->y = fabsf(s0->y);
358 d->z = fabsf(s0->z);
359 d->w = fabsf(s0->w);
360 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
361 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
364 /* Stubs */
366 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
367 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
368 FIXME(" : Stub\n");
371 void vshader_call(WINED3DSHADERVECTOR* d) {
372 FIXME(" : Stub\n");
375 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
376 FIXME(" : Stub\n");
379 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
380 FIXME(" : Stub\n");
383 void vshader_ret(void) {
384 FIXME(" : Stub\n");
387 void vshader_endloop(void) {
388 FIXME(" : Stub\n");
391 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
392 FIXME(" : Stub\n");
395 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
396 FIXME(" : Stub\n");
399 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
400 FIXME(" : Stub\n");
403 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404 FIXME(" : Stub\n");
407 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408 FIXME(" : Stub\n");
411 void vshader_rep(WINED3DSHADERVECTOR* d) {
412 FIXME(" : Stub\n");
415 void vshader_endrep(void) {
416 FIXME(" : Stub\n");
419 void vshader_if(WINED3DSHADERVECTOR* d) {
420 FIXME(" : Stub\n");
423 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424 FIXME(" : Stub\n");
427 void vshader_else(void) {
428 FIXME(" : Stub\n");
431 void vshader_label(WINED3DSHADERVECTOR* d) {
432 FIXME(" : Stub\n");
435 void vshader_endif(void) {
436 FIXME(" : Stub\n");
439 void vshader_break(void) {
440 FIXME(" : Stub\n");
443 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
444 FIXME(" : Stub\n");
447 void vshader_breakp(WINED3DSHADERVECTOR* d) {
448 FIXME(" : Stub\n");
451 void vshader_mova(WINED3DSHADERVECTOR* d) {
452 FIXME(" : Stub\n");
455 void vshader_defb(WINED3DSHADERVECTOR* d) {
456 FIXME(" : Stub\n");
459 void vshader_defi(WINED3DSHADERVECTOR* d) {
460 FIXME(" : Stub\n");
463 void vshader_texldd(WINED3DSHADERVECTOR* d) {
464 FIXME(" : Stub\n");
467 void vshader_setp(WINED3DSHADERVECTOR* d) {
468 FIXME(" : Stub\n");
471 void vshader_texldl(WINED3DSHADERVECTOR* d) {
472 FIXME(" : Stub\n");
475 /* Prototype */
476 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
477 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
478 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
479 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
482 * log, exp, frc, m*x* seems to be macros ins ... to see
484 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
486 /* Arithmetic */
487 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, NULL, 0, 0},
488 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
489 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
490 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
491 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
492 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
511 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
512 /* TODO: sng can possibly be performed a s
513 RCP tmp, vec
514 MUL out, tmp, vec*/
515 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
516 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
517 DP3 tmp , vec, vec;
518 RSQ tmp, tmp.x;
519 MUL vec.xyz, vec, tmp;
520 but I think this is better because it accounts for w properly.
521 DP3 tmp , vec, vec;
522 RSQ tmp, tmp.x;
523 MUL vec, vec, tmp;
526 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, NULL, 0, 0},
527 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, NULL, NULL, 0, 0},
529 /* Matrix */
530 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
531 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
532 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
533 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
534 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
536 /* Declare registers */
537 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
539 /* Constant definitions */
540 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
541 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
542 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, NULL, NULL, 0, 0},
544 /* Flow control - requires GLSL or software shaders */
545 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
546 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
547 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
548 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
549 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
550 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
551 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
552 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
553 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
554 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
555 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
556 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
557 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
558 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
559 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
561 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
562 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, NULL, 0, 0},
563 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
564 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
567 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
568 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
569 static const char swizzle_reg_chars[] = "xyzw";
571 DWORD reg = param & D3DSP_REGNUM_MASK;
572 DWORD regtype = shader_get_regtype(param);
574 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
576 switch (regtype) {
577 case D3DSPR_TEMP:
578 TRACE("r%lu", reg);
579 break;
580 case D3DSPR_INPUT:
581 TRACE("v%lu", reg);
582 break;
583 case D3DSPR_CONST:
584 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
585 break;
586 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
587 TRACE("a%lu", reg);
588 break;
589 case D3DSPR_RASTOUT:
590 TRACE("%s", rastout_reg_names[reg]);
591 break;
592 case D3DSPR_ATTROUT:
593 TRACE("oD%lu", reg);
594 break;
595 case D3DSPR_TEXCRDOUT:
596 TRACE("oT%lu", reg);
597 break;
598 case D3DSPR_CONSTINT:
599 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
600 break;
601 case D3DSPR_CONSTBOOL:
602 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
603 break;
604 case D3DSPR_LABEL:
605 TRACE("l%lu", reg);
606 break;
607 case D3DSPR_LOOP:
608 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
609 break;
610 case D3DSPR_SAMPLER:
611 TRACE("s%lu", reg);
612 break;
613 default:
614 FIXME("Unknown %lu reg %lu\n",regtype, reg);
615 break;
618 if (!input) {
619 /** operand output */
620 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
621 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
622 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
623 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
624 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
626 } else {
627 /** operand input */
628 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
629 DWORD swizzle_x = swizzle & 0x03;
630 DWORD swizzle_y = (swizzle >> 2) & 0x03;
631 DWORD swizzle_z = (swizzle >> 4) & 0x03;
632 DWORD swizzle_w = (swizzle >> 6) & 0x03;
634 * swizzle bits fields:
635 * WWZZYYXX
637 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
638 if (swizzle_x == swizzle_y &&
639 swizzle_x == swizzle_z &&
640 swizzle_x == swizzle_w) {
641 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
642 } else {
643 TRACE(".%c%c%c%c",
644 swizzle_reg_chars[swizzle_x],
645 swizzle_reg_chars[swizzle_y],
646 swizzle_reg_chars[swizzle_z],
647 swizzle_reg_chars[swizzle_w]);
653 inline static BOOL vshader_is_version_token(DWORD token) {
654 return 0xFFFE0000 == (token & 0xFFFE0000);
657 inline static BOOL vshader_is_comment_token(DWORD token) {
658 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
661 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
662 /** operand output */
663 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
664 strcat(hwLine, ".");
665 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
666 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
667 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
668 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
672 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
673 static const char swizzle_reg_chars_color_fix[] = "zyxw";
674 static const char swizzle_reg_chars[] = "xyzw";
675 const char* swizzle_regs = NULL;
676 char tmpReg[255];
678 /** operand input */
679 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
680 DWORD swizzle_x = swizzle & 0x03;
681 DWORD swizzle_y = (swizzle >> 2) & 0x03;
682 DWORD swizzle_z = (swizzle >> 4) & 0x03;
683 DWORD swizzle_w = (swizzle >> 6) & 0x03;
685 if (is_color) {
686 swizzle_regs = swizzle_reg_chars_color_fix;
687 } else {
688 swizzle_regs = swizzle_reg_chars;
692 * swizzle bits fields:
693 * WWZZYYXX
695 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
696 if (is_color) {
697 sprintf(tmpReg, ".%c%c%c%c",
698 swizzle_regs[swizzle_x],
699 swizzle_regs[swizzle_y],
700 swizzle_regs[swizzle_z],
701 swizzle_regs[swizzle_w]);
702 strcat(hwLine, tmpReg);
704 return ;
706 if (swizzle_x == swizzle_y &&
707 swizzle_x == swizzle_z &&
708 swizzle_x == swizzle_w)
710 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
711 strcat(hwLine, tmpReg);
712 } else {
713 sprintf(tmpReg, ".%c%c%c%c",
714 swizzle_regs[swizzle_x],
715 swizzle_regs[swizzle_y],
716 swizzle_regs[swizzle_z],
717 swizzle_regs[swizzle_w]);
718 strcat(hwLine, tmpReg);
722 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
723 /* oPos, oFog and oPts in D3D */
724 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
726 DWORD reg = param & D3DSP_REGNUM_MASK;
727 DWORD regtype = shader_get_regtype(param);
728 char tmpReg[255];
729 BOOL is_color = FALSE;
731 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
732 strcat(hwLine, " -");
733 } else {
734 strcat(hwLine, " ");
737 switch (regtype) {
738 case D3DSPR_TEMP:
739 sprintf(tmpReg, "R%lu", reg);
740 strcat(hwLine, tmpReg);
741 break;
742 case D3DSPR_INPUT:
743 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
744 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
745 is_color = TRUE;
747 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
748 if (This->namedArrays) {
749 sprintf(tmpReg, "namedVertex%lu", reg);
750 } else {
751 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
752 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
754 strcat(hwLine, tmpReg);
755 break;
756 case D3DSPR_CONST:
757 /* FIXME: some constants are named so we need a constants map*/
758 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
759 if (param & D3DVS_ADDRMODE_RELATIVE) {
760 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
762 sprintf(tmpReg, "const%lu", reg);
763 } else {
764 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
766 strcat(hwLine, tmpReg);
767 break;
768 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
769 sprintf(tmpReg, "A%lu", reg);
770 strcat(hwLine, tmpReg);
771 break;
772 case D3DSPR_RASTOUT:
773 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
774 strcat(hwLine, tmpReg);
775 break;
776 case D3DSPR_ATTROUT:
777 if (reg==0) {
778 strcat(hwLine, "result.color.primary");
779 } else {
780 strcat(hwLine, "result.color.secondary");
782 break;
783 case D3DSPR_TEXCRDOUT:
784 sprintf(tmpReg, "result.texcoord[%lu]", reg);
785 strcat(hwLine, tmpReg);
786 break;
787 default:
788 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
789 break;
792 if (!is_input) {
793 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
794 } else {
795 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
799 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
801 switch(usage & 0xFFFF) {
802 case D3DDECLUSAGE_POSITION:
803 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
804 TRACE("Setting position to %d\n", arrayNo);
805 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
806 This->namedArrays = TRUE;
807 } else {
808 /* TODO: position indexes go from 0-8!!*/
809 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
810 /* robots uses positions up to 8, the position arrays are just packed.*/
811 if ((usage & 0xF0000) >> 16 > 1) {
812 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
814 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
815 This->declaredArrays = TRUE;
817 break;
818 case D3DDECLUSAGE_BLENDINDICES:
819 /* not supported by openGL */
820 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
821 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
822 This->declaredArrays = TRUE;
823 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
824 break;
825 case D3DDECLUSAGE_BLENDWEIGHT:
826 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
827 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
828 This->namedArrays = TRUE;
829 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
830 break;
831 case D3DDECLUSAGE_NORMAL:
832 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
833 TRACE("Setting normal to %d\n", arrayNo);
834 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
835 This->namedArrays = TRUE;
836 } else {
837 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
838 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
839 This->declaredArrays = TRUE;
841 break;
842 case D3DDECLUSAGE_PSIZE:
843 TRACE("Setting PSIZE to %d\n", arrayNo);
844 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
845 This->namedArrays = TRUE;
846 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
847 break;
848 case D3DDECLUSAGE_COLOR:
849 if((usage & 0xF0000) >> 16 == 0) {
850 TRACE("Setting DIFFUSE to %d\n", arrayNo);
851 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
852 This->namedArrays = TRUE;
853 } else {
854 TRACE("Setting SPECULAR to %d\n", arrayNo);
855 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
856 This->namedArrays = TRUE;
858 break;
859 case D3DDECLUSAGE_TEXCOORD:
860 This->namedArrays = TRUE;
861 /* only 7 texture coords have been designed for, so run a quick sanity check */
862 if ((usage & 0xF0000) >> 16 > 7) {
863 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
864 } else {
865 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
866 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
868 break;
869 /* The following aren't supported by openGL,
870 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
871 this should be caught in the first pass */
872 case D3DDECLUSAGE_TANGENT:
873 TRACE("Setting TANGENT to %d\n", arrayNo);
874 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
875 This->declaredArrays = TRUE;
876 break;
877 case D3DDECLUSAGE_BINORMAL:
878 TRACE("Setting BINORMAL to %d\n", arrayNo);
879 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
880 This->declaredArrays = TRUE;
881 break;
882 case D3DDECLUSAGE_TESSFACTOR:
883 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
884 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
885 This->declaredArrays = TRUE;
886 break;
887 case D3DDECLUSAGE_POSITIONT:
888 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
889 FIXME("Setting positiont to %d\n", arrayNo);
890 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
891 This->namedArrays = TRUE;
892 } else {
893 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
894 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
895 This->declaredArrays = TRUE;
896 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
898 break;
899 case D3DDECLUSAGE_FOG:
900 /* supported by OpenGL */
901 TRACE("Setting FOG to %d\n", arrayNo);
902 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
903 This->namedArrays = TRUE;
904 break;
905 case D3DDECLUSAGE_DEPTH:
906 TRACE("Setting DEPTH to %d\n", arrayNo);
907 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
908 This->declaredArrays = TRUE;
909 break;
910 case D3DDECLUSAGE_SAMPLE:
911 TRACE("Setting SAMPLE to %d\n", arrayNo);
912 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
913 This->declaredArrays = TRUE;
914 break;
915 default:
916 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
920 void vshader_set_version(
921 IWineD3DVertexShaderImpl *This,
922 DWORD version) {
924 DWORD major = (version >> 8) & 0x0F;
925 DWORD minor = version & 0x0F;
927 This->baseShader.hex_version = version;
928 This->baseShader.version = major * 10 + minor;
929 TRACE("vs_%lu_%lu\n", major, minor);
931 This->baseShader.limits.texture = 0;
933 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
934 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
936 switch (This->baseShader.version) {
937 case 10:
938 case 11: This->baseShader.limits.temporary = 12;
939 This->baseShader.limits.constant_bool = 0;
940 This->baseShader.limits.constant_int = 0;
941 This->baseShader.limits.address = 1;
942 break;
944 case 20:
945 case 21: This->baseShader.limits.temporary = 12;
946 This->baseShader.limits.constant_bool = 16;
947 This->baseShader.limits.constant_int = 16;
948 This->baseShader.limits.address = 1;
949 break;
951 case 30: This->baseShader.limits.temporary = 32;
952 This->baseShader.limits.constant_bool = 32;
953 This->baseShader.limits.constant_int = 32;
954 This->baseShader.limits.address = 1;
955 break;
957 default: This->baseShader.limits.temporary = 12;
958 This->baseShader.limits.constant_bool = 0;
959 This->baseShader.limits.constant_int = 0;
960 This->baseShader.limits.address = 1;
961 FIXME("Unrecognized vertex shader version %lx!\n", version);
965 /* Map the opcode 1-to-1 to the GL code */
966 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
968 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
969 CONST SHADER_OPCODE* curOpcode = arg->opcode;
970 SHADER_BUFFER* buffer = arg->buffer;
971 DWORD dst = arg->dst;
972 DWORD* src = arg->src;
974 DWORD dst_regtype = shader_get_regtype(dst);
975 char tmpLine[256];
976 unsigned int i;
978 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
979 strcpy(tmpLine, "ARL");
980 else
981 strcpy(tmpLine, curOpcode->glname);
983 if (curOpcode->num_params > 0) {
984 vshader_program_add_param(This, dst, FALSE, tmpLine);
985 for (i = 1; i < curOpcode->num_params; ++i) {
986 strcat(tmpLine, ",");
987 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
990 shader_addline(buffer, "%s;\n", tmpLine);
993 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
995 DWORD dst = arg->dst;
996 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
997 char tmpLine[256];
998 SHADER_BUFFER* buffer = arg->buffer;
1000 if (This->namedArrays) {
1001 const char* attribName = "undefined";
1002 switch(dst & 0xFFFF) {
1003 case D3DDECLUSAGE_POSITION:
1004 attribName = "vertex.position";
1005 break;
1006 case D3DDECLUSAGE_BLENDINDICES:
1007 /* not supported by openGL */
1008 attribName = "vertex.blend";
1009 break;
1010 case D3DDECLUSAGE_BLENDWEIGHT:
1011 attribName = "vertex.weight";
1012 break;
1013 case D3DDECLUSAGE_NORMAL:
1014 attribName = "vertex.normal";
1015 break;
1016 case D3DDECLUSAGE_PSIZE:
1017 attribName = "vertex.psize";
1018 break;
1019 case D3DDECLUSAGE_COLOR:
1020 if((dst & 0xF0000) >> 16 == 0) {
1021 attribName = "vertex.color";
1022 } else {
1023 attribName = "vertex.color.secondary";
1025 break;
1026 case D3DDECLUSAGE_TEXCOORD:
1028 char tmpChar[100];
1029 tmpChar[0] = 0;
1030 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
1031 attribName = tmpChar;
1032 break;
1034 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1035 case D3DDECLUSAGE_TANGENT:
1036 attribName = "vertex.tangent";
1037 break;
1038 case D3DDECLUSAGE_BINORMAL:
1039 attribName = "vertex.binormal";
1040 break;
1041 case D3DDECLUSAGE_TESSFACTOR:
1042 attribName = "vertex.tessfactor";
1043 break;
1044 case D3DDECLUSAGE_POSITIONT:
1045 attribName = "vertex.possitionT";
1046 break;
1047 case D3DDECLUSAGE_FOG:
1048 attribName = "vertex.fogcoord";
1049 break;
1050 case D3DDECLUSAGE_DEPTH:
1051 attribName = "vertex.depth";
1052 break;
1053 case D3DDECLUSAGE_SAMPLE:
1054 attribName = "vertex.sample";
1055 break;
1056 default:
1057 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
1060 sprintf(tmpLine, "ATTRIB ");
1061 vshader_program_add_param(This, dst, FALSE, tmpLine);
1062 if (This->namedArrays)
1063 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
1068 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
1070 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
1071 SHADER_BUFFER* buffer = arg->buffer;
1072 DWORD reg = arg->dst;
1074 shader_addline(buffer,
1075 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
1076 *((const float *)(arg->src + 0)),
1077 *((const float *)(arg->src + 1)),
1078 *((const float *)(arg->src + 2)),
1079 *((const float *)(arg->src + 3)) );
1081 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
1084 /** Handles transforming all D3DSIO_M?x? opcodes for
1085 Vertex shaders to ARB_vertex_program codes */
1086 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1088 int i;
1089 int nComponents = 0;
1090 SHADER_OPCODE_ARG tmpArg;
1092 /* Set constants for the temporary argument */
1093 tmpArg.shader = arg->shader;
1094 tmpArg.buffer = arg->buffer;
1095 tmpArg.src[0] = arg->src[0];
1097 switch(arg->opcode->opcode) {
1098 case D3DSIO_M4x4:
1099 nComponents = 4;
1100 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1101 break;
1102 case D3DSIO_M4x3:
1103 nComponents = 3;
1104 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1105 break;
1106 case D3DSIO_M3x4:
1107 nComponents = 4;
1108 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1109 break;
1110 case D3DSIO_M3x3:
1111 nComponents = 3;
1112 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1113 break;
1114 case D3DSIO_M3x2:
1115 nComponents = 2;
1116 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1117 break;
1118 default:
1119 break;
1122 for (i = 0; i < nComponents; i++) {
1123 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1124 tmpArg.src[1] = arg->src[1]+i;
1125 vshader_hw_map2gl(&tmpArg);
1129 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1130 or GLSL and send it to the card */
1131 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1132 IWineD3DVertexShader *iface,
1133 CONST DWORD *pFunction) {
1135 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1136 SHADER_BUFFER buffer;
1138 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1139 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1140 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1141 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1142 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1143 This->fixupVertexBufferSize = PGMSIZE;
1144 This->fixupVertexBuffer[0] = 0;
1146 buffer.buffer = This->device->fixupVertexBuffer;
1147 #else
1148 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1149 #endif
1150 buffer.bsize = 0;
1151 buffer.lineNo = 0;
1153 /* TODO: Optionally, generate the GLSL shader instead */
1154 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1155 /* Create the hw ARB shader */
1156 shader_addline(&buffer, "!!ARBvp1.0\n");
1158 /* Mesa supports only 95 constants */
1159 if (GL_VEND(MESA) || GL_VEND(WINE))
1160 This->baseShader.limits.constant_float =
1161 min(95, This->baseShader.limits.constant_float);
1163 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1164 This->baseShader.limits.constant_float,
1165 This->baseShader.limits.constant_float - 1);
1167 /** Call the base shader generation routine to generate most
1168 of the vertex shader string for us */
1169 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1171 shader_addline(&buffer, "END\n\0");
1173 /* TODO: change to resource.glObjectHandle or something like that */
1174 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1176 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1177 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1179 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1180 /* Create the program and check for errors */
1181 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1182 buffer.bsize, buffer.buffer));
1184 if (glGetError() == GL_INVALID_OPERATION) {
1185 GLint errPos;
1186 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1187 FIXME("HW VertexShader Error at position %d: %s\n",
1188 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1189 This->baseShader.prgId = -1;
1193 #if 1 /* if were using the data buffer of device then we don't need to free it */
1194 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1195 #endif
1198 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1200 * TODO: use the NV_vertex_program (or 1_1) extension
1201 * and specifics vendors (ARB_vertex_program??) variants for it
1203 return TRUE;
1206 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1207 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1209 /** Vertex Shader Temporary Registers */
1210 WINED3DSHADERVECTOR R[12];
1211 /*D3DSHADERSCALAR A0;*/
1212 WINED3DSHADERVECTOR A[1];
1213 /** temporary Vector for modifier management */
1214 WINED3DSHADERVECTOR d;
1215 WINED3DSHADERVECTOR s[3];
1216 /** parser datas */
1217 const DWORD* pToken = This->baseShader.function;
1218 const SHADER_OPCODE* curOpcode = NULL;
1219 /** functions parameters */
1220 WINED3DSHADERVECTOR* p[4];
1221 WINED3DSHADERVECTOR* p_send[4];
1222 DWORD i;
1224 /** init temporary register */
1225 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1227 /* vshader_program_parse(vshader); */
1228 #if 0 /* Must not be 1 in cvs */
1229 TRACE("Input:\n");
1230 TRACE_VSVECTOR(This->data->C[0]);
1231 TRACE_VSVECTOR(This->data->C[1]);
1232 TRACE_VSVECTOR(This->data->C[2]);
1233 TRACE_VSVECTOR(This->data->C[3]);
1234 TRACE_VSVECTOR(This->data->C[4]);
1235 TRACE_VSVECTOR(This->data->C[5]);
1236 TRACE_VSVECTOR(This->data->C[6]);
1237 TRACE_VSVECTOR(This->data->C[7]);
1238 TRACE_VSVECTOR(This->data->C[8]);
1239 TRACE_VSVECTOR(This->data->C[64]);
1240 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1241 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1242 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1243 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1244 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1245 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1246 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1247 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1248 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1249 #endif
1251 TRACE_VSVECTOR(vshader->data->C[64]);
1252 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1254 /* the first dword is the version tag */
1255 /* TODO: parse it */
1257 if (vshader_is_version_token(*pToken)) { /** version */
1258 ++pToken;
1260 while (D3DVS_END() != *pToken) {
1261 if (vshader_is_comment_token(*pToken)) { /** comment */
1262 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1263 ++pToken;
1264 pToken += comment_len;
1265 continue ;
1267 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1268 ++pToken;
1269 if (NULL == curOpcode) {
1270 i = 0;
1271 /* unknown current opcode ... */
1272 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1273 while (*pToken & 0x80000000) {
1274 if (i == 0) {
1275 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1277 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1278 vshader_program_dump_vs_param(*pToken, i);
1279 TRACE("\n");
1280 ++i;
1281 ++pToken;
1283 /* return FALSE; */
1284 } else {
1285 if (curOpcode->num_params > 0) {
1286 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1287 for (i = 0; i < curOpcode->num_params; ++i) {
1288 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1289 DWORD regtype = shader_get_regtype(pToken[i]);
1291 switch (regtype) {
1292 case D3DSPR_TEMP:
1293 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1294 p[i] = &R[reg];
1295 break;
1296 case D3DSPR_INPUT:
1297 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1298 p[i] = &input->V[reg];
1299 break;
1300 case D3DSPR_CONST:
1301 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1302 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1303 } else {
1304 p[i] = &This->data->C[reg];
1306 break;
1307 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1308 if (0 != reg) {
1309 ERR("cannot handle address registers != a0, forcing use of a0\n");
1310 reg = 0;
1312 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1313 p[i] = &A[reg];
1314 break;
1315 case D3DSPR_RASTOUT:
1316 switch (reg) {
1317 case D3DSRO_POSITION:
1318 p[i] = &output->oPos;
1319 break;
1320 case D3DSRO_FOG:
1321 p[i] = &output->oFog;
1322 break;
1323 case D3DSRO_POINT_SIZE:
1324 p[i] = &output->oPts;
1325 break;
1327 break;
1328 case D3DSPR_ATTROUT:
1329 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1330 p[i] = &output->oD[reg];
1331 break;
1332 case D3DSPR_TEXCRDOUT:
1333 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1334 p[i] = &output->oT[reg];
1335 break;
1336 /* TODO Decls and defs */
1337 #if 0
1338 case D3DSPR_DCL:
1339 case D3DSPR_DEF:
1340 #endif
1341 default:
1342 break;
1345 if (i > 0) { /* input reg */
1346 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1347 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1349 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1350 /* TRACE("p[%d] not swizzled\n", i); */
1351 p_send[i] = p[i];
1352 } else {
1353 DWORD swizzle_x = swizzle & 0x03;
1354 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1355 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1356 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1357 /* TRACE("p[%d] swizzled\n", i); */
1358 float* tt = (float*) p[i];
1359 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1360 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1361 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1362 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1363 p_send[i] = &s[i];
1365 } else { /* output reg */
1366 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1367 p_send[i] = p[i];
1368 } else {
1369 p_send[i] = &d; /* to be post-processed for modifiers management */
1375 switch (curOpcode->num_params) {
1376 case 0:
1377 curOpcode->soft_fct();
1378 break;
1379 case 1:
1380 curOpcode->soft_fct(p_send[0]);
1381 break;
1382 case 2:
1383 curOpcode->soft_fct(p_send[0], p_send[1]);
1384 break;
1385 case 3:
1386 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1387 break;
1388 case 4:
1389 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1390 break;
1391 case 5:
1392 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1393 break;
1394 case 6:
1395 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1396 break;
1397 default:
1398 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1401 /* check if output reg modifier post-process */
1402 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1403 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1404 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1405 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1406 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1408 #if 0
1409 TRACE_VSVECTOR(output->oPos);
1410 TRACE_VSVECTOR(output->oD[0]);
1411 TRACE_VSVECTOR(output->oD[1]);
1412 TRACE_VSVECTOR(output->oT[0]);
1413 TRACE_VSVECTOR(output->oT[1]);
1414 TRACE_VSVECTOR(R[0]);
1415 TRACE_VSVECTOR(R[1]);
1416 TRACE_VSVECTOR(R[2]);
1417 TRACE_VSVECTOR(R[3]);
1418 TRACE_VSVECTOR(R[4]);
1419 TRACE_VSVECTOR(R[5]);
1420 #endif
1422 /* to next opcode token */
1423 pToken += curOpcode->num_params;
1425 #if 0
1426 TRACE("End of current instruction:\n");
1427 TRACE_VSVECTOR(output->oPos);
1428 TRACE_VSVECTOR(output->oD[0]);
1429 TRACE_VSVECTOR(output->oD[1]);
1430 TRACE_VSVECTOR(output->oT[0]);
1431 TRACE_VSVECTOR(output->oT[1]);
1432 TRACE_VSVECTOR(R[0]);
1433 TRACE_VSVECTOR(R[1]);
1434 TRACE_VSVECTOR(R[2]);
1435 TRACE_VSVECTOR(R[3]);
1436 TRACE_VSVECTOR(R[4]);
1437 TRACE_VSVECTOR(R[5]);
1438 #endif
1440 #if 0 /* Must not be 1 in cvs */
1441 TRACE("Output:\n");
1442 TRACE_VSVECTOR(output->oPos);
1443 TRACE_VSVECTOR(output->oD[0]);
1444 TRACE_VSVECTOR(output->oD[1]);
1445 TRACE_VSVECTOR(output->oT[0]);
1446 TRACE_VSVECTOR(output->oT[1]);
1447 #endif
1448 return WINED3D_OK;
1451 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1452 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1453 FIXME("(%p) : stub\n", This);
1454 return WINED3D_OK;
1457 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1458 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1459 FIXME("(%p) : stub\n", This);
1460 return WINED3D_OK;
1463 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1464 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1465 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1466 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1467 return WINED3DERR_INVALIDCALL;
1469 if (NULL == pConstantData) {
1470 return WINED3DERR_INVALIDCALL;
1472 FIXME("(%p) : stub\n", This);
1473 return WINED3D_OK;
1476 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1477 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1478 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1479 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1480 return WINED3DERR_INVALIDCALL;
1482 if (NULL == pConstantData) {
1483 return WINED3DERR_INVALIDCALL;
1485 FIXME("(%p) : stub\n", This);
1486 return WINED3D_OK;
1489 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1490 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1491 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1492 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1493 return WINED3DERR_INVALIDCALL;
1495 if (NULL == pConstantData) {
1496 return WINED3DERR_INVALIDCALL;
1498 FIXME("(%p) : stub\n", This);
1499 return WINED3D_OK;
1502 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1503 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1504 FIXME("(%p) : stub\n", This);
1505 return WINED3D_OK;
1508 #endif
1510 /* *******************************************
1511 IWineD3DVertexShader IUnknown parts follow
1512 ******************************************* */
1513 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1515 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1516 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1517 if (IsEqualGUID(riid, &IID_IUnknown)
1518 || IsEqualGUID(riid, &IID_IWineD3DBase)
1519 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1520 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1521 IUnknown_AddRef(iface);
1522 *ppobj = This;
1523 return S_OK;
1525 *ppobj = NULL;
1526 return E_NOINTERFACE;
1529 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1530 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1531 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1532 return InterlockedIncrement(&This->ref);
1535 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1536 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1537 ULONG ref;
1538 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1539 ref = InterlockedDecrement(&This->ref);
1540 if (ref == 0) {
1541 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1542 HeapFree(GetProcessHeap(), 0, This);
1544 return ref;
1547 /* *******************************************
1548 IWineD3DVertexShader IWineD3DVertexShader parts follow
1549 ******************************************* */
1551 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1552 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1554 *parent = This->parent;
1555 IUnknown_AddRef(*parent);
1556 TRACE("(%p) : returning %p\n", This, *parent);
1557 return WINED3D_OK;
1560 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1561 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1562 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1563 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1564 TRACE("(%p) returning %p\n", This, *pDevice);
1565 return WINED3D_OK;
1568 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1569 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1570 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1572 if (NULL == pData) {
1573 *pSizeOfData = This->baseShader.functionLength;
1574 return WINED3D_OK;
1576 if (*pSizeOfData < This->baseShader.functionLength) {
1577 *pSizeOfData = This->baseShader.functionLength;
1578 return WINED3DERR_MOREDATA;
1580 if (NULL == This->baseShader.function) { /* no function defined */
1581 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1582 (*(DWORD **) pData) = NULL;
1583 } else {
1584 if(This->baseShader.functionLength == 0){
1587 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1588 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1590 return WINED3D_OK;
1593 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1594 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1595 const DWORD* pToken = pFunction;
1596 const SHADER_OPCODE* curOpcode = NULL;
1597 DWORD len = 0;
1598 DWORD i;
1599 TRACE("(%p) : Parsing programme\n", This);
1601 /* Initialise vertex input arrays */
1602 This->namedArrays = FALSE;
1603 This->declaredArrays = FALSE;
1604 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1605 This->arrayUsageMap[i] = -1;
1607 if (NULL != pToken) {
1608 while (D3DVS_END() != *pToken) {
1609 if (vshader_is_version_token(*pToken)) { /** version */
1610 vshader_set_version(This, *pToken);
1611 ++pToken;
1612 ++len;
1613 continue;
1615 if (vshader_is_comment_token(*pToken)) { /** comment */
1616 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1617 ++pToken;
1618 TRACE("//%s\n", (char*)pToken);
1619 pToken += comment_len;
1620 len += comment_len + 1;
1621 continue;
1623 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1624 ++pToken;
1625 ++len;
1626 if (NULL == curOpcode) {
1627 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1628 while (*pToken & 0x80000000) {
1629 /* unknown current opcode ... */
1630 FIXME("unrecognized opcode: %08lx", *pToken);
1631 ++pToken;
1632 ++len;
1633 TRACE("\n");
1636 } else {
1637 if (curOpcode->opcode == D3DSIO_DCL) {
1639 DWORD usage = *pToken;
1640 DWORD param = *(pToken + 1);
1642 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1643 shader_program_dump_decl_usage(usage, param);
1644 shader_dump_ins_modifiers(param);
1645 TRACE(" ");
1646 vshader_program_dump_vs_param(param, 0);
1647 pToken += 2;
1648 len += 2;
1650 } else
1651 if (curOpcode->opcode == D3DSIO_DEF) {
1652 TRACE("def c%lu = ", *pToken & 0xFF);
1653 ++pToken;
1654 ++len;
1655 TRACE("%f ,", *(float *)pToken);
1656 ++pToken;
1657 ++len;
1658 TRACE("%f ,", *(float *)pToken);
1659 ++pToken;
1660 ++len;
1661 TRACE("%f ,", *(float *)pToken);
1662 ++pToken;
1663 ++len;
1664 TRACE("%f", *(float *)pToken);
1665 ++pToken;
1666 ++len;
1667 } else {
1668 TRACE("%s", curOpcode->name);
1669 if (curOpcode->num_params > 0) {
1670 shader_dump_ins_modifiers(*pToken);
1671 TRACE(" ");
1672 vshader_program_dump_vs_param(*pToken, 0);
1673 ++pToken;
1674 ++len;
1675 for (i = 1; i < curOpcode->num_params; ++i) {
1676 TRACE(", ");
1677 vshader_program_dump_vs_param(*pToken, 1);
1678 ++pToken;
1679 ++len;
1683 TRACE("\n");
1686 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1687 } else {
1688 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1691 /* Handy for debugging using numbered arrays instead of named arrays */
1692 #if 1
1693 /* TODO: using numbered arrays for software shaders makes things easier */
1694 This->declaredArrays = TRUE;
1695 #endif
1697 /* named arrays and declared arrays are mutually exclusive */
1698 if (This->declaredArrays)
1699 This->namedArrays = FALSE;
1701 /* Generate HW shader in needed */
1702 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1703 #if 1
1704 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1705 #endif
1708 /* copy the function ... because it will certainly be released by application */
1709 if (NULL != pFunction) {
1710 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1711 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1712 } else {
1713 This->baseShader.function = NULL;
1715 return WINED3D_OK;
1718 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1720 /*** IUnknown methods ***/
1721 IWineD3DVertexShaderImpl_QueryInterface,
1722 IWineD3DVertexShaderImpl_AddRef,
1723 IWineD3DVertexShaderImpl_Release,
1724 /*** IWineD3DBase methods ***/
1725 IWineD3DVertexShaderImpl_GetParent,
1726 /*** IWineD3DBaseShader methods ***/
1727 IWineD3DVertexShaderImpl_SetFunction,
1728 /*** IWineD3DVertexShader methods ***/
1729 IWineD3DVertexShaderImpl_GetDevice,
1730 IWineD3DVertexShaderImpl_GetFunction