Update the address of the Free Software Foundation.
[wine/testsucceed.git] / dlls / wined3d / vertexshader.c
blobcb8d973c66c3eb5779fd4b8f07f46b8b666fe61f
1 /*
2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006 Ivan Gyurdiev
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
26 #include <math.h>
27 #include <stdio.h>
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
35 /* Shader debugging - Change the following line to enable debugging of software
36 vertex shaders */
37 #if 0 /* Musxt not be 1 in cvs version */
38 # define VSTRACE(A) TRACE A
39 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
40 #else
41 # define VSTRACE(A)
42 # define TRACE_VSVECTOR(name)
43 #endif
45 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 /**
48 * DirectX9 SDK download
49 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
51 * Exploring D3DX
52 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
54 * Using Vertex Shaders
55 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
57 * Dx9 New
58 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
60 * Dx9 Shaders
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
64 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
66 * Dx9 D3DX
67 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
69 * FVF
70 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
72 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
73 * http://developer.nvidia.com/view.asp?IO=vstovp
75 * NVIDIA: Memory Management with VAR
76 * http://developer.nvidia.com/view.asp?IO=var_memory_management
79 /* 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
80 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 */
82 #define GLNAME_REQUIRE_GLSL ((const char *)1)
84 /*******************************
85 * vshader functions software VM
88 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
89 d->x = s0->x + s1->x;
90 d->y = s0->y + s1->y;
91 d->z = s0->z + s1->z;
92 d->w = s0->w + s1->w;
93 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
94 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
97 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
98 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
99 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
100 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
103 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
104 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
105 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
106 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
109 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
110 d->x = 1.0f;
111 d->y = s0->y * s1->y;
112 d->z = s0->z;
113 d->w = s1->w;
114 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
115 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
118 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
119 union {
120 float f;
121 DWORD d;
122 } tmp;
124 tmp.f = floorf(s0->w);
125 d->x = powf(2.0f, tmp.f);
126 d->y = s0->w - tmp.f;
127 tmp.f = powf(2.0f, s0->w);
128 tmp.d &= 0xFFFFFF00U;
129 d->z = tmp.f;
130 d->w = 1.0f;
131 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
132 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
135 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
136 d->x = 1.0f;
137 d->y = (0.0f < s0->x) ? s0->x : 0.0f;
138 d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
139 d->w = 1.0f;
140 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
141 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
144 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
145 float tmp_f = fabsf(s0->w);
146 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
147 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
148 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
151 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
152 d->x = s0->x * s1->x + s2->x;
153 d->y = s0->y * s1->y + s2->y;
154 d->z = s0->z * s1->z + s2->z;
155 d->w = s0->w * s1->w + s2->w;
156 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
157 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));
160 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
161 d->x = (s0->x >= s1->x) ? s0->x : s1->x;
162 d->y = (s0->y >= s1->y) ? s0->y : s1->y;
163 d->z = (s0->z >= s1->z) ? s0->z : s1->z;
164 d->w = (s0->w >= s1->w) ? s0->w : s1->w;
165 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
166 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
169 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
170 d->x = (s0->x < s1->x) ? s0->x : s1->x;
171 d->y = (s0->y < s1->y) ? s0->y : s1->y;
172 d->z = (s0->z < s1->z) ? s0->z : s1->z;
173 d->w = (s0->w < s1->w) ? s0->w : s1->w;
174 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
175 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
178 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
179 d->x = s0->x;
180 d->y = s0->y;
181 d->z = s0->z;
182 d->w = s0->w;
183 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
184 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
187 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
188 d->x = s0->x * s1->x;
189 d->y = s0->y * s1->y;
190 d->z = s0->z * s1->z;
191 d->w = s0->w * s1->w;
192 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
193 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
196 void vshader_nop(void) {
197 /* NOPPPP ahhh too easy ;) */
198 VSTRACE(("executing nop\n"));
201 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
202 d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
203 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
207 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
208 float tmp_f = fabsf(s0->w);
209 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);
210 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
211 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
214 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
215 d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
216 d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
217 d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
218 d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
219 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
220 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
223 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
224 d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
225 d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
226 d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
227 d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
228 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
229 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
232 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
233 d->x = s0->x - s1->x;
234 d->y = s0->y - s1->y;
235 d->z = s0->z - s1->z;
236 d->w = s0->w - s1->w;
237 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
238 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
242 * Version 1.1 specific
245 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
246 d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
247 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
248 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
251 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
252 float tmp_f = fabsf(s0->w);
253 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
254 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
255 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
258 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
259 d->x = s0->x - floorf(s0->x);
260 d->y = s0->y - floorf(s0->y);
261 d->z = 0.0f;
262 d->w = 1.0f;
263 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
264 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
267 typedef FLOAT D3DMATRIX44[4][4];
268 typedef FLOAT D3DMATRIX43[4][3];
269 typedef FLOAT D3DMATRIX34[3][4];
270 typedef FLOAT D3DMATRIX33[3][3];
271 typedef FLOAT D3DMATRIX23[2][3];
273 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
275 * Buggy CODE: here only if cast not work for copy/paste
276 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
277 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
278 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
279 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
280 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
281 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
282 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
284 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
285 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
286 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
287 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
288 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));
289 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));
290 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));
291 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));
294 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
295 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
298 d->w = 1.0f;
299 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));
300 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));
301 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));
302 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
305 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
307 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
308 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
309 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
310 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));
311 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
312 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));
313 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
316 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
320 d->w = 1.0f;
321 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));
322 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323 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));
324 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
327 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
328 FIXME("check\n");
329 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
330 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
331 d->z = 0.0f;
332 d->w = 1.0f;
336 * Version 2.0 specific
338 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
339 d->x = s0->x * (s1->x - s2->x) + s2->x;
340 d->y = s0->y * (s1->y - s2->y) + s2->y;
341 d->z = s0->z * (s1->z - s2->z) + s2->z;
342 d->w = s0->w * (s1->w - s2->w) + s2->w;
345 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
346 d->x = s0->y * s1->z - s0->z * s1->y;
347 d->y = s0->z * s1->x - s0->x * s1->z;
348 d->z = s0->x * s1->y - s0->y * s1->x;
349 d->w = 0.9f; /* w is undefined, so set it to something safeish */
351 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
352 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
355 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
357 d->x = fabsf(s0->x);
358 d->y = fabsf(s0->y);
359 d->z = fabsf(s0->z);
360 d->w = fabsf(s0->w);
361 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
362 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
365 /* Stubs */
367 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
368 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
369 FIXME(" : Stub\n");
372 void vshader_call(WINED3DSHADERVECTOR* d) {
373 FIXME(" : Stub\n");
376 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
377 FIXME(" : Stub\n");
380 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
381 FIXME(" : Stub\n");
384 void vshader_ret(void) {
385 FIXME(" : Stub\n");
388 void vshader_endloop(void) {
389 FIXME(" : Stub\n");
392 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393 FIXME(" : Stub\n");
396 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
397 FIXME(" : Stub\n");
400 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401 FIXME(" : Stub\n");
404 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405 FIXME(" : Stub\n");
408 void vshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409 FIXME(" : Stub\n");
412 void vshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
413 FIXME(" : Stub\n");
416 void vshader_rep(WINED3DSHADERVECTOR* d) {
417 FIXME(" : Stub\n");
420 void vshader_endrep(void) {
421 FIXME(" : Stub\n");
424 void vshader_if(WINED3DSHADERVECTOR* d) {
425 FIXME(" : Stub\n");
428 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
429 FIXME(" : Stub\n");
432 void vshader_else(void) {
433 FIXME(" : Stub\n");
436 void vshader_label(WINED3DSHADERVECTOR* d) {
437 FIXME(" : Stub\n");
440 void vshader_endif(void) {
441 FIXME(" : Stub\n");
444 void vshader_break(void) {
445 FIXME(" : Stub\n");
448 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449 FIXME(" : Stub\n");
452 void vshader_breakp(WINED3DSHADERVECTOR* d) {
453 FIXME(" : Stub\n");
456 void vshader_mova(WINED3DSHADERVECTOR* d) {
457 FIXME(" : Stub\n");
460 void vshader_defb(WINED3DSHADERVECTOR* d) {
461 FIXME(" : Stub\n");
464 void vshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
465 FIXME(" : Stub\n");
468 void vshader_texldd(WINED3DSHADERVECTOR* d) {
469 FIXME(" : Stub\n");
472 void vshader_setp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
473 FIXME(" : Stub\n");
476 void vshader_texldl(WINED3DSHADERVECTOR* d) {
477 FIXME(" : Stub\n");
480 /* Prototype */
481 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
482 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
483 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
484 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
487 * log, exp, frc, m*x* seems to be macros ins ... to see
489 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
491 /* Arithmetic */
492 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
511 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
512 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
513 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, NULL, NULL, 0, 0},
514 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
515 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
516 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
517 /* TODO: sng can possibly be performed a s
518 RCP tmp, vec
519 MUL out, tmp, vec*/
520 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
521 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
522 DP3 tmp , vec, vec;
523 RSQ tmp, tmp.x;
524 MUL vec.xyz, vec, tmp;
525 but I think this is better because it accounts for w properly.
526 DP3 tmp , vec, vec;
527 RSQ tmp, tmp.x;
528 MUL vec, vec, tmp;
531 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, NULL, 0, 0},
532 {D3DSIO_SINCOS, "sincos", NULL, 4, vshader_sincos2, NULL, NULL, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
533 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos3, NULL, NULL, D3DVS_VERSION(3,0), -1},
535 /* Matrix */
536 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
537 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
538 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
539 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
540 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
542 /* Declare registers */
543 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
545 /* Constant definitions */
546 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
547 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
548 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 5, vshader_defi, NULL, NULL, 0, 0},
550 /* Flow control - requires GLSL or software shaders */
551 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
552 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
553 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
554 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
555 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
556 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
557 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
558 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
559 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
560 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
561 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
562 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
563 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
564 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
565 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
567 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
568 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 3, vshader_setp, NULL, NULL, 0, 0},
569 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
570 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
573 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
574 /** operand output */
575 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
576 strcat(hwLine, ".");
577 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
578 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
579 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
580 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
584 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
585 static const char swizzle_reg_chars_color_fix[] = "zyxw";
586 static const char swizzle_reg_chars[] = "xyzw";
587 const char* swizzle_regs = NULL;
588 char tmpReg[255];
590 /** operand input */
591 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
592 DWORD swizzle_x = swizzle & 0x03;
593 DWORD swizzle_y = (swizzle >> 2) & 0x03;
594 DWORD swizzle_z = (swizzle >> 4) & 0x03;
595 DWORD swizzle_w = (swizzle >> 6) & 0x03;
597 if (is_color) {
598 swizzle_regs = swizzle_reg_chars_color_fix;
599 } else {
600 swizzle_regs = swizzle_reg_chars;
604 * swizzle bits fields:
605 * WWZZYYXX
607 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
608 if (is_color) {
609 sprintf(tmpReg, ".%c%c%c%c",
610 swizzle_regs[swizzle_x],
611 swizzle_regs[swizzle_y],
612 swizzle_regs[swizzle_z],
613 swizzle_regs[swizzle_w]);
614 strcat(hwLine, tmpReg);
616 return ;
618 if (swizzle_x == swizzle_y &&
619 swizzle_x == swizzle_z &&
620 swizzle_x == swizzle_w)
622 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
623 strcat(hwLine, tmpReg);
624 } else {
625 sprintf(tmpReg, ".%c%c%c%c",
626 swizzle_regs[swizzle_x],
627 swizzle_regs[swizzle_y],
628 swizzle_regs[swizzle_z],
629 swizzle_regs[swizzle_w]);
630 strcat(hwLine, tmpReg);
634 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
635 /* oPos, oFog and oPts in D3D */
636 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
638 DWORD reg = param & D3DSP_REGNUM_MASK;
639 DWORD regtype = shader_get_regtype(param);
640 char tmpReg[255];
641 BOOL is_color = FALSE;
643 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
644 strcat(hwLine, " -");
645 } else {
646 strcat(hwLine, " ");
649 switch (regtype) {
650 case D3DSPR_TEMP:
651 sprintf(tmpReg, "R%lu", reg);
652 strcat(hwLine, tmpReg);
653 break;
654 case D3DSPR_INPUT:
655 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
656 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
657 is_color = TRUE;
659 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
660 if (This->namedArrays) {
661 sprintf(tmpReg, "namedVertex%lu", reg);
662 } else {
663 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
664 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
666 strcat(hwLine, tmpReg);
667 break;
668 case D3DSPR_CONST:
669 /* FIXME: some constants are named so we need a constants map*/
670 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
671 if (param & D3DVS_ADDRMODE_RELATIVE) {
672 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
674 sprintf(tmpReg, "const%lu", reg);
675 } else {
676 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
678 strcat(hwLine, tmpReg);
679 break;
680 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
681 sprintf(tmpReg, "A%lu", reg);
682 strcat(hwLine, tmpReg);
683 break;
684 case D3DSPR_RASTOUT:
685 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
686 strcat(hwLine, tmpReg);
687 break;
688 case D3DSPR_ATTROUT:
689 if (reg==0) {
690 strcat(hwLine, "result.color.primary");
691 } else {
692 strcat(hwLine, "result.color.secondary");
694 break;
695 case D3DSPR_TEXCRDOUT:
696 sprintf(tmpReg, "result.texcoord[%lu]", reg);
697 strcat(hwLine, tmpReg);
698 break;
699 default:
700 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
701 strcat(hwLine, "unrecognized_register");
702 break;
705 if (!is_input) {
706 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
707 } else {
708 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
712 static void vshader_parse_input_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
714 switch(usage & 0xFFFF) {
715 case D3DDECLUSAGE_POSITION:
716 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
717 TRACE("Setting position to %d\n", arrayNo);
718 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
719 This->namedArrays = TRUE;
720 } else {
721 /* TODO: position indexes go from 0-8!!*/
722 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
723 /* robots uses positions up to 8, the position arrays are just packed.*/
724 if ((usage & 0xF0000) >> 16 > 1) {
725 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
727 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
728 This->declaredArrays = TRUE;
730 break;
731 case D3DDECLUSAGE_BLENDINDICES:
732 /* not supported by openGL */
733 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
734 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
735 This->declaredArrays = TRUE;
736 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
737 break;
738 case D3DDECLUSAGE_BLENDWEIGHT:
739 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
740 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
741 This->namedArrays = TRUE;
742 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
743 break;
744 case D3DDECLUSAGE_NORMAL:
745 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
746 TRACE("Setting normal to %d\n", arrayNo);
747 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
748 This->namedArrays = TRUE;
749 } else {
750 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
751 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
752 This->declaredArrays = TRUE;
754 break;
755 case D3DDECLUSAGE_PSIZE:
756 TRACE("Setting PSIZE to %d\n", arrayNo);
757 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
758 This->namedArrays = TRUE;
759 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
760 break;
761 case D3DDECLUSAGE_COLOR:
762 if((usage & 0xF0000) >> 16 == 0) {
763 TRACE("Setting DIFFUSE to %d\n", arrayNo);
764 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
765 This->namedArrays = TRUE;
766 } else {
767 TRACE("Setting SPECULAR to %d\n", arrayNo);
768 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
769 This->namedArrays = TRUE;
771 break;
772 case D3DDECLUSAGE_TEXCOORD:
773 This->namedArrays = TRUE;
774 /* only 7 texture coords have been designed for, so run a quick sanity check */
775 if ((usage & 0xF0000) >> 16 > 7) {
776 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
777 } else {
778 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
779 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
781 break;
782 /* The following aren't supported by openGL,
783 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
784 this should be caught in the first pass */
785 case D3DDECLUSAGE_TANGENT:
786 TRACE("Setting TANGENT to %d\n", arrayNo);
787 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
788 This->declaredArrays = TRUE;
789 break;
790 case D3DDECLUSAGE_BINORMAL:
791 TRACE("Setting BINORMAL to %d\n", arrayNo);
792 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
793 This->declaredArrays = TRUE;
794 break;
795 case D3DDECLUSAGE_TESSFACTOR:
796 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
797 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
798 This->declaredArrays = TRUE;
799 break;
800 case D3DDECLUSAGE_POSITIONT:
801 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
802 FIXME("Setting positiont to %d\n", arrayNo);
803 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
804 This->namedArrays = TRUE;
805 } else {
806 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
807 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
808 This->declaredArrays = TRUE;
809 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
811 break;
812 case D3DDECLUSAGE_FOG:
813 /* supported by OpenGL */
814 TRACE("Setting FOG to %d\n", arrayNo);
815 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
816 This->namedArrays = TRUE;
817 break;
818 case D3DDECLUSAGE_DEPTH:
819 TRACE("Setting DEPTH to %d\n", arrayNo);
820 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
821 This->declaredArrays = TRUE;
822 break;
823 case D3DDECLUSAGE_SAMPLE:
824 TRACE("Setting SAMPLE to %d\n", arrayNo);
825 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
826 This->declaredArrays = TRUE;
827 break;
828 default:
829 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
833 void vshader_set_version(
834 IWineD3DVertexShaderImpl *This,
835 DWORD version) {
837 DWORD major = (version >> 8) & 0x0F;
838 DWORD minor = version & 0x0F;
840 This->baseShader.hex_version = version;
841 This->baseShader.version = major * 10 + minor;
842 TRACE("vs_%lu_%lu\n", major, minor);
844 This->baseShader.limits.texture = 0;
846 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
847 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
849 switch (This->baseShader.version) {
850 case 10:
851 case 11: This->baseShader.limits.temporary = 12;
852 This->baseShader.limits.constant_bool = 0;
853 This->baseShader.limits.constant_int = 0;
854 This->baseShader.limits.address = 1;
855 break;
857 case 20:
858 case 21: This->baseShader.limits.temporary = 12;
859 This->baseShader.limits.constant_bool = 16;
860 This->baseShader.limits.constant_int = 16;
861 This->baseShader.limits.address = 1;
862 break;
864 case 30: This->baseShader.limits.temporary = 32;
865 This->baseShader.limits.constant_bool = 32;
866 This->baseShader.limits.constant_int = 32;
867 This->baseShader.limits.address = 1;
868 break;
870 default: This->baseShader.limits.temporary = 12;
871 This->baseShader.limits.constant_bool = 0;
872 This->baseShader.limits.constant_int = 0;
873 This->baseShader.limits.address = 1;
874 FIXME("Unrecognized vertex shader version %lx!\n", version);
878 /* Map the opcode 1-to-1 to the GL code */
879 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
881 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
882 CONST SHADER_OPCODE* curOpcode = arg->opcode;
883 SHADER_BUFFER* buffer = arg->buffer;
884 DWORD dst = arg->dst;
885 DWORD* src = arg->src;
887 DWORD dst_regtype = shader_get_regtype(dst);
888 char tmpLine[256];
889 unsigned int i;
891 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
892 strcpy(tmpLine, "ARL");
893 else
894 strcpy(tmpLine, curOpcode->glname);
896 if (curOpcode->num_params > 0) {
897 vshader_program_add_param(This, dst, FALSE, tmpLine);
898 for (i = 1; i < curOpcode->num_params; ++i) {
899 strcat(tmpLine, ",");
900 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
903 shader_addline(buffer, "%s;\n", tmpLine);
906 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
908 DWORD dst = arg->dst;
909 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
910 char tmpLine[256];
911 SHADER_BUFFER* buffer = arg->buffer;
913 if (This->namedArrays) {
914 const char* attribName = "undefined";
915 switch(dst & 0xFFFF) {
916 case D3DDECLUSAGE_POSITION:
917 attribName = "vertex.position";
918 break;
919 case D3DDECLUSAGE_BLENDINDICES:
920 /* not supported by openGL */
921 attribName = "vertex.blend";
922 break;
923 case D3DDECLUSAGE_BLENDWEIGHT:
924 attribName = "vertex.weight";
925 break;
926 case D3DDECLUSAGE_NORMAL:
927 attribName = "vertex.normal";
928 break;
929 case D3DDECLUSAGE_PSIZE:
930 attribName = "vertex.psize";
931 break;
932 case D3DDECLUSAGE_COLOR:
933 if((dst & 0xF0000) >> 16 == 0) {
934 attribName = "vertex.color";
935 } else {
936 attribName = "vertex.color.secondary";
938 break;
939 case D3DDECLUSAGE_TEXCOORD:
941 char tmpChar[100];
942 tmpChar[0] = 0;
943 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
944 attribName = tmpChar;
945 break;
947 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
948 case D3DDECLUSAGE_TANGENT:
949 attribName = "vertex.tangent";
950 break;
951 case D3DDECLUSAGE_BINORMAL:
952 attribName = "vertex.binormal";
953 break;
954 case D3DDECLUSAGE_TESSFACTOR:
955 attribName = "vertex.tessfactor";
956 break;
957 case D3DDECLUSAGE_POSITIONT:
958 attribName = "vertex.possitionT";
959 break;
960 case D3DDECLUSAGE_FOG:
961 attribName = "vertex.fogcoord";
962 break;
963 case D3DDECLUSAGE_DEPTH:
964 attribName = "vertex.depth";
965 break;
966 case D3DDECLUSAGE_SAMPLE:
967 attribName = "vertex.sample";
968 break;
969 default:
970 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
973 sprintf(tmpLine, "ATTRIB ");
974 vshader_program_add_param(This, dst, FALSE, tmpLine);
975 if (This->namedArrays)
976 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
981 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
983 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
984 SHADER_BUFFER* buffer = arg->buffer;
985 DWORD reg = arg->dst;
987 shader_addline(buffer,
988 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
989 *((const float *)(arg->src + 0)),
990 *((const float *)(arg->src + 1)),
991 *((const float *)(arg->src + 2)),
992 *((const float *)(arg->src + 3)) );
994 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
997 /** Handles transforming all D3DSIO_M?x? opcodes for
998 Vertex shaders to ARB_vertex_program codes */
999 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1001 int i;
1002 int nComponents = 0;
1003 SHADER_OPCODE_ARG tmpArg;
1005 /* Set constants for the temporary argument */
1006 tmpArg.shader = arg->shader;
1007 tmpArg.buffer = arg->buffer;
1008 tmpArg.src[0] = arg->src[0];
1010 switch(arg->opcode->opcode) {
1011 case D3DSIO_M4x4:
1012 nComponents = 4;
1013 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1014 break;
1015 case D3DSIO_M4x3:
1016 nComponents = 3;
1017 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1018 break;
1019 case D3DSIO_M3x4:
1020 nComponents = 4;
1021 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1022 break;
1023 case D3DSIO_M3x3:
1024 nComponents = 3;
1025 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1026 break;
1027 case D3DSIO_M3x2:
1028 nComponents = 2;
1029 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1030 break;
1031 default:
1032 break;
1035 for (i = 0; i < nComponents; i++) {
1036 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1037 tmpArg.src[1] = arg->src[1]+i;
1038 vshader_hw_map2gl(&tmpArg);
1042 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1043 or GLSL and send it to the card */
1044 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1045 IWineD3DVertexShader *iface,
1046 CONST DWORD *pFunction) {
1048 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1049 SHADER_BUFFER buffer;
1051 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1052 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1053 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1054 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1055 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1056 This->fixupVertexBufferSize = PGMSIZE;
1057 This->fixupVertexBuffer[0] = 0;
1059 buffer.buffer = This->device->fixupVertexBuffer;
1060 #else
1061 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1062 #endif
1063 buffer.bsize = 0;
1064 buffer.lineNo = 0;
1066 /* TODO: Optionally, generate the GLSL shader instead */
1067 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1068 /* Create the hw ARB shader */
1069 shader_addline(&buffer, "!!ARBvp1.0\n");
1071 /* Mesa supports only 95 constants */
1072 if (GL_VEND(MESA) || GL_VEND(WINE))
1073 This->baseShader.limits.constant_float =
1074 min(95, This->baseShader.limits.constant_float);
1076 /** Call the base shader generation routine to generate most
1077 of the vertex shader string for us */
1078 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1080 shader_addline(&buffer, "END\n\0");
1082 /* TODO: change to resource.glObjectHandle or something like that */
1083 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1085 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1086 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1088 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1089 /* Create the program and check for errors */
1090 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1091 buffer.bsize, buffer.buffer));
1093 if (glGetError() == GL_INVALID_OPERATION) {
1094 GLint errPos;
1095 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1096 FIXME("HW VertexShader Error at position %d: %s\n",
1097 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1098 This->baseShader.prgId = -1;
1102 #if 1 /* if were using the data buffer of device then we don't need to free it */
1103 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1104 #endif
1107 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1109 * TODO: use the NV_vertex_program (or 1_1) extension
1110 * and specifics vendors (ARB_vertex_program??) variants for it
1112 return TRUE;
1115 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1116 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1117 DWORD opcode_token;
1119 /** Vertex Shader Temporary Registers */
1120 WINED3DSHADERVECTOR R[12];
1121 /*D3DSHADERSCALAR A0;*/
1122 WINED3DSHADERVECTOR A[1];
1123 /** temporary Vector for modifier management */
1124 WINED3DSHADERVECTOR d;
1125 WINED3DSHADERVECTOR s[3];
1126 /** parser datas */
1127 const DWORD* pToken = This->baseShader.function;
1128 const SHADER_OPCODE* curOpcode = NULL;
1129 /** functions parameters */
1130 WINED3DSHADERVECTOR* p[6];
1131 WINED3DSHADERVECTOR* p_send[6];
1132 DWORD i;
1134 /** init temporary register */
1135 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1137 /* vshader_program_parse(vshader); */
1138 #if 0 /* Must not be 1 in cvs */
1139 TRACE("Input:\n");
1140 TRACE_VSVECTOR(This->data->C[0]);
1141 TRACE_VSVECTOR(This->data->C[1]);
1142 TRACE_VSVECTOR(This->data->C[2]);
1143 TRACE_VSVECTOR(This->data->C[3]);
1144 TRACE_VSVECTOR(This->data->C[4]);
1145 TRACE_VSVECTOR(This->data->C[5]);
1146 TRACE_VSVECTOR(This->data->C[6]);
1147 TRACE_VSVECTOR(This->data->C[7]);
1148 TRACE_VSVECTOR(This->data->C[8]);
1149 TRACE_VSVECTOR(This->data->C[64]);
1150 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1151 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1152 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1153 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1154 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1155 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1156 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1157 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1158 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1159 #endif
1161 TRACE_VSVECTOR(vshader->data->C[64]);
1162 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1164 /* the first dword is the version tag */
1165 /* TODO: parse it */
1167 if (shader_is_vshader_version(*pToken)) { /** version */
1168 ++pToken;
1170 while (D3DVS_END() != *pToken) {
1171 if (shader_is_comment(*pToken)) { /** comment */
1172 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1173 ++pToken;
1174 pToken += comment_len;
1175 continue ;
1178 opcode_token = *pToken++;
1179 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1181 if (NULL == curOpcode) {
1182 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1183 pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1184 /* return FALSE; */
1186 } else {
1187 if (curOpcode->num_params > 0) {
1188 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1189 for (i = 0; i < curOpcode->num_params; ++i) {
1190 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1191 DWORD regtype = shader_get_regtype(pToken[i]);
1193 switch (regtype) {
1194 case D3DSPR_TEMP:
1195 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1196 p[i] = &R[reg];
1197 break;
1198 case D3DSPR_INPUT:
1199 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1200 p[i] = &input->V[reg];
1201 break;
1202 case D3DSPR_CONST:
1203 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1204 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1205 } else {
1206 p[i] = &This->data->C[reg];
1208 break;
1209 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1210 if (0 != reg) {
1211 ERR("cannot handle address registers != a0, forcing use of a0\n");
1212 reg = 0;
1214 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1215 p[i] = &A[reg];
1216 break;
1217 case D3DSPR_RASTOUT:
1218 switch (reg) {
1219 case D3DSRO_POSITION:
1220 p[i] = &output->oPos;
1221 break;
1222 case D3DSRO_FOG:
1223 p[i] = &output->oFog;
1224 break;
1225 case D3DSRO_POINT_SIZE:
1226 p[i] = &output->oPts;
1227 break;
1229 break;
1230 case D3DSPR_ATTROUT:
1231 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1232 p[i] = &output->oD[reg];
1233 break;
1234 case D3DSPR_TEXCRDOUT:
1235 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1236 p[i] = &output->oT[reg];
1237 break;
1238 /* TODO Decls and defs */
1239 #if 0
1240 case D3DSPR_DCL:
1241 case D3DSPR_DEF:
1242 #endif
1243 default:
1244 break;
1247 if (i > 0) { /* input reg */
1248 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1249 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1251 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1252 /* TRACE("p[%d] not swizzled\n", i); */
1253 p_send[i] = p[i];
1254 } else {
1255 DWORD swizzle_x = swizzle & 0x03;
1256 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1257 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1258 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1259 /* TRACE("p[%d] swizzled\n", i); */
1260 float* tt = (float*) p[i];
1261 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1262 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1263 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1264 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1265 p_send[i] = &s[i];
1267 } else { /* output reg */
1268 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1269 p_send[i] = p[i];
1270 } else {
1271 p_send[i] = &d; /* to be post-processed for modifiers management */
1277 switch (curOpcode->num_params) {
1278 case 0:
1279 curOpcode->soft_fct();
1280 break;
1281 case 1:
1282 curOpcode->soft_fct(p_send[0]);
1283 break;
1284 case 2:
1285 curOpcode->soft_fct(p_send[0], p_send[1]);
1286 break;
1287 case 3:
1288 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1289 break;
1290 case 4:
1291 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1292 break;
1293 case 5:
1294 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1295 break;
1296 case 6:
1297 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1298 break;
1299 default:
1300 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1303 /* check if output reg modifier post-process */
1304 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1305 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1306 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1307 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1308 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1310 #if 0
1311 TRACE_VSVECTOR(output->oPos);
1312 TRACE_VSVECTOR(output->oD[0]);
1313 TRACE_VSVECTOR(output->oD[1]);
1314 TRACE_VSVECTOR(output->oT[0]);
1315 TRACE_VSVECTOR(output->oT[1]);
1316 TRACE_VSVECTOR(R[0]);
1317 TRACE_VSVECTOR(R[1]);
1318 TRACE_VSVECTOR(R[2]);
1319 TRACE_VSVECTOR(R[3]);
1320 TRACE_VSVECTOR(R[4]);
1321 TRACE_VSVECTOR(R[5]);
1322 #endif
1324 /* to next opcode token */
1325 pToken += curOpcode->num_params;
1327 #if 0
1328 TRACE("End of current instruction:\n");
1329 TRACE_VSVECTOR(output->oPos);
1330 TRACE_VSVECTOR(output->oD[0]);
1331 TRACE_VSVECTOR(output->oD[1]);
1332 TRACE_VSVECTOR(output->oT[0]);
1333 TRACE_VSVECTOR(output->oT[1]);
1334 TRACE_VSVECTOR(R[0]);
1335 TRACE_VSVECTOR(R[1]);
1336 TRACE_VSVECTOR(R[2]);
1337 TRACE_VSVECTOR(R[3]);
1338 TRACE_VSVECTOR(R[4]);
1339 TRACE_VSVECTOR(R[5]);
1340 #endif
1342 #if 0 /* Must not be 1 in cvs */
1343 TRACE("Output:\n");
1344 TRACE_VSVECTOR(output->oPos);
1345 TRACE_VSVECTOR(output->oD[0]);
1346 TRACE_VSVECTOR(output->oD[1]);
1347 TRACE_VSVECTOR(output->oT[0]);
1348 TRACE_VSVECTOR(output->oT[1]);
1349 #endif
1350 return WINED3D_OK;
1353 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1354 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1355 FIXME("(%p) : stub\n", This);
1356 return WINED3D_OK;
1359 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1360 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1361 FIXME("(%p) : stub\n", This);
1362 return WINED3D_OK;
1365 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1366 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1367 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1368 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1369 return WINED3DERR_INVALIDCALL;
1371 if (NULL == pConstantData) {
1372 return WINED3DERR_INVALIDCALL;
1374 FIXME("(%p) : stub\n", This);
1375 return WINED3D_OK;
1378 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1379 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1380 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1381 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1382 return WINED3DERR_INVALIDCALL;
1384 if (NULL == pConstantData) {
1385 return WINED3DERR_INVALIDCALL;
1387 FIXME("(%p) : stub\n", This);
1388 return WINED3D_OK;
1391 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1392 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1393 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1394 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1395 return WINED3DERR_INVALIDCALL;
1397 if (NULL == pConstantData) {
1398 return WINED3DERR_INVALIDCALL;
1400 FIXME("(%p) : stub\n", This);
1401 return WINED3D_OK;
1404 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1405 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1406 FIXME("(%p) : stub\n", This);
1407 return WINED3D_OK;
1410 #endif
1412 /* *******************************************
1413 IWineD3DVertexShader IUnknown parts follow
1414 ******************************************* */
1415 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1417 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1418 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1419 if (IsEqualGUID(riid, &IID_IUnknown)
1420 || IsEqualGUID(riid, &IID_IWineD3DBase)
1421 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1422 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1423 IUnknown_AddRef(iface);
1424 *ppobj = This;
1425 return S_OK;
1427 *ppobj = NULL;
1428 return E_NOINTERFACE;
1431 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1432 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1433 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1434 return InterlockedIncrement(&This->ref);
1437 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1438 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1439 ULONG ref;
1440 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1441 ref = InterlockedDecrement(&This->ref);
1442 if (ref == 0) {
1443 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1444 HeapFree(GetProcessHeap(), 0, This);
1446 return ref;
1449 /* *******************************************
1450 IWineD3DVertexShader IWineD3DVertexShader parts follow
1451 ******************************************* */
1453 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1454 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1456 *parent = This->parent;
1457 IUnknown_AddRef(*parent);
1458 TRACE("(%p) : returning %p\n", This, *parent);
1459 return WINED3D_OK;
1462 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1463 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1464 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1465 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1466 TRACE("(%p) returning %p\n", This, *pDevice);
1467 return WINED3D_OK;
1470 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1471 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1472 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1474 if (NULL == pData) {
1475 *pSizeOfData = This->baseShader.functionLength;
1476 return WINED3D_OK;
1478 if (*pSizeOfData < This->baseShader.functionLength) {
1479 *pSizeOfData = This->baseShader.functionLength;
1480 return WINED3DERR_MOREDATA;
1482 if (NULL == This->baseShader.function) { /* no function defined */
1483 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1484 (*(DWORD **) pData) = NULL;
1485 } else {
1486 if(This->baseShader.functionLength == 0){
1489 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1490 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1492 return WINED3D_OK;
1495 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1496 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1497 const DWORD* pToken = pFunction;
1498 const SHADER_OPCODE* curOpcode = NULL;
1499 DWORD opcode_token;
1500 DWORD len = 0;
1501 DWORD i;
1502 TRACE("(%p) : Parsing programme\n", This);
1504 /* Initialise vertex input arrays */
1505 This->namedArrays = FALSE;
1506 This->declaredArrays = FALSE;
1507 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1508 This->arrayUsageMap[i] = -1;
1510 if (NULL != pToken) {
1511 while (D3DVS_END() != *pToken) {
1512 if (shader_is_vshader_version(*pToken)) { /** version */
1513 vshader_set_version(This, *pToken);
1514 ++pToken;
1515 ++len;
1516 continue;
1518 if (shader_is_comment(*pToken)) { /** comment */
1519 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1520 ++pToken;
1521 TRACE("//%s\n", (char*)pToken);
1522 pToken += comment_len;
1523 len += comment_len + 1;
1524 continue;
1527 opcode_token = *pToken++;
1528 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1529 len++;
1531 if (NULL == curOpcode) {
1532 int tokens_read;
1534 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1535 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1536 pToken += tokens_read;
1537 len += tokens_read;
1539 } else {
1540 if (curOpcode->opcode == D3DSIO_DCL) {
1542 DWORD usage = *pToken;
1543 DWORD param = *(pToken + 1);
1544 DWORD regtype = shader_get_regtype(param);
1546 if (regtype == D3DSPR_INPUT)
1547 vshader_parse_input_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1548 shader_program_dump_decl_usage(usage, param);
1549 shader_dump_ins_modifiers(param);
1550 TRACE(" ");
1551 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1552 pToken += 2;
1553 len += 2;
1555 } else
1556 if (curOpcode->opcode == D3DSIO_DEF) {
1557 TRACE("def c%lu = ", *pToken & 0xFF);
1558 ++pToken;
1559 ++len;
1560 TRACE("%f ,", *(float *)pToken);
1561 ++pToken;
1562 ++len;
1563 TRACE("%f ,", *(float *)pToken);
1564 ++pToken;
1565 ++len;
1566 TRACE("%f ,", *(float *)pToken);
1567 ++pToken;
1568 ++len;
1569 TRACE("%f", *(float *)pToken);
1570 ++pToken;
1571 ++len;
1572 } else {
1574 DWORD param, addr_token;
1575 int tokens_read;
1577 /* Print out predication source token first - it follows
1578 * the destination token. */
1579 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1580 TRACE("(");
1581 shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1582 TRACE(") ");
1585 TRACE("%s", curOpcode->name);
1586 if (curOpcode->num_params > 0) {
1588 /* Destination token */
1589 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1590 pToken, &param, &addr_token);
1591 pToken += tokens_read;
1592 len += tokens_read;
1594 shader_dump_ins_modifiers(param);
1595 TRACE(" ");
1596 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1598 /* Predication token - already printed out, just skip it */
1599 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1600 pToken++;
1601 len++;
1604 /* Other source tokens */
1605 for (i = 1; i < curOpcode->num_params; ++i) {
1607 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1608 pToken, &param, &addr_token);
1609 pToken += tokens_read;
1610 len += tokens_read;
1612 TRACE(", ");
1613 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1617 TRACE("\n");
1620 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1621 } else {
1622 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1625 /* Handy for debugging using numbered arrays instead of named arrays */
1626 #if 1
1627 /* TODO: using numbered arrays for software shaders makes things easier */
1628 This->declaredArrays = TRUE;
1629 #endif
1631 /* named arrays and declared arrays are mutually exclusive */
1632 if (This->declaredArrays)
1633 This->namedArrays = FALSE;
1635 /* Generate HW shader in needed */
1636 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1637 #if 1
1638 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1639 #endif
1642 /* copy the function ... because it will certainly be released by application */
1643 if (NULL != pFunction) {
1644 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1645 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1646 } else {
1647 This->baseShader.function = NULL;
1649 return WINED3D_OK;
1652 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1654 /*** IUnknown methods ***/
1655 IWineD3DVertexShaderImpl_QueryInterface,
1656 IWineD3DVertexShaderImpl_AddRef,
1657 IWineD3DVertexShaderImpl_Release,
1658 /*** IWineD3DBase methods ***/
1659 IWineD3DVertexShaderImpl_GetParent,
1660 /*** IWineD3DBaseShader methods ***/
1661 IWineD3DVertexShaderImpl_SetFunction,
1662 /*** IWineD3DVertexShader methods ***/
1663 IWineD3DVertexShaderImpl_GetDevice,
1664 IWineD3DVertexShaderImpl_GetFunction