winspool: Implement EnumMonitorsA on top of EnumMonitorsW.
[wine/multimedia.git] / dlls / wined3d / vertexshader.c
blob26701f66fefca9255c21c98da7ad61963d35a8fc
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 */
365 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
366 FIXME(" : Stub\n");
369 void vshader_texkill(WINED3DSHADERVECTOR* d) {
370 FIXME(" : Stub\n");
373 void vshader_tex(WINED3DSHADERVECTOR* d) {
374 FIXME(" : Stub\n");
376 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
377 FIXME(" : Stub\n");
380 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
381 FIXME(" : Stub\n");
384 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
385 FIXME(" : Stub\n");
388 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
389 FIXME(" : Stub\n");
392 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393 FIXME(" : Stub\n");
396 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
397 FIXME(" : Stub\n");
400 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401 FIXME(" : Stub\n");
404 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405 FIXME(" : Stub\n");
408 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409 FIXME(" : Stub\n");
412 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
413 FIXME(" : Stub\n");
416 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
417 FIXME(" : Stub\n");
420 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
421 FIXME(" : Stub\n");
424 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
425 FIXME(" : Stub\n");
428 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
429 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
430 FIXME(" : Stub\n");
433 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
434 FIXME(" : Stub\n");
437 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
438 FIXME(" : Stub\n");
441 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
442 FIXME(" : Stub\n");
445 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
446 FIXME(" : Stub\n");
449 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
450 FIXME(" : Stub\n");
453 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
454 FIXME(" : Stub\n");
457 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
458 FIXME(" : Stub\n");
461 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
462 FIXME(" : Stub\n");
465 void vshader_call(WINED3DSHADERVECTOR* d) {
466 FIXME(" : Stub\n");
469 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
470 FIXME(" : Stub\n");
473 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
474 FIXME(" : Stub\n");
477 void vshader_ret(WINED3DSHADERVECTOR* d) {
478 FIXME(" : Stub\n");
481 void vshader_endloop(WINED3DSHADERVECTOR* d) {
482 FIXME(" : Stub\n");
485 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
486 FIXME(" : Stub\n");
489 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
490 FIXME(" : Stub\n");
493 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
494 FIXME(" : Stub\n");
497 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
498 FIXME(" : Stub\n");
501 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
502 FIXME(" : Stub\n");
505 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
506 FIXME(" : Stub\n");
509 void vshader_endrep(void) {
510 FIXME(" : Stub\n");
513 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
514 FIXME(" : Stub\n");
517 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
518 FIXME(" : Stub\n");
521 void vshader_else(WINED3DSHADERVECTOR* d) {
522 FIXME(" : Stub\n");
525 void vshader_label(WINED3DSHADERVECTOR* d) {
526 FIXME(" : Stub\n");
529 void vshader_endif(WINED3DSHADERVECTOR* d) {
530 FIXME(" : Stub\n");
533 void vshader_break(WINED3DSHADERVECTOR* d) {
534 FIXME(" : Stub\n");
537 void vshader_breakc(WINED3DSHADERVECTOR* d) {
538 FIXME(" : Stub\n");
541 void vshader_mova(WINED3DSHADERVECTOR* d) {
542 FIXME(" : Stub\n");
545 void vshader_defb(WINED3DSHADERVECTOR* d) {
546 FIXME(" : Stub\n");
549 void vshader_defi(WINED3DSHADERVECTOR* d) {
550 FIXME(" : Stub\n");
553 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
554 FIXME(" : Stub\n");
557 void vshader_dsx(WINED3DSHADERVECTOR* d) {
558 FIXME(" : Stub\n");
561 void vshader_dsy(WINED3DSHADERVECTOR* d) {
562 FIXME(" : Stub\n");
565 void vshader_texldd(WINED3DSHADERVECTOR* d) {
566 FIXME(" : Stub\n");
569 void vshader_setp(WINED3DSHADERVECTOR* d) {
570 FIXME(" : Stub\n");
573 void vshader_texldl(WINED3DSHADERVECTOR* d) {
574 FIXME(" : Stub\n");
577 void vshader_breakp(WINED3DSHADERVECTOR* d) {
578 FIXME(" : Stub\n");
583 * log, exp, frc, m*x* seems to be macros ins ... to see
585 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
586 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, 0, 0},
587 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, 0, 0},
588 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, 0, 0},
589 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, 0, 0},
590 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, 0, 0},
591 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, 0, 0},
592 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, 0, 0},
593 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, 0, 0},
594 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, 0, 0},
595 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, 0, 0},
596 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, 0, 0},
597 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, 0, 0},
598 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, 0, 0},
599 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, 0, 0},
600 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, 0, 0},
601 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, 0, 0},
602 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, 0, 0},
603 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, 0, 0},
604 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, 0, 0},
605 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, 0, 0},
606 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, 0, 0},
607 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
608 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
609 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
610 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
611 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
612 /** FIXME: use direct access so add the others opcodes as stubs */
613 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
614 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 */
615 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, 0, 0},
616 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, 0, 0},
617 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, 0, 0},
618 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, 0, 0},
619 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, 0, 0},
620 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, 0, 0},
621 /* DCL is a specil operation */
622 {D3DSIO_DCL, "dcl", NULL, 1, vshader_dcl, 0, 0},
623 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, 0, 0},
624 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, 0, 0},
625 /* TODO: sng can possibly be performed as
626 RCP tmp, vec
627 MUL out, tmp, vec*/
628 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, 0, 0},
629 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
630 DP3 tmp , vec, vec;
631 RSQ tmp, tmp.x;
632 MUL vec.xyz, vec, tmp;
633 but I think this is better because it accounts for w properly.
634 DP3 tmp , vec, vec;
635 RSQ tmp, tmp.x;
636 MUL vec, vec, tmp;
639 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, 0, 0},
640 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, 0, 0},
641 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 2, vshader_rep, 0, 0},
642 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, 0, 0},
643 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 2, vshader_if, 0, 0},
644 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, 0, 0},
645 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 2, vshader_else, 0, 0},
646 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 2, vshader_endif, 0, 0},
647 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 2, vshader_break, 0, 0},
648 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, 0, 0},
649 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, 0, 0},
650 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, 0, 0},
651 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, 0, 0},
653 {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL, 1, vshader_texcoord, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
654 {D3DSIO_TEXCOORD, "texcrd", GLNAME_REQUIRE_GLSL, 2, vshader_texcoord, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
655 {D3DSIO_TEXKILL, "texkill", GLNAME_REQUIRE_GLSL, 1, vshader_texkill, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
656 {D3DSIO_TEX, "tex", GLNAME_REQUIRE_GLSL, 1, vshader_tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
657 {D3DSIO_TEX, "texld", GLNAME_REQUIRE_GLSL, 2, vshader_texld, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
658 {D3DSIO_TEXBEM, "texbem", GLNAME_REQUIRE_GLSL, 2, vshader_texbem, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
659 {D3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 2, vshader_texbeml, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
660 {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2ar, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
661 {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2gb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
662 {D3DSIO_TEXM3x2PAD, "texm3x2pad", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2pad, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
663 {D3DSIO_TEXM3x2TEX, "texm3x2tex", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
664 {D3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3diff, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
665 {D3DSIO_TEXM3x3SPEC, "texm3x3spec", GLNAME_REQUIRE_GLSL, 3, vshader_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
668 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, 0, 0},
669 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, 0, 0},
670 {D3DSIO_CND, "cnd", GLNAME_REQUIRE_GLSL, 4, vshader_cnd, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
671 /* def is a special operation */
672 {D3DSIO_DEF, "def", NULL, 5, vshader_def, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
673 {D3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 2, vshader_texreg2rgb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
677 {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
679 {D3DSIO_CMP, "cmp", GLNAME_REQUIRE_GLSL, 4, vshader_cmp, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
680 {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 3, vshader_bem, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
681 /* TODO: dp2add can be made out of multiple instuctions */
682 {D3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 2, vshader_dp2add, 0, 0},
683 {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 2, vshader_dsx, 0, 0},
684 {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 2, vshader_dsy, 0, 0},
685 {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 2, vshader_texldd, 0, 0},
686 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, 0, 0},
687 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, 0, 0},
688 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 2, vshader_breakp, 0, 0},
689 {D3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, vshader_nop, 0, 0},
690 {0, NULL, NULL, 0, NULL, 0, 0}
694 inline static const SHADER_OPCODE* vshader_program_get_opcode(IWineD3DVertexShaderImpl *This, const DWORD code) {
695 DWORD i = 0;
696 const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
698 /** TODO: use dichotomic search or hash table */
699 while (NULL != shader_ins[i].name) {
700 if ((code & D3DSI_OPCODE_MASK) == shader_ins[i].opcode) {
701 return &shader_ins[i];
703 ++i;
705 FIXME("Unsupported opcode %lx\n",code);
706 return NULL;
709 inline static void vshader_program_dump_param(const DWORD param, int input) {
710 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
711 static const char swizzle_reg_chars[] = "xyzw";
713 DWORD reg = param & 0x00001FFF;
714 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
716 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
718 switch (regtype) {
719 case D3DSPR_TEMP:
720 TRACE("R[%lu]", reg);
721 break;
722 case D3DSPR_INPUT:
723 TRACE("v%lu", reg);
724 break;
725 case D3DSPR_CONST:
726 TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
727 break;
728 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
729 TRACE("a[%lu]", reg);
730 break;
731 case D3DSPR_RASTOUT:
732 TRACE("%s", rastout_reg_names[reg]);
733 break;
734 case D3DSPR_ATTROUT:
735 TRACE("oD[%lu]", reg);
736 break;
737 case D3DSPR_TEXCRDOUT:
738 TRACE("oT[%lu]", reg);
739 break;
740 default:
741 FIXME("Unknown %lu %u reg %lu\n",regtype, D3DSPR_ATTROUT, reg);
742 break;
745 if (!input) {
746 /** operand output */
747 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
748 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
749 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
750 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
751 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
753 } else {
754 /** operand input */
755 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
756 DWORD swizzle_x = swizzle & 0x03;
757 DWORD swizzle_y = (swizzle >> 2) & 0x03;
758 DWORD swizzle_z = (swizzle >> 4) & 0x03;
759 DWORD swizzle_w = (swizzle >> 6) & 0x03;
761 * swizzle bits fields:
762 * WWZZYYXX
764 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
765 if (swizzle_x == swizzle_y &&
766 swizzle_x == swizzle_z &&
767 swizzle_x == swizzle_w) {
768 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
769 } else {
770 TRACE(".%c%c%c%c",
771 swizzle_reg_chars[swizzle_x],
772 swizzle_reg_chars[swizzle_y],
773 swizzle_reg_chars[swizzle_z],
774 swizzle_reg_chars[swizzle_w]);
780 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
781 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
782 static const char swizzle_reg_chars[] = "xyzw";
783 /* the unknown mask is for bits not yet accounted for by any other mask... */
784 #define UNKNOWN_MASK 0xC000
786 /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
787 #define EXTENDED_REG 0x1800
789 DWORD reg = param & D3DSP_REGNUM_MASK; /* 0x00001FFF; isn't this D3DSP_REGNUM_MASK? */
790 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
792 if(param & UNKNOWN_MASK) { /* if this register has any of the unknown bits set then report them*/
793 FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype, (param & EXTENDED_REG), param & UNKNOWN_MASK);
796 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
798 switch (regtype /*<< D3DSP_REGTYPE_SHIFT*/) {
799 case D3DSPR_TEMP:
800 TRACE("r%lu", reg);
801 break;
802 case D3DSPR_INPUT:
803 TRACE("v%lu", reg);
804 break;
805 case D3DSPR_CONST:
806 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
807 break;
808 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
809 TRACE("a%lu", reg);
810 break;
811 case D3DSPR_RASTOUT:
812 TRACE("%s", rastout_reg_names[reg]);
813 break;
814 case D3DSPR_ATTROUT:
815 TRACE("oD%lu", reg);
816 break;
817 case D3DSPR_TEXCRDOUT:
818 TRACE("oT%lu", reg);
819 break;
820 case D3DSPR_CONSTINT:
821 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
822 break;
823 case D3DSPR_CONSTBOOL:
824 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
825 break;
826 case D3DSPR_LABEL:
827 TRACE("l%lu", reg);
828 break;
829 case D3DSPR_LOOP:
830 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
831 break;
832 default:
833 FIXME("Unknown %lu reg %lu\n",regtype, reg);
834 break;
837 if (!input) {
838 /** operand output */
839 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
840 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
841 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
842 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
843 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
845 } else {
846 /** operand input */
847 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
848 DWORD swizzle_x = swizzle & 0x03;
849 DWORD swizzle_y = (swizzle >> 2) & 0x03;
850 DWORD swizzle_z = (swizzle >> 4) & 0x03;
851 DWORD swizzle_w = (swizzle >> 6) & 0x03;
853 * swizzle bits fields:
854 * WWZZYYXX
856 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
857 if (swizzle_x == swizzle_y &&
858 swizzle_x == swizzle_z &&
859 swizzle_x == swizzle_w) {
860 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
861 } else {
862 TRACE(".%c%c%c%c",
863 swizzle_reg_chars[swizzle_x],
864 swizzle_reg_chars[swizzle_y],
865 swizzle_reg_chars[swizzle_z],
866 swizzle_reg_chars[swizzle_w]);
872 inline static void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl *This, DWORD token) {
873 TRACE("dcl_");
874 switch(token & 0xFFFF) {
875 case D3DDECLUSAGE_POSITION:
876 TRACE("%s%ld ", "position",(token & 0xF0000) >> 16);
877 break;
878 case D3DDECLUSAGE_BLENDINDICES:
879 TRACE("%s ", "blend");
880 break;
881 case D3DDECLUSAGE_BLENDWEIGHT:
882 TRACE("%s ", "weight");
883 break;
884 case D3DDECLUSAGE_NORMAL:
885 TRACE("%s%ld ", "normal",(token & 0xF0000) >> 16);
886 break;
887 case D3DDECLUSAGE_PSIZE:
888 TRACE("%s ", "psize");
889 break;
890 case D3DDECLUSAGE_COLOR:
891 if((token & 0xF0000) >> 16 == 0) {
892 TRACE("%s ", "color");
893 } else {
894 TRACE("%s ", "specular");
896 break;
897 case D3DDECLUSAGE_TEXCOORD:
898 TRACE("%s%ld ", "texture", (token & 0xF0000) >> 16);
899 break;
900 case D3DDECLUSAGE_TANGENT:
901 TRACE("%s ", "tangent");
902 break;
903 case D3DDECLUSAGE_BINORMAL:
904 TRACE("%s ", "binormal");
905 break;
906 case D3DDECLUSAGE_TESSFACTOR:
907 TRACE("%s ", "tessfactor");
908 break;
909 case D3DDECLUSAGE_POSITIONT:
910 TRACE("%s%ld ", "positionT",(token & 0xF0000) >> 16);
911 break;
912 case D3DDECLUSAGE_FOG:
913 TRACE("%s ", "fog");
914 break;
915 case D3DDECLUSAGE_DEPTH:
916 TRACE("%s ", "depth");
917 break;
918 case D3DDECLUSAGE_SAMPLE:
919 TRACE("%s ", "sample");
920 break;
921 default:
922 FIXME("Unrecognised dcl %08lx", token & 0xFFFF);
926 inline static BOOL vshader_is_version_token(DWORD token) {
927 return 0xFFFE0000 == (token & 0xFFFE0000);
930 inline static BOOL vshader_is_comment_token(DWORD token) {
931 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
934 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
935 /** operand output */
936 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
937 strcat(hwLine, ".");
938 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
939 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
940 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
941 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
945 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
946 static const char swizzle_reg_chars_color_fix[] = "zyxw";
947 static const char swizzle_reg_chars[] = "xyzw";
948 const char* swizzle_regs = NULL;
949 char tmpReg[255];
951 /** operand input */
952 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
953 DWORD swizzle_x = swizzle & 0x03;
954 DWORD swizzle_y = (swizzle >> 2) & 0x03;
955 DWORD swizzle_z = (swizzle >> 4) & 0x03;
956 DWORD swizzle_w = (swizzle >> 6) & 0x03;
958 if (is_color) {
959 swizzle_regs = swizzle_reg_chars_color_fix;
960 } else {
961 swizzle_regs = swizzle_reg_chars;
965 * swizzle bits fields:
966 * WWZZYYXX
968 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
969 if (is_color) {
970 sprintf(tmpReg, ".%c%c%c%c",
971 swizzle_regs[swizzle_x],
972 swizzle_regs[swizzle_y],
973 swizzle_regs[swizzle_z],
974 swizzle_regs[swizzle_w]);
975 strcat(hwLine, tmpReg);
977 return ;
979 if (swizzle_x == swizzle_y &&
980 swizzle_x == swizzle_z &&
981 swizzle_x == swizzle_w)
983 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
984 strcat(hwLine, tmpReg);
985 } else {
986 sprintf(tmpReg, ".%c%c%c%c",
987 swizzle_regs[swizzle_x],
988 swizzle_regs[swizzle_y],
989 swizzle_regs[swizzle_z],
990 swizzle_regs[swizzle_w]);
991 strcat(hwLine, tmpReg);
995 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
996 /* oPos, oFog and oPts in D3D */
997 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
999 DWORD reg = param & 0x00001FFF;
1000 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1001 char tmpReg[255];
1002 BOOL is_color = FALSE;
1004 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
1005 strcat(hwLine, " -");
1006 } else {
1007 strcat(hwLine, " ");
1010 switch (regtype) {
1011 case D3DSPR_TEMP:
1012 sprintf(tmpReg, "T%lu", reg);
1013 strcat(hwLine, tmpReg);
1014 break;
1015 case D3DSPR_INPUT:
1016 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
1017 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
1018 is_color = TRUE;
1020 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1021 if (This->namedArrays) {
1022 sprintf(tmpReg, "namedVertex%lu", reg);
1023 } else {
1024 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1025 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
1027 strcat(hwLine, tmpReg);
1028 break;
1029 case D3DSPR_CONST:
1030 /* FIXME: some constants are named so we need a constants map*/
1031 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
1032 if (param & D3DVS_ADDRMODE_RELATIVE) {
1033 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
1035 sprintf(tmpReg, "const%lu", reg);
1036 } else {
1037 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
1039 strcat(hwLine, tmpReg);
1040 break;
1041 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
1042 sprintf(tmpReg, "A%lu", reg);
1043 strcat(hwLine, tmpReg);
1044 break;
1045 case D3DSPR_RASTOUT:
1046 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
1047 strcat(hwLine, tmpReg);
1048 break;
1049 case D3DSPR_ATTROUT:
1050 if (reg==0) {
1051 strcat(hwLine, "result.color.primary");
1052 } else {
1053 strcat(hwLine, "result.color.secondary");
1055 break;
1056 case D3DSPR_TEXCRDOUT:
1057 sprintf(tmpReg, "result.texcoord[%lu]", reg);
1058 strcat(hwLine, tmpReg);
1059 break;
1060 default:
1061 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1062 break;
1065 if (!is_input) {
1066 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1067 } else {
1068 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1072 DWORD MacroExpansion[4*4];
1074 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1075 int i;
1076 int nComponents = 0;
1077 DWORD opcode =0;
1078 switch(macro_opcode) {
1079 case D3DSIO_M4x4:
1080 nComponents = 4;
1081 opcode = D3DSIO_DP4;
1082 break;
1083 case D3DSIO_M4x3:
1084 nComponents = 3;
1085 opcode = D3DSIO_DP4;
1086 break;
1087 case D3DSIO_M3x4:
1088 nComponents = 4;
1089 opcode = D3DSIO_DP3;
1090 break;
1091 case D3DSIO_M3x3:
1092 nComponents = 3;
1093 opcode = D3DSIO_DP3;
1094 break;
1095 case D3DSIO_M3x2:
1096 nComponents = 2;
1097 opcode = D3DSIO_DP3;
1098 break;
1099 default:
1100 break;
1102 for (i = 0; i < nComponents; i++) {
1103 MacroExpansion[i*4+0] = opcode;
1104 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1105 MacroExpansion[i*4+2] = *(args+1);
1106 MacroExpansion[i*4+3] = (*(args+2))+i;
1108 return nComponents;
1111 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
1113 switch(usage & 0xFFFF) {
1114 case D3DDECLUSAGE_POSITION:
1115 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1116 TRACE("Setting position to %d\n", arrayNo);
1117 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1118 This->namedArrays = TRUE;
1119 } else {
1120 /* TODO: position indexes go from 0-8!!*/
1121 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1122 /* robots uses positions up to 8, the position arrays are just packed.*/
1123 if ((usage & 0xF0000) >> 16 > 1) {
1124 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1126 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1127 This->declaredArrays = TRUE;
1129 break;
1130 case D3DDECLUSAGE_BLENDINDICES:
1131 /* not supported by openGL */
1132 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1133 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1134 This->declaredArrays = TRUE;
1135 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1136 break;
1137 case D3DDECLUSAGE_BLENDWEIGHT:
1138 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1139 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1140 This->namedArrays = TRUE;
1141 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1142 break;
1143 case D3DDECLUSAGE_NORMAL:
1144 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1145 TRACE("Setting normal to %d\n", arrayNo);
1146 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1147 This->namedArrays = TRUE;
1148 } else {
1149 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1150 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1151 This->declaredArrays = TRUE;
1153 break;
1154 case D3DDECLUSAGE_PSIZE:
1155 TRACE("Setting PSIZE to %d\n", arrayNo);
1156 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1157 This->namedArrays = TRUE;
1158 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1159 break;
1160 case D3DDECLUSAGE_COLOR:
1161 if((usage & 0xF0000) >> 16 == 0) {
1162 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1163 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1164 This->namedArrays = TRUE;
1165 } else {
1166 TRACE("Setting SPECULAR to %d\n", arrayNo);
1167 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1168 This->namedArrays = TRUE;
1170 break;
1171 case D3DDECLUSAGE_TEXCOORD:
1172 This->namedArrays = TRUE;
1173 /* only 7 texture coords have been designed for, so run a quick sanity check */
1174 if ((usage & 0xF0000) >> 16 > 7) {
1175 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1176 } else {
1177 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1178 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1180 break;
1181 /* The following aren't supported by openGL,
1182 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1183 this should be caught in the first pass */
1184 case D3DDECLUSAGE_TANGENT:
1185 TRACE("Setting TANGENT to %d\n", arrayNo);
1186 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1187 This->declaredArrays = TRUE;
1188 break;
1189 case D3DDECLUSAGE_BINORMAL:
1190 TRACE("Setting BINORMAL to %d\n", arrayNo);
1191 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1192 This->declaredArrays = TRUE;
1193 break;
1194 case D3DDECLUSAGE_TESSFACTOR:
1195 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1196 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1197 This->declaredArrays = TRUE;
1198 break;
1199 case D3DDECLUSAGE_POSITIONT:
1200 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1201 FIXME("Setting positiont to %d\n", arrayNo);
1202 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1203 This->namedArrays = TRUE;
1204 } else {
1205 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1206 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1207 This->declaredArrays = TRUE;
1208 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1210 break;
1211 case D3DDECLUSAGE_FOG:
1212 /* supported by OpenGL */
1213 TRACE("Setting FOG to %d\n", arrayNo);
1214 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1215 This->namedArrays = TRUE;
1216 break;
1217 case D3DDECLUSAGE_DEPTH:
1218 TRACE("Setting DEPTH to %d\n", arrayNo);
1219 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1220 This->declaredArrays = TRUE;
1221 break;
1222 case D3DDECLUSAGE_SAMPLE:
1223 TRACE("Setting SAMPLE to %d\n", arrayNo);
1224 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1225 This->declaredArrays = TRUE;
1226 break;
1227 default:
1228 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1233 * Function parser ...
1236 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1237 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1238 const DWORD* pToken = pFunction;
1239 const DWORD* pSavedToken = NULL;
1240 const SHADER_OPCODE* curOpcode = NULL;
1241 int nRemInstr = -1;
1242 DWORD i;
1243 unsigned lineNum = 0;
1244 char *pgmStr = NULL;
1245 char tmpLine[255];
1246 DWORD nUseAddressRegister = 0;
1247 DWORD nUseTempRegister = 0;
1248 DWORD regtype;
1249 DWORD reg;
1250 BOOL tmpsUsed[32];
1251 #if 0 /* TODO: loope register (just another address register ) */
1252 BOOL hasLoops = FALSE;
1253 #endif
1255 #define PGMSIZE 65535
1256 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1257 int pgmLength = 0;
1259 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1260 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1261 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1262 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1263 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1264 This->fixupVertexBufferSize = PGMSIZE;
1265 This->fixupVertexBuffer[0] = 0;
1267 pgmStr = This->device->fixupVertexBuffer;
1268 #endif
1269 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1270 int _tmpLineLen = strlen(_tmpLine); \
1271 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1272 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); \
1273 } else { \
1274 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1276 pgmLength += _tmpLineLen; \
1279 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1280 /* Initialise the shader */
1281 This->namedArrays = FALSE;
1282 This->declaredArrays = FALSE;
1283 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1284 This->arrayUsageMap[i] = -1;
1286 /* set all the tmpsUsed to not used */
1287 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1289 /* 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 */
1290 This->highestConstant = -1;
1293 * First pass to determine what we need to declare:
1294 * - Temporary variables
1295 * - Address variables
1297 if (NULL != pToken) {
1298 while (D3DVS_END() != *pToken) {
1299 if (vshader_is_version_token(*pToken)) {
1300 /** skip version */
1301 ++pToken;
1302 continue;
1304 if (vshader_is_comment_token(*pToken)) { /** comment */
1305 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1306 ++pToken;
1307 pToken += comment_len;
1308 continue;
1310 curOpcode = vshader_program_get_opcode(This, *pToken);
1311 ++pToken;
1312 /* TODO: dcl's */
1313 /* TODO: Consts */
1315 if (NULL == curOpcode) {
1316 while (*pToken & 0x80000000) {
1317 FIXME("unrecognized opcode: %08lx\n", *pToken);
1318 /* skip unrecognized opcode */
1319 ++pToken;
1321 } else {
1322 if (curOpcode->opcode == D3DSIO_DCL){
1323 INT usage = *pToken++;
1324 INT arrayNo = (*pToken++ & 0x00001FFF);
1325 parse_decl_usage(This, usage, arrayNo);
1326 } else if(curOpcode->opcode == D3DSIO_DEF) {
1327 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1328 FIXME("Constant %ld\n", *pToken & 0xFF);
1329 ++pToken;
1330 ++pToken;
1331 ++pToken;
1332 ++pToken;
1333 ++pToken;
1335 } else {
1336 /* Check to see if and tmp or addressing redisters are used */
1337 if (curOpcode->num_params > 0) {
1338 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1339 reg = ((*pToken) & 0x00001FFF);
1340 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1341 if (D3DSPR_TEMP == regtype){
1342 tmpsUsed[reg] = TRUE;
1343 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1345 ++pToken;
1346 for (i = 1; i < curOpcode->num_params; ++i) {
1347 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1348 reg = ((*pToken) & 0x00001FFF);
1349 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1350 if (D3DSPR_TEMP == regtype){
1351 tmpsUsed[reg] = TRUE;
1352 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1354 ++pToken;
1358 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1359 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1360 FIXME("This shader requires gl shader language support\n");
1361 #if 0
1362 This->shaderLanguage = GLSHADER_GLSL;
1363 #endif
1365 #endif
1369 #if 1
1370 #define VSHADER_ALWAYS_NUMBERED
1371 #endif
1373 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1374 /* TODO: using numbered arrays for software shaders makes things easier */
1375 This->declaredArrays = TRUE;
1376 #endif
1378 /* named arrays and declared arrays are mutually exclusive */
1379 if (This->declaredArrays) {
1380 This->namedArrays = FALSE;
1382 /* TODO: validate
1383 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1384 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1387 /** second pass, now generate */
1388 pToken = pFunction;
1390 if (NULL != pToken) {
1391 while (1) {
1392 tmpLine[0] = 0;
1393 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1394 /* Macro is finished, continue normal path */
1395 pToken = pSavedToken;
1396 if (D3DVS_END() == *pToken)
1397 break;
1399 if (vshader_is_version_token(*pToken)) { /** version */
1400 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1401 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1402 int numTemps;
1403 int numConstants;
1405 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1407 /* Each release of vertex shaders has had different numbers of temp registers */
1408 switch (version) {
1409 case 10:
1410 case 11: numTemps=12;
1411 numConstants=96;/* min(GL_LIMITS(constants),96) */
1412 strcpy(tmpLine, "!!ARBvp1.0\n");
1413 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1414 break;
1415 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1416 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1417 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)*/
1418 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1419 numConstants=96; /* min(GL_LIMITS(constants),256) */
1420 strcpy(tmpLine, "!!ARBvp1.0\n");
1421 FIXME("No work done yet to support vs2.0 in hw\n");
1422 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1423 break;
1424 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1425 numConstants=96; /* min(GL_LIMITS(constants),256) */
1426 strcpy(tmpLine, "!!ARBvp1.0\n");
1427 FIXME("No work done yet to support vs2.1 in hw\n");
1428 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1429 break;
1430 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1431 numConstants=96;/* min(GL_LIMITS(constants),256) */
1432 strcpy(tmpLine, "!!ARBvp3.0\n");
1433 FIXME("No work done yet to support vs3.0 in hw\n");
1434 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1435 break;
1436 default:
1437 numTemps=12;/* min(GL_LIMITS(temps),12) */
1438 numConstants=96;/* min(GL_LIMITS(constants),96) */
1439 strcpy(tmpLine, "!!ARBvp1.0\n");
1440 FIXME("Unrecognized vertex shader version %d!\n", version);
1442 PNSTRCAT(pgmStr, tmpLine);
1444 ++lineNum;
1446 /* This should be a bitmap so that only temp registers that are used are declared. */
1447 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1448 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1449 sprintf(tmpLine, "TEMP T%ld;\n", i);
1450 ++lineNum;
1451 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1452 PNSTRCAT(pgmStr, tmpLine);
1456 /* TODO: loop register counts as an address register */
1457 for (i = 0; i < nUseAddressRegister; i++) {
1458 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1459 ++lineNum;
1460 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1461 PNSTRCAT(pgmStr, tmpLine);
1464 /* Due to the dynamic constants binding mechanism, we need to declare
1465 * all the constants for relative addressing. */
1466 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1467 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1468 numConstants = 95;
1470 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1471 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1473 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1474 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1475 PNSTRCAT(pgmStr, tmpLine);
1477 ++lineNum;
1479 ++pToken;
1480 continue;
1482 if (vshader_is_comment_token(*pToken)) { /** comment */
1483 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1484 ++pToken;
1485 FIXME("#%s\n", (char*)pToken);
1486 pToken += comment_len;
1487 continue;
1490 curOpcode = vshader_program_get_opcode(This, *pToken);
1491 ++pToken;
1492 if (NULL == curOpcode) {
1493 /* unknown current opcode ... (shouldn't be any!) */
1494 while (*pToken & 0x80000000) {
1495 FIXME("unrecognized opcode: %08lx\n", *pToken);
1496 ++pToken;
1498 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1499 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1501 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1502 pToken += curOpcode->num_params;
1503 } else {
1504 /* Build opcode for GL vertex_program */
1505 switch (curOpcode->opcode) {
1506 case D3DSIO_NOP:
1507 continue;
1508 case D3DSIO_MOV:
1509 /* Address registers must be loaded with the ARL instruction */
1510 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1511 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1512 strcpy(tmpLine, "ARL");
1513 break;
1514 } else
1515 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1517 /* fall through */
1518 case D3DSIO_ADD:
1519 case D3DSIO_SUB:
1520 case D3DSIO_MAD:
1521 case D3DSIO_MUL:
1522 case D3DSIO_RCP:
1523 case D3DSIO_RSQ:
1524 case D3DSIO_DP3:
1525 case D3DSIO_DP4:
1526 case D3DSIO_MIN:
1527 case D3DSIO_MAX:
1528 case D3DSIO_SLT:
1529 case D3DSIO_SGE:
1530 case D3DSIO_LIT:
1531 case D3DSIO_DST:
1532 case D3DSIO_FRC:
1533 case D3DSIO_EXPP:
1534 case D3DSIO_LOGP:
1535 case D3DSIO_EXP:
1536 case D3DSIO_LOG:
1537 strcpy(tmpLine, curOpcode->glname);
1538 break;
1539 case D3DSIO_M4x4:
1540 case D3DSIO_M4x3:
1541 case D3DSIO_M3x4:
1542 case D3DSIO_M3x3:
1543 case D3DSIO_M3x2:
1544 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1545 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1546 /* Save point to next instruction */
1547 pSavedToken = pToken + 3;
1548 /* Execute expanded macro */
1549 pToken = MacroExpansion;
1550 continue;
1551 /* dcl and def are handeled in the first pass */
1552 case D3DSIO_DCL:
1553 if (This->namedArrays) {
1554 const char* attribName = "undefined";
1555 switch(*pToken & 0xFFFF) {
1556 case D3DDECLUSAGE_POSITION:
1557 attribName = "vertex.position";
1558 break;
1559 case D3DDECLUSAGE_BLENDINDICES:
1560 /* not supported by openGL */
1561 attribName = "vertex.blend";
1562 break;
1563 case D3DDECLUSAGE_BLENDWEIGHT:
1564 attribName = "vertex.weight";
1565 break;
1566 case D3DDECLUSAGE_NORMAL:
1567 attribName = "vertex.normal";
1568 break;
1569 case D3DDECLUSAGE_PSIZE:
1570 attribName = "vertex.psize";
1571 break;
1572 case D3DDECLUSAGE_COLOR:
1573 if((*pToken & 0xF0000) >> 16 == 0) {
1574 attribName = "vertex.color";
1575 } else {
1576 attribName = "vertex.color.secondary";
1578 break;
1579 case D3DDECLUSAGE_TEXCOORD:
1581 char tmpChar[100];
1582 tmpChar[0] = 0;
1583 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1584 attribName = tmpChar;
1585 break;
1587 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1588 case D3DDECLUSAGE_TANGENT:
1589 attribName = "vertex.tangent";
1590 break;
1591 case D3DDECLUSAGE_BINORMAL:
1592 attribName = "vertex.binormal";
1593 break;
1594 case D3DDECLUSAGE_TESSFACTOR:
1595 attribName = "vertex.tessfactor";
1596 break;
1597 case D3DDECLUSAGE_POSITIONT:
1598 attribName = "vertex.possitionT";
1599 break;
1600 case D3DDECLUSAGE_FOG:
1601 attribName = "vertex.fogcoord";
1602 break;
1603 case D3DDECLUSAGE_DEPTH:
1604 attribName = "vertex.depth";
1605 break;
1606 case D3DDECLUSAGE_SAMPLE:
1607 attribName = "vertex.sample";
1608 break;
1609 default:
1610 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1613 char tmpChar[80];
1614 ++pToken;
1615 sprintf(tmpLine, "ATTRIB ");
1616 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1617 sprintf(tmpChar," = %s", attribName);
1618 strcat(tmpLine, tmpChar);
1619 strcat(tmpLine,";\n");
1620 ++lineNum;
1621 if (This->namedArrays) {
1622 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1623 PNSTRCAT(pgmStr, tmpLine);
1625 } else {
1626 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1629 } else {
1630 /* eat the token so it doesn't generate a warning */
1631 ++pToken;
1633 ++pToken;
1634 continue;
1635 case D3DSIO_DEF:
1637 char tmpChar[80];
1638 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1639 ++pToken;
1640 sprintf(tmpChar,"%f ,", *(float *)pToken);
1641 strcat(tmpLine, tmpChar);
1642 ++pToken;
1643 sprintf(tmpChar,"%f ,", *(float *)pToken);
1644 strcat(tmpLine, tmpChar);
1645 ++pToken;
1646 sprintf(tmpChar,"%f ,", *(float *)pToken);
1647 strcat(tmpLine, tmpChar);
1648 ++pToken;
1649 sprintf(tmpChar,"%f}", *(float *)pToken);
1650 strcat(tmpLine, tmpChar);
1652 strcat(tmpLine,";\n");
1653 ++lineNum;
1654 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1655 PNSTRCAT(pgmStr, tmpLine);
1657 ++pToken;
1658 continue;
1660 default:
1661 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1662 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1663 } else {
1664 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1667 if (curOpcode->num_params > 0) {
1668 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1670 ++pToken;
1671 for (i = 1; i < curOpcode->num_params; ++i) {
1672 strcat(tmpLine, ",");
1673 vshader_program_add_param(This, *pToken, TRUE, tmpLine);
1674 ++pToken;
1677 strcat(tmpLine,";\n");
1678 ++lineNum;
1679 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1680 PNSTRCAT(pgmStr, tmpLine);
1684 strcpy(tmpLine, "END\n");
1685 ++lineNum;
1686 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1687 PNSTRCAT(pgmStr, tmpLine);
1690 /* finally null terminate the pgmStr*/
1691 pgmStr[pgmLength] = 0;
1693 /* Check that Vertex Shaders are supported */
1694 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1695 /* Create the hw shader */
1696 /* TODO: change to resource.glObjectHandel or something like that */
1697 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1698 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1699 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1701 /* Create the program and check for errors */
1702 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1703 if (glGetError() == GL_INVALID_OPERATION) {
1704 GLint errPos;
1705 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1706 FIXME("HW VertexShader Error at position %d: %s\n",
1707 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1708 This->baseShader.prgId = -1;
1711 #if 1 /* if were using the data buffer of device then we don't need to free it */
1712 HeapFree(GetProcessHeap(), 0, pgmStr);
1713 #endif
1714 #undef PNSTRCAT
1717 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1719 * TODO: use the NV_vertex_program (or 1_1) extension
1720 * and specifics vendors (ARB_vertex_program??) variants for it
1722 return TRUE;
1725 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1726 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1728 /** Vertex Shader Temporary Registers */
1729 WINED3DSHADERVECTOR R[12];
1730 /*D3DSHADERSCALAR A0;*/
1731 WINED3DSHADERVECTOR A[1];
1732 /** temporary Vector for modifier management */
1733 WINED3DSHADERVECTOR d;
1734 WINED3DSHADERVECTOR s[3];
1735 /** parser datas */
1736 const DWORD* pToken = This->baseShader.function;
1737 const SHADER_OPCODE* curOpcode = NULL;
1738 /** functions parameters */
1739 WINED3DSHADERVECTOR* p[4];
1740 WINED3DSHADERVECTOR* p_send[4];
1741 DWORD i;
1743 /** init temporary register */
1744 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1746 /* vshader_program_parse(vshader); */
1747 #if 0 /* Must not be 1 in cvs */
1748 TRACE("Input:\n");
1749 TRACE_VSVECTOR(This->data->C[0]);
1750 TRACE_VSVECTOR(This->data->C[1]);
1751 TRACE_VSVECTOR(This->data->C[2]);
1752 TRACE_VSVECTOR(This->data->C[3]);
1753 TRACE_VSVECTOR(This->data->C[4]);
1754 TRACE_VSVECTOR(This->data->C[5]);
1755 TRACE_VSVECTOR(This->data->C[6]);
1756 TRACE_VSVECTOR(This->data->C[7]);
1757 TRACE_VSVECTOR(This->data->C[8]);
1758 TRACE_VSVECTOR(This->data->C[64]);
1759 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1760 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1761 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1762 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1763 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1764 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1765 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1766 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1767 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1768 #endif
1770 TRACE_VSVECTOR(vshader->data->C[64]);
1771 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1773 /* the first dword is the version tag */
1774 /* TODO: parse it */
1776 if (vshader_is_version_token(*pToken)) { /** version */
1777 ++pToken;
1779 while (D3DVS_END() != *pToken) {
1780 if (vshader_is_comment_token(*pToken)) { /** comment */
1781 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1782 ++pToken;
1783 pToken += comment_len;
1784 continue ;
1786 curOpcode = vshader_program_get_opcode(This, *pToken);
1787 ++pToken;
1788 if (NULL == curOpcode) {
1789 i = 0;
1790 /* unknown current opcode ... */
1791 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1792 while (*pToken & 0x80000000) {
1793 if (i == 0) {
1794 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1796 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1797 vshader_program_dump_param(*pToken, i);
1798 TRACE("\n");
1799 ++i;
1800 ++pToken;
1802 /* return FALSE; */
1803 } else {
1804 if (curOpcode->num_params > 0) {
1805 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1806 for (i = 0; i < curOpcode->num_params; ++i) {
1807 DWORD reg = pToken[i] & 0x00001FFF;
1808 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1810 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1811 case D3DSPR_TEMP:
1812 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1813 p[i] = &R[reg];
1814 break;
1815 case D3DSPR_INPUT:
1816 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1817 p[i] = &input->V[reg];
1818 break;
1819 case D3DSPR_CONST:
1820 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1821 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1822 } else {
1823 p[i] = &This->data->C[reg];
1825 break;
1826 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1827 if (0 != reg) {
1828 ERR("cannot handle address registers != a0, forcing use of a0\n");
1829 reg = 0;
1831 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1832 p[i] = &A[reg];
1833 break;
1834 case D3DSPR_RASTOUT:
1835 switch (reg) {
1836 case D3DSRO_POSITION:
1837 p[i] = &output->oPos;
1838 break;
1839 case D3DSRO_FOG:
1840 p[i] = &output->oFog;
1841 break;
1842 case D3DSRO_POINT_SIZE:
1843 p[i] = &output->oPts;
1844 break;
1846 break;
1847 case D3DSPR_ATTROUT:
1848 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1849 p[i] = &output->oD[reg];
1850 break;
1851 case D3DSPR_TEXCRDOUT:
1852 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1853 p[i] = &output->oT[reg];
1854 break;
1855 /* TODO Decls and defs */
1856 #if 0
1857 case D3DSPR_DCL:
1858 case D3DSPR_DEF:
1859 #endif
1860 default:
1861 break;
1864 if (i > 0) { /* input reg */
1865 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1866 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1868 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1869 /* TRACE("p[%d] not swizzled\n", i); */
1870 p_send[i] = p[i];
1871 } else {
1872 DWORD swizzle_x = swizzle & 0x03;
1873 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1874 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1875 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1876 /* TRACE("p[%d] swizzled\n", i); */
1877 float* tt = (float*) p[i];
1878 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1879 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1880 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1881 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1882 p_send[i] = &s[i];
1884 } else { /* output reg */
1885 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1886 p_send[i] = p[i];
1887 } else {
1888 p_send[i] = &d; /* to be post-processed for modifiers management */
1894 switch (curOpcode->num_params) {
1895 case 0:
1896 curOpcode->soft_fct();
1897 break;
1898 case 1:
1899 curOpcode->soft_fct(p_send[0]);
1900 break;
1901 case 2:
1902 curOpcode->soft_fct(p_send[0], p_send[1]);
1903 break;
1904 case 3:
1905 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1906 break;
1907 case 4:
1908 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1909 break;
1910 case 5:
1911 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1912 break;
1913 case 6:
1914 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1915 break;
1916 default:
1917 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1920 /* check if output reg modifier post-process */
1921 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1922 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1923 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1924 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1925 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1927 #if 0
1928 TRACE_VSVECTOR(output->oPos);
1929 TRACE_VSVECTOR(output->oD[0]);
1930 TRACE_VSVECTOR(output->oD[1]);
1931 TRACE_VSVECTOR(output->oT[0]);
1932 TRACE_VSVECTOR(output->oT[1]);
1933 TRACE_VSVECTOR(R[0]);
1934 TRACE_VSVECTOR(R[1]);
1935 TRACE_VSVECTOR(R[2]);
1936 TRACE_VSVECTOR(R[3]);
1937 TRACE_VSVECTOR(R[4]);
1938 TRACE_VSVECTOR(R[5]);
1939 #endif
1941 /* to next opcode token */
1942 pToken += curOpcode->num_params;
1944 #if 0
1945 TRACE("End of current instruction:\n");
1946 TRACE_VSVECTOR(output->oPos);
1947 TRACE_VSVECTOR(output->oD[0]);
1948 TRACE_VSVECTOR(output->oD[1]);
1949 TRACE_VSVECTOR(output->oT[0]);
1950 TRACE_VSVECTOR(output->oT[1]);
1951 TRACE_VSVECTOR(R[0]);
1952 TRACE_VSVECTOR(R[1]);
1953 TRACE_VSVECTOR(R[2]);
1954 TRACE_VSVECTOR(R[3]);
1955 TRACE_VSVECTOR(R[4]);
1956 TRACE_VSVECTOR(R[5]);
1957 #endif
1959 #if 0 /* Must not be 1 in cvs */
1960 TRACE("Output:\n");
1961 TRACE_VSVECTOR(output->oPos);
1962 TRACE_VSVECTOR(output->oD[0]);
1963 TRACE_VSVECTOR(output->oD[1]);
1964 TRACE_VSVECTOR(output->oT[0]);
1965 TRACE_VSVECTOR(output->oT[1]);
1966 #endif
1967 return D3D_OK;
1970 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1971 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1972 FIXME("(%p) : stub\n", This);
1973 return D3D_OK;
1976 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1977 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1978 FIXME("(%p) : stub\n", This);
1979 return D3D_OK;
1982 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1983 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1984 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1985 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1986 return D3DERR_INVALIDCALL;
1988 if (NULL == pConstantData) {
1989 return D3DERR_INVALIDCALL;
1991 FIXME("(%p) : stub\n", This);
1992 return D3D_OK;
1995 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1996 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1997 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1998 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1999 return D3DERR_INVALIDCALL;
2001 if (NULL == pConstantData) {
2002 return D3DERR_INVALIDCALL;
2004 FIXME("(%p) : stub\n", This);
2005 return D3D_OK;
2008 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
2009 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2010 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2011 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
2012 return D3DERR_INVALIDCALL;
2014 if (NULL == pConstantData) {
2015 return D3DERR_INVALIDCALL;
2017 FIXME("(%p) : stub\n", This);
2018 return D3D_OK;
2021 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
2022 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
2023 FIXME("(%p) : stub\n", This);
2024 return D3D_OK;
2027 #endif
2029 /* *******************************************
2030 IWineD3DVertexShader IUnknown parts follow
2031 ******************************************* */
2032 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
2034 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2035 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
2036 if (IsEqualGUID(riid, &IID_IUnknown)
2037 || IsEqualGUID(riid, &IID_IWineD3DBase)
2038 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
2039 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
2040 IUnknown_AddRef(iface);
2041 *ppobj = This;
2042 return D3D_OK;
2044 return E_NOINTERFACE;
2047 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
2048 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2049 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2050 return InterlockedIncrement(&This->ref);
2053 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
2054 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2055 ULONG ref;
2056 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2057 ref = InterlockedDecrement(&This->ref);
2058 if (ref == 0) {
2059 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2060 HeapFree(GetProcessHeap(), 0, This);
2062 return ref;
2065 /* *******************************************
2066 IWineD3DVertexShader IWineD3DVertexShader parts follow
2067 ******************************************* */
2069 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2070 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2072 *parent = This->parent;
2073 IUnknown_AddRef(*parent);
2074 TRACE("(%p) : returning %p\n", This, *parent);
2075 return D3D_OK;
2078 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2079 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2080 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2081 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2082 TRACE("(%p) returning %p\n", This, *pDevice);
2083 return D3D_OK;
2086 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2087 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2088 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2090 if (NULL == pData) {
2091 *pSizeOfData = This->baseShader.functionLength;
2092 return D3D_OK;
2094 if (*pSizeOfData < This->baseShader.functionLength) {
2095 *pSizeOfData = This->baseShader.functionLength;
2096 return D3DERR_MOREDATA;
2098 if (NULL == This->baseShader.function) { /* no function defined */
2099 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2100 (*(DWORD **) pData) = NULL;
2101 } else {
2102 if(This->baseShader.functionLength == 0){
2105 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2106 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
2108 return D3D_OK;
2111 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2112 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2113 const DWORD* pToken = pFunction;
2114 const SHADER_OPCODE* curOpcode = NULL;
2115 DWORD len = 0;
2116 DWORD i;
2117 TRACE("(%p) : Parsing programme\n", This);
2119 if (NULL != pToken) {
2120 while (D3DVS_END() != *pToken) {
2121 if (vshader_is_version_token(*pToken)) { /** version */
2122 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2123 ++pToken;
2124 ++len;
2125 continue;
2127 if (vshader_is_comment_token(*pToken)) { /** comment */
2128 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2129 ++pToken;
2130 TRACE("//%s\n", (char*)pToken);
2131 pToken += comment_len;
2132 len += comment_len + 1;
2133 continue;
2135 curOpcode = vshader_program_get_opcode(This, *pToken);
2136 ++pToken;
2137 ++len;
2138 if (NULL == curOpcode) {
2139 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2140 while (*pToken & 0x80000000) {
2141 /* unknown current opcode ... */
2142 FIXME("unrecognized opcode: %08lx", *pToken);
2143 ++pToken;
2144 ++len;
2145 TRACE("\n");
2148 } else {
2149 if (curOpcode->opcode == D3DSIO_DCL) {
2150 vshader_program_dump_decl_usage(This, *pToken);
2151 ++pToken;
2152 ++len;
2153 vshader_program_dump_vs_param(*pToken, 0);
2154 ++pToken;
2155 ++len;
2156 } else
2157 if (curOpcode->opcode == D3DSIO_DEF) {
2158 TRACE("def c%lu = ", *pToken & 0xFF);
2159 ++pToken;
2160 ++len;
2161 TRACE("%f ,", *(float *)pToken);
2162 ++pToken;
2163 ++len;
2164 TRACE("%f ,", *(float *)pToken);
2165 ++pToken;
2166 ++len;
2167 TRACE("%f ,", *(float *)pToken);
2168 ++pToken;
2169 ++len;
2170 TRACE("%f", *(float *)pToken);
2171 ++pToken;
2172 ++len;
2173 } else {
2174 TRACE("%s ", curOpcode->name);
2175 if (curOpcode->num_params > 0) {
2176 vshader_program_dump_vs_param(*pToken, 0);
2177 ++pToken;
2178 ++len;
2179 for (i = 1; i < curOpcode->num_params; ++i) {
2180 TRACE(", ");
2181 vshader_program_dump_vs_param(*pToken, 1);
2182 ++pToken;
2183 ++len;
2187 TRACE("\n");
2190 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
2191 } else {
2192 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
2195 /* Generate HW shader in needed */
2196 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2197 #if 1
2198 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2199 #endif
2202 /* copy the function ... because it will certainly be released by application */
2203 if (NULL != pFunction) {
2204 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
2205 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
2206 } else {
2207 This->baseShader.function = NULL;
2209 return D3D_OK;
2212 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2214 /*** IUnknown methods ***/
2215 IWineD3DVertexShaderImpl_QueryInterface,
2216 IWineD3DVertexShaderImpl_AddRef,
2217 IWineD3DVertexShaderImpl_Release,
2218 /*** IWineD3DBase methods ***/
2219 IWineD3DVertexShaderImpl_GetParent,
2220 /*** IWineD3DBaseShader methods ***/
2221 IWineD3DVertexShaderImpl_SetFunction,
2222 /*** IWineD3DVertexShader methods ***/
2223 IWineD3DVertexShaderImpl_GetDevice,
2224 IWineD3DVertexShaderImpl_GetFunction