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
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
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)
41 # define TRACE_VSVECTOR(name)
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
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
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
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
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
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) {
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) {
110 d->y = s0->y * s1->y;
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) {
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;
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) {
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;
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) {
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);
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;
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;
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) {
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;
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) {
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));
366 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
367 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
371 void vshader_call(WINED3DSHADERVECTOR* d) {
375 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
379 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
383 void vshader_ret(void) {
387 void vshader_endloop(void) {
391 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
395 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
399 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
403 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
407 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
411 void vshader_rep(WINED3DSHADERVECTOR* d) {
415 void vshader_endrep(void) {
419 void vshader_if(WINED3DSHADERVECTOR* d) {
423 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
427 void vshader_else(void) {
431 void vshader_label(WINED3DSHADERVECTOR* d) {
435 void vshader_endif(void) {
439 void vshader_break(void) {
443 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
447 void vshader_breakp(WINED3DSHADERVECTOR* d) {
451 void vshader_mova(WINED3DSHADERVECTOR* d) {
455 void vshader_defb(WINED3DSHADERVECTOR* d) {
459 void vshader_defi(WINED3DSHADERVECTOR* d) {
463 void vshader_texldd(WINED3DSHADERVECTOR* d) {
467 void vshader_setp(WINED3DSHADERVECTOR* d) {
471 void vshader_texldl(WINED3DSHADERVECTOR* d) {
476 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
477 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
478 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
479 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
482 * log, exp, frc, m*x* seems to be macros ins ... to see
484 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
487 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, 0, 0},
488 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, 0, 0},
489 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, 0, 0},
490 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, 0, 0},
491 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, 0, 0},
492 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, 0, 0},
493 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, 0, 0},
494 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, 0, 0},
495 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, 0, 0},
496 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, 0, 0},
497 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, 0, 0},
498 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, 0, 0},
499 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, 0, 0},
500 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, 0, 0},
501 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, 0, 0},
502 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, 0, 0},
503 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, 0, 0},
504 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, 0, 0},
505 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, 0, 0},
506 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, 0, 0},
507 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, 0, 0},
508 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, vshader_hw_map2gl, 0, 0},
509 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, 0, 0},
510 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, 0, 0},
511 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, 0, 0},
512 /* TODO: sng can possibly be performed a s
515 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, 0, 0},
516 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
519 MUL vec.xyz, vec, tmp;
520 but I think this is better because it accounts for w properly.
526 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, 0, 0},
527 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, NULL, 0, 0},
530 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, 0, 0},
531 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, 0, 0},
532 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, 0, 0},
533 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, 0, 0},
534 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, 0, 0},
536 /* Declare registers */
537 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, 0, 0},
539 /* Constant definitions */
540 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, 0, 0},
541 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, 0, 0},
542 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, NULL, 0, 0},
544 /* Flow control - requires GLSL or software shaders */
545 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, 0, 0},
546 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, 0, 0},
547 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, 0, 0},
548 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, 0, 0},
549 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, 0, 0},
550 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, 0, 0},
551 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, 0, 0},
552 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, 0, 0},
553 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, 0, 0},
554 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, 0, 0},
555 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, 0, 0},
556 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, 0, 0},
557 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, 0, 0},
558 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, 0, 0},
559 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, 0, 0},
561 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, 0, 0},
562 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, 0, 0},
563 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, 0, 0},
564 {0, NULL, NULL, 0, NULL, 0, 0}
567 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
568 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
569 static const char swizzle_reg_chars[] = "xyzw";
571 DWORD reg = param & D3DSP_REGNUM_MASK;
572 DWORD regtype = shader_get_regtype(param);
574 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
584 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
586 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
590 TRACE("%s", rastout_reg_names[reg]);
595 case D3DSPR_TEXCRDOUT:
598 case D3DSPR_CONSTINT:
599 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
601 case D3DSPR_CONSTBOOL:
602 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
608 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
614 FIXME("Unknown %lu reg %lu\n",regtype, reg);
619 /** operand output */
620 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
621 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
622 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
623 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
624 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
628 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
629 DWORD swizzle_x = swizzle & 0x03;
630 DWORD swizzle_y = (swizzle >> 2) & 0x03;
631 DWORD swizzle_z = (swizzle >> 4) & 0x03;
632 DWORD swizzle_w = (swizzle >> 6) & 0x03;
634 * swizzle bits fields:
637 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
638 if (swizzle_x == swizzle_y &&
639 swizzle_x == swizzle_z &&
640 swizzle_x == swizzle_w) {
641 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
644 swizzle_reg_chars[swizzle_x],
645 swizzle_reg_chars[swizzle_y],
646 swizzle_reg_chars[swizzle_z],
647 swizzle_reg_chars[swizzle_w]);
653 inline static BOOL vshader_is_version_token(DWORD token) {
654 return 0xFFFE0000 == (token & 0xFFFE0000);
657 inline static BOOL vshader_is_comment_token(DWORD token) {
658 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
661 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
662 /** operand output */
663 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
665 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
666 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
667 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
668 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
672 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
673 static const char swizzle_reg_chars_color_fix[] = "zyxw";
674 static const char swizzle_reg_chars[] = "xyzw";
675 const char* swizzle_regs = NULL;
679 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
680 DWORD swizzle_x = swizzle & 0x03;
681 DWORD swizzle_y = (swizzle >> 2) & 0x03;
682 DWORD swizzle_z = (swizzle >> 4) & 0x03;
683 DWORD swizzle_w = (swizzle >> 6) & 0x03;
686 swizzle_regs = swizzle_reg_chars_color_fix;
688 swizzle_regs = swizzle_reg_chars;
692 * swizzle bits fields:
695 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
697 sprintf(tmpReg, ".%c%c%c%c",
698 swizzle_regs[swizzle_x],
699 swizzle_regs[swizzle_y],
700 swizzle_regs[swizzle_z],
701 swizzle_regs[swizzle_w]);
702 strcat(hwLine, tmpReg);
706 if (swizzle_x == swizzle_y &&
707 swizzle_x == swizzle_z &&
708 swizzle_x == swizzle_w)
710 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
711 strcat(hwLine, tmpReg);
713 sprintf(tmpReg, ".%c%c%c%c",
714 swizzle_regs[swizzle_x],
715 swizzle_regs[swizzle_y],
716 swizzle_regs[swizzle_z],
717 swizzle_regs[swizzle_w]);
718 strcat(hwLine, tmpReg);
722 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
723 /* oPos, oFog and oPts in D3D */
724 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
726 DWORD reg = param & D3DSP_REGNUM_MASK;
727 DWORD regtype = shader_get_regtype(param);
729 BOOL is_color = FALSE;
731 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
732 strcat(hwLine, " -");
739 sprintf(tmpReg, "T%lu", reg);
740 strcat(hwLine, tmpReg);
743 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
744 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
747 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
748 if (This->namedArrays) {
749 sprintf(tmpReg, "namedVertex%lu", reg);
751 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
752 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
754 strcat(hwLine, tmpReg);
757 /* FIXME: some constants are named so we need a constants map*/
758 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
759 if (param & D3DVS_ADDRMODE_RELATIVE) {
760 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
762 sprintf(tmpReg, "const%lu", reg);
764 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
766 strcat(hwLine, tmpReg);
768 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
769 sprintf(tmpReg, "A%lu", reg);
770 strcat(hwLine, tmpReg);
773 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
774 strcat(hwLine, tmpReg);
778 strcat(hwLine, "result.color.primary");
780 strcat(hwLine, "result.color.secondary");
783 case D3DSPR_TEXCRDOUT:
784 sprintf(tmpReg, "result.texcoord[%lu]", reg);
785 strcat(hwLine, tmpReg);
788 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
793 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
795 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
799 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
801 switch(usage & 0xFFFF) {
802 case D3DDECLUSAGE_POSITION:
803 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
804 TRACE("Setting position to %d\n", arrayNo);
805 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
806 This->namedArrays = TRUE;
808 /* TODO: position indexes go from 0-8!!*/
809 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
810 /* robots uses positions up to 8, the position arrays are just packed.*/
811 if ((usage & 0xF0000) >> 16 > 1) {
812 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
814 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
815 This->declaredArrays = TRUE;
818 case D3DDECLUSAGE_BLENDINDICES:
819 /* not supported by openGL */
820 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
821 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
822 This->declaredArrays = TRUE;
823 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
825 case D3DDECLUSAGE_BLENDWEIGHT:
826 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
827 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
828 This->namedArrays = TRUE;
829 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
831 case D3DDECLUSAGE_NORMAL:
832 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
833 TRACE("Setting normal to %d\n", arrayNo);
834 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
835 This->namedArrays = TRUE;
837 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
838 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
839 This->declaredArrays = TRUE;
842 case D3DDECLUSAGE_PSIZE:
843 TRACE("Setting PSIZE to %d\n", arrayNo);
844 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
845 This->namedArrays = TRUE;
846 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
848 case D3DDECLUSAGE_COLOR:
849 if((usage & 0xF0000) >> 16 == 0) {
850 TRACE("Setting DIFFUSE to %d\n", arrayNo);
851 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
852 This->namedArrays = TRUE;
854 TRACE("Setting SPECULAR to %d\n", arrayNo);
855 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
856 This->namedArrays = TRUE;
859 case D3DDECLUSAGE_TEXCOORD:
860 This->namedArrays = TRUE;
861 /* only 7 texture coords have been designed for, so run a quick sanity check */
862 if ((usage & 0xF0000) >> 16 > 7) {
863 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
865 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
866 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
869 /* The following aren't supported by openGL,
870 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
871 this should be caught in the first pass */
872 case D3DDECLUSAGE_TANGENT:
873 TRACE("Setting TANGENT to %d\n", arrayNo);
874 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
875 This->declaredArrays = TRUE;
877 case D3DDECLUSAGE_BINORMAL:
878 TRACE("Setting BINORMAL to %d\n", arrayNo);
879 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
880 This->declaredArrays = TRUE;
882 case D3DDECLUSAGE_TESSFACTOR:
883 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
884 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
885 This->declaredArrays = TRUE;
887 case D3DDECLUSAGE_POSITIONT:
888 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
889 FIXME("Setting positiont to %d\n", arrayNo);
890 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
891 This->namedArrays = TRUE;
893 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
894 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
895 This->declaredArrays = TRUE;
896 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
899 case D3DDECLUSAGE_FOG:
900 /* supported by OpenGL */
901 TRACE("Setting FOG to %d\n", arrayNo);
902 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
903 This->namedArrays = TRUE;
905 case D3DDECLUSAGE_DEPTH:
906 TRACE("Setting DEPTH to %d\n", arrayNo);
907 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
908 This->declaredArrays = TRUE;
910 case D3DDECLUSAGE_SAMPLE:
911 TRACE("Setting SAMPLE to %d\n", arrayNo);
912 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
913 This->declaredArrays = TRUE;
916 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
920 void vshader_set_version(
921 IWineD3DVertexShaderImpl *This,
924 DWORD major = (version >> 8) & 0x0F;
925 DWORD minor = version & 0x0F;
927 This->baseShader.hex_version = version;
928 This->baseShader.version = major * 10 + minor;
929 TRACE("vs_%lu_%lu\n", major, minor);
931 This->baseShader.limits.texture = 0;
933 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
934 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
936 switch (This->baseShader.version) {
938 case 11: This->baseShader.limits.temporary = 12;
939 This->baseShader.limits.constant_bool = 0;
940 This->baseShader.limits.constant_int = 0;
941 This->baseShader.limits.address = 1;
945 case 21: This->baseShader.limits.temporary = 12;
946 This->baseShader.limits.constant_bool = 16;
947 This->baseShader.limits.constant_int = 16;
948 This->baseShader.limits.address = 1;
951 case 30: This->baseShader.limits.temporary = 32;
952 This->baseShader.limits.constant_bool = 32;
953 This->baseShader.limits.constant_int = 32;
954 This->baseShader.limits.address = 1;
957 default: This->baseShader.limits.temporary = 12;
958 This->baseShader.limits.constant_bool = 0;
959 This->baseShader.limits.constant_int = 0;
960 This->baseShader.limits.address = 1;
961 FIXME("Unrecognized vertex shader version %lx!\n", version);
965 /* Map the opcode 1-to-1 to the GL code */
966 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
968 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
969 CONST SHADER_OPCODE* curOpcode = arg->opcode;
970 SHADER_BUFFER* buffer = arg->buffer;
971 DWORD dst = arg->dst;
972 DWORD* src = arg->src;
974 DWORD dst_regtype = shader_get_regtype(dst);
978 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
979 strcpy(tmpLine, "ARL");
981 strcpy(tmpLine, curOpcode->glname);
983 if (curOpcode->num_params > 0) {
984 vshader_program_add_param(This, dst, FALSE, tmpLine);
985 for (i = 1; i < curOpcode->num_params; ++i) {
986 strcat(tmpLine, ",");
987 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
990 shader_addline(buffer, "%s;\n", tmpLine);
993 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
995 DWORD dst = arg->dst;
996 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
998 SHADER_BUFFER* buffer = arg->buffer;
1000 if (This->namedArrays) {
1001 const char* attribName = "undefined";
1002 switch(dst & 0xFFFF) {
1003 case D3DDECLUSAGE_POSITION:
1004 attribName = "vertex.position";
1006 case D3DDECLUSAGE_BLENDINDICES:
1007 /* not supported by openGL */
1008 attribName = "vertex.blend";
1010 case D3DDECLUSAGE_BLENDWEIGHT:
1011 attribName = "vertex.weight";
1013 case D3DDECLUSAGE_NORMAL:
1014 attribName = "vertex.normal";
1016 case D3DDECLUSAGE_PSIZE:
1017 attribName = "vertex.psize";
1019 case D3DDECLUSAGE_COLOR:
1020 if((dst & 0xF0000) >> 16 == 0) {
1021 attribName = "vertex.color";
1023 attribName = "vertex.color.secondary";
1026 case D3DDECLUSAGE_TEXCOORD:
1030 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
1031 attribName = tmpChar;
1034 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1035 case D3DDECLUSAGE_TANGENT:
1036 attribName = "vertex.tangent";
1038 case D3DDECLUSAGE_BINORMAL:
1039 attribName = "vertex.binormal";
1041 case D3DDECLUSAGE_TESSFACTOR:
1042 attribName = "vertex.tessfactor";
1044 case D3DDECLUSAGE_POSITIONT:
1045 attribName = "vertex.possitionT";
1047 case D3DDECLUSAGE_FOG:
1048 attribName = "vertex.fogcoord";
1050 case D3DDECLUSAGE_DEPTH:
1051 attribName = "vertex.depth";
1053 case D3DDECLUSAGE_SAMPLE:
1054 attribName = "vertex.sample";
1057 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
1060 sprintf(tmpLine, "ATTRIB ");
1061 vshader_program_add_param(This, dst, FALSE, tmpLine);
1062 if (This->namedArrays)
1063 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
1068 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
1070 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
1071 SHADER_BUFFER* buffer = arg->buffer;
1072 DWORD reg = arg->dst;
1074 shader_addline(buffer,
1075 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
1076 *((const float *)(arg->src + 0)),
1077 *((const float *)(arg->src + 1)),
1078 *((const float *)(arg->src + 2)),
1079 *((const float *)(arg->src + 3)) );
1081 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
1084 /** Handles transforming all D3DSIO_M?x? opcodes for
1085 Vertex shaders to ARB_vertex_program codes */
1086 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1089 int nComponents = 0;
1090 SHADER_OPCODE_ARG tmpArg;
1092 /* Set constants for the temporary argument */
1093 tmpArg.shader = arg->shader;
1094 tmpArg.buffer = arg->buffer;
1095 tmpArg.src[0] = arg->src[0];
1097 switch(arg->opcode->opcode) {
1100 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1104 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1108 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1112 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1116 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1122 for (i = 0; i < nComponents; i++) {
1123 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1124 tmpArg.src[1] = arg->src[1]+i;
1125 vshader_hw_map2gl(&tmpArg);
1130 * Function parser ...
1133 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1134 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1135 const DWORD* pToken = pFunction;
1136 const SHADER_OPCODE* curOpcode = NULL;
1138 SHADER_BUFFER buffer;
1139 DWORD addressUsed, tempsUsed;
1141 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1142 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1143 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1144 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1145 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1146 This->fixupVertexBufferSize = PGMSIZE;
1147 This->fixupVertexBuffer[0] = 0;
1149 buffer.buffer = This->device->fixupVertexBuffer;
1151 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1155 /* First pass: figure out which temporary and texture registers are used */
1156 shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &addressUsed);
1157 TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
1159 /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded
1160 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1161 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1164 /* Mesa supports only 95 constants */
1165 if (GL_VEND(MESA) || GL_VEND(WINE))
1166 This->baseShader.limits.constant_float =
1167 min(95, This->baseShader.limits.constant_float);
1169 /* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
1170 shader_addline(&buffer, "!!ARBvp1.0\n");
1172 /* Pre-declare registers */
1173 for (i = 0; i < This->baseShader.limits.temporary; i++) {
1174 if (tempsUsed & (1 << i))
1175 shader_addline(&buffer, "TEMP T%lu;\n", i);
1178 for (i = 0; i < This->baseShader.limits.address; i++) {
1179 if (addressUsed & (1 << i))
1180 shader_addline(&buffer, "ADDRESS A%ld;\n", i);
1183 /* Why do we need to alias those? */
1184 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1185 This->baseShader.limits.constant_float,
1186 This->baseShader.limits.constant_float - 1);
1188 /** second pass, now generate */
1191 if (NULL != pToken) {
1194 if (D3DVS_END() == *pToken)
1198 if (vshader_is_version_token(*pToken)) {
1204 if (vshader_is_comment_token(*pToken)) {
1205 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1207 TRACE("#%s\n", (char*)pToken);
1208 pToken += comment_len;
1213 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1216 /* Unknown opcode and its parameters */
1217 if (NULL == curOpcode) {
1218 while (*pToken & 0x80000000) {
1219 FIXME("unrecognized opcode: %08lx\n", *pToken);
1223 /* Unhandled opcode */
1224 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1226 FIXME("Token %s requires greater functionality than "
1227 "Vertex_Program_ARB supports\n", curOpcode->name);
1228 pToken += curOpcode->num_params;
1230 /* If a generator function is set, use it */
1231 } else if (curOpcode->hw_fct != NULL) {
1233 SHADER_OPCODE_ARG hw_arg;
1235 hw_arg.shader = (IWineD3DBaseShader*) This;
1236 hw_arg.opcode = curOpcode;
1237 hw_arg.buffer = &buffer;
1238 if (curOpcode->num_params > 0) {
1239 hw_arg.dst = *pToken;
1241 /* FIXME: this does not account for relative address tokens */
1242 for (i = 1; i < curOpcode->num_params; i++)
1243 hw_arg.src[i-1] = *(pToken + i);
1246 curOpcode->hw_fct(&hw_arg);
1247 pToken += curOpcode->num_params;
1249 /* Unrecognized or No-Op code */
1252 switch (curOpcode->opcode) {
1256 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1257 pToken += curOpcode->num_params;
1261 shader_addline(&buffer, "END\n");
1264 /* finally null terminate the buffer */
1265 buffer.buffer[buffer.bsize] = 0;
1267 /* Check that Vertex Shaders are supported */
1268 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1269 /* Create the hw shader */
1270 /* TODO: change to resource.glObjectHandel or something like that */
1271 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1272 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1273 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1275 /* Create the program and check for errors */
1276 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1277 buffer.bsize, buffer.buffer));
1279 if (glGetError() == GL_INVALID_OPERATION) {
1281 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1282 FIXME("HW VertexShader Error at position %d: %s\n",
1283 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1284 This->baseShader.prgId = -1;
1287 #if 1 /* if were using the data buffer of device then we don't need to free it */
1288 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1292 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1294 * TODO: use the NV_vertex_program (or 1_1) extension
1295 * and specifics vendors (ARB_vertex_program??) variants for it
1300 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1301 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1303 /** Vertex Shader Temporary Registers */
1304 WINED3DSHADERVECTOR R[12];
1305 /*D3DSHADERSCALAR A0;*/
1306 WINED3DSHADERVECTOR A[1];
1307 /** temporary Vector for modifier management */
1308 WINED3DSHADERVECTOR d;
1309 WINED3DSHADERVECTOR s[3];
1311 const DWORD* pToken = This->baseShader.function;
1312 const SHADER_OPCODE* curOpcode = NULL;
1313 /** functions parameters */
1314 WINED3DSHADERVECTOR* p[4];
1315 WINED3DSHADERVECTOR* p_send[4];
1318 /** init temporary register */
1319 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1321 /* vshader_program_parse(vshader); */
1322 #if 0 /* Must not be 1 in cvs */
1324 TRACE_VSVECTOR(This->data->C[0]);
1325 TRACE_VSVECTOR(This->data->C[1]);
1326 TRACE_VSVECTOR(This->data->C[2]);
1327 TRACE_VSVECTOR(This->data->C[3]);
1328 TRACE_VSVECTOR(This->data->C[4]);
1329 TRACE_VSVECTOR(This->data->C[5]);
1330 TRACE_VSVECTOR(This->data->C[6]);
1331 TRACE_VSVECTOR(This->data->C[7]);
1332 TRACE_VSVECTOR(This->data->C[8]);
1333 TRACE_VSVECTOR(This->data->C[64]);
1334 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1335 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1336 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1337 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1338 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1339 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1340 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1341 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1342 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1345 TRACE_VSVECTOR(vshader->data->C[64]);
1346 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1348 /* the first dword is the version tag */
1349 /* TODO: parse it */
1351 if (vshader_is_version_token(*pToken)) { /** version */
1354 while (D3DVS_END() != *pToken) {
1355 if (vshader_is_comment_token(*pToken)) { /** comment */
1356 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1358 pToken += comment_len;
1361 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1363 if (NULL == curOpcode) {
1365 /* unknown current opcode ... */
1366 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1367 while (*pToken & 0x80000000) {
1369 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1371 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1372 vshader_program_dump_vs_param(*pToken, i);
1379 if (curOpcode->num_params > 0) {
1380 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1381 for (i = 0; i < curOpcode->num_params; ++i) {
1382 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1383 DWORD regtype = shader_get_regtype(pToken[i]);
1387 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1391 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1392 p[i] = &input->V[reg];
1395 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1396 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1398 p[i] = &This->data->C[reg];
1401 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1403 ERR("cannot handle address registers != a0, forcing use of a0\n");
1406 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1409 case D3DSPR_RASTOUT:
1411 case D3DSRO_POSITION:
1412 p[i] = &output->oPos;
1415 p[i] = &output->oFog;
1417 case D3DSRO_POINT_SIZE:
1418 p[i] = &output->oPts;
1422 case D3DSPR_ATTROUT:
1423 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1424 p[i] = &output->oD[reg];
1426 case D3DSPR_TEXCRDOUT:
1427 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1428 p[i] = &output->oT[reg];
1430 /* TODO Decls and defs */
1439 if (i > 0) { /* input reg */
1440 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1441 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1443 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1444 /* TRACE("p[%d] not swizzled\n", i); */
1447 DWORD swizzle_x = swizzle & 0x03;
1448 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1449 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1450 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1451 /* TRACE("p[%d] swizzled\n", i); */
1452 float* tt = (float*) p[i];
1453 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1454 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1455 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1456 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1459 } else { /* output reg */
1460 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1463 p_send[i] = &d; /* to be post-processed for modifiers management */
1469 switch (curOpcode->num_params) {
1471 curOpcode->soft_fct();
1474 curOpcode->soft_fct(p_send[0]);
1477 curOpcode->soft_fct(p_send[0], p_send[1]);
1480 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1483 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1486 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1489 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1492 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1495 /* check if output reg modifier post-process */
1496 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1497 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1498 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1499 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1500 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1503 TRACE_VSVECTOR(output->oPos);
1504 TRACE_VSVECTOR(output->oD[0]);
1505 TRACE_VSVECTOR(output->oD[1]);
1506 TRACE_VSVECTOR(output->oT[0]);
1507 TRACE_VSVECTOR(output->oT[1]);
1508 TRACE_VSVECTOR(R[0]);
1509 TRACE_VSVECTOR(R[1]);
1510 TRACE_VSVECTOR(R[2]);
1511 TRACE_VSVECTOR(R[3]);
1512 TRACE_VSVECTOR(R[4]);
1513 TRACE_VSVECTOR(R[5]);
1516 /* to next opcode token */
1517 pToken += curOpcode->num_params;
1520 TRACE("End of current instruction:\n");
1521 TRACE_VSVECTOR(output->oPos);
1522 TRACE_VSVECTOR(output->oD[0]);
1523 TRACE_VSVECTOR(output->oD[1]);
1524 TRACE_VSVECTOR(output->oT[0]);
1525 TRACE_VSVECTOR(output->oT[1]);
1526 TRACE_VSVECTOR(R[0]);
1527 TRACE_VSVECTOR(R[1]);
1528 TRACE_VSVECTOR(R[2]);
1529 TRACE_VSVECTOR(R[3]);
1530 TRACE_VSVECTOR(R[4]);
1531 TRACE_VSVECTOR(R[5]);
1534 #if 0 /* Must not be 1 in cvs */
1536 TRACE_VSVECTOR(output->oPos);
1537 TRACE_VSVECTOR(output->oD[0]);
1538 TRACE_VSVECTOR(output->oD[1]);
1539 TRACE_VSVECTOR(output->oT[0]);
1540 TRACE_VSVECTOR(output->oT[1]);
1545 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1546 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1547 FIXME("(%p) : stub\n", This);
1551 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1552 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1553 FIXME("(%p) : stub\n", This);
1557 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1558 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1559 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1560 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1561 return WINED3DERR_INVALIDCALL;
1563 if (NULL == pConstantData) {
1564 return WINED3DERR_INVALIDCALL;
1566 FIXME("(%p) : stub\n", This);
1570 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1571 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1572 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1573 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1574 return WINED3DERR_INVALIDCALL;
1576 if (NULL == pConstantData) {
1577 return WINED3DERR_INVALIDCALL;
1579 FIXME("(%p) : stub\n", This);
1583 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1584 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1585 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1586 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1587 return WINED3DERR_INVALIDCALL;
1589 if (NULL == pConstantData) {
1590 return WINED3DERR_INVALIDCALL;
1592 FIXME("(%p) : stub\n", This);
1596 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1597 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1598 FIXME("(%p) : stub\n", This);
1604 /* *******************************************
1605 IWineD3DVertexShader IUnknown parts follow
1606 ******************************************* */
1607 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1609 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1610 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1611 if (IsEqualGUID(riid, &IID_IUnknown)
1612 || IsEqualGUID(riid, &IID_IWineD3DBase)
1613 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1614 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1615 IUnknown_AddRef(iface);
1620 return E_NOINTERFACE;
1623 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1624 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1625 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1626 return InterlockedIncrement(&This->ref);
1629 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1630 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1632 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1633 ref = InterlockedDecrement(&This->ref);
1635 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1636 HeapFree(GetProcessHeap(), 0, This);
1641 /* *******************************************
1642 IWineD3DVertexShader IWineD3DVertexShader parts follow
1643 ******************************************* */
1645 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1646 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1648 *parent = This->parent;
1649 IUnknown_AddRef(*parent);
1650 TRACE("(%p) : returning %p\n", This, *parent);
1654 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1655 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1656 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1657 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1658 TRACE("(%p) returning %p\n", This, *pDevice);
1662 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1663 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1664 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1666 if (NULL == pData) {
1667 *pSizeOfData = This->baseShader.functionLength;
1670 if (*pSizeOfData < This->baseShader.functionLength) {
1671 *pSizeOfData = This->baseShader.functionLength;
1672 return WINED3DERR_MOREDATA;
1674 if (NULL == This->baseShader.function) { /* no function defined */
1675 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1676 (*(DWORD **) pData) = NULL;
1678 if(This->baseShader.functionLength == 0){
1681 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1682 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1687 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1688 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1689 const DWORD* pToken = pFunction;
1690 const SHADER_OPCODE* curOpcode = NULL;
1693 TRACE("(%p) : Parsing programme\n", This);
1695 /* Initialise vertex input arrays */
1696 This->namedArrays = FALSE;
1697 This->declaredArrays = FALSE;
1698 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1699 This->arrayUsageMap[i] = -1;
1701 if (NULL != pToken) {
1702 while (D3DVS_END() != *pToken) {
1703 if (vshader_is_version_token(*pToken)) { /** version */
1704 vshader_set_version(This, *pToken);
1709 if (vshader_is_comment_token(*pToken)) { /** comment */
1710 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1712 TRACE("//%s\n", (char*)pToken);
1713 pToken += comment_len;
1714 len += comment_len + 1;
1717 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1720 if (NULL == curOpcode) {
1721 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1722 while (*pToken & 0x80000000) {
1723 /* unknown current opcode ... */
1724 FIXME("unrecognized opcode: %08lx", *pToken);
1731 if (curOpcode->opcode == D3DSIO_DCL) {
1733 DWORD usage = *pToken;
1734 DWORD param = *(pToken + 1);
1736 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1737 shader_program_dump_decl_usage(usage, param);
1739 vshader_program_dump_vs_param(param, 0);
1744 if (curOpcode->opcode == D3DSIO_DEF) {
1745 TRACE("def c%lu = ", *pToken & 0xFF);
1748 TRACE("%f ,", *(float *)pToken);
1751 TRACE("%f ,", *(float *)pToken);
1754 TRACE("%f ,", *(float *)pToken);
1757 TRACE("%f", *(float *)pToken);
1761 TRACE("%s ", curOpcode->name);
1762 if (curOpcode->num_params > 0) {
1763 vshader_program_dump_vs_param(*pToken, 0);
1766 for (i = 1; i < curOpcode->num_params; ++i) {
1768 vshader_program_dump_vs_param(*pToken, 1);
1777 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1779 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1782 /* Handy for debugging using numbered arrays instead of named arrays */
1784 /* TODO: using numbered arrays for software shaders makes things easier */
1785 This->declaredArrays = TRUE;
1788 /* named arrays and declared arrays are mutually exclusive */
1789 if (This->declaredArrays)
1790 This->namedArrays = FALSE;
1792 /* Generate HW shader in needed */
1793 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1795 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
1799 /* copy the function ... because it will certainly be released by application */
1800 if (NULL != pFunction) {
1801 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1802 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1804 This->baseShader.function = NULL;
1809 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1811 /*** IUnknown methods ***/
1812 IWineD3DVertexShaderImpl_QueryInterface,
1813 IWineD3DVertexShaderImpl_AddRef,
1814 IWineD3DVertexShaderImpl_Release,
1815 /*** IWineD3DBase methods ***/
1816 IWineD3DVertexShaderImpl_GetParent,
1817 /*** IWineD3DBaseShader methods ***/
1818 IWineD3DVertexShaderImpl_SetFunction,
1819 /*** IWineD3DVertexShader methods ***/
1820 IWineD3DVertexShaderImpl_GetDevice,
1821 IWineD3DVertexShaderImpl_GetFunction