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, NULL, 0, 0},
488 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
489 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
490 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
491 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
492 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
511 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
512 /* TODO: sng can possibly be performed a s
515 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
516 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
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, NULL, 0, 0},
527 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, NULL, NULL, 0, 0},
530 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
531 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
532 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
533 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
534 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
536 /* Declare registers */
537 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
539 /* Constant definitions */
540 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
541 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
542 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, NULL, NULL, 0, 0},
544 /* Flow control - requires GLSL or software shaders */
545 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
546 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
547 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
548 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
549 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
550 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
551 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
552 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
553 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
554 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
555 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
556 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
557 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
558 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
559 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
561 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
562 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, NULL, 0, 0},
563 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
564 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
567 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
568 /** operand output */
569 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
571 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
572 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
573 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
574 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
578 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
579 static const char swizzle_reg_chars_color_fix[] = "zyxw";
580 static const char swizzle_reg_chars[] = "xyzw";
581 const char* swizzle_regs = NULL;
585 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
586 DWORD swizzle_x = swizzle & 0x03;
587 DWORD swizzle_y = (swizzle >> 2) & 0x03;
588 DWORD swizzle_z = (swizzle >> 4) & 0x03;
589 DWORD swizzle_w = (swizzle >> 6) & 0x03;
592 swizzle_regs = swizzle_reg_chars_color_fix;
594 swizzle_regs = swizzle_reg_chars;
598 * swizzle bits fields:
601 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
603 sprintf(tmpReg, ".%c%c%c%c",
604 swizzle_regs[swizzle_x],
605 swizzle_regs[swizzle_y],
606 swizzle_regs[swizzle_z],
607 swizzle_regs[swizzle_w]);
608 strcat(hwLine, tmpReg);
612 if (swizzle_x == swizzle_y &&
613 swizzle_x == swizzle_z &&
614 swizzle_x == swizzle_w)
616 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
617 strcat(hwLine, tmpReg);
619 sprintf(tmpReg, ".%c%c%c%c",
620 swizzle_regs[swizzle_x],
621 swizzle_regs[swizzle_y],
622 swizzle_regs[swizzle_z],
623 swizzle_regs[swizzle_w]);
624 strcat(hwLine, tmpReg);
628 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
629 /* oPos, oFog and oPts in D3D */
630 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
632 DWORD reg = param & D3DSP_REGNUM_MASK;
633 DWORD regtype = shader_get_regtype(param);
635 BOOL is_color = FALSE;
637 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
638 strcat(hwLine, " -");
645 sprintf(tmpReg, "R%lu", reg);
646 strcat(hwLine, tmpReg);
649 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
650 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
653 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
654 if (This->namedArrays) {
655 sprintf(tmpReg, "namedVertex%lu", reg);
657 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
658 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
660 strcat(hwLine, tmpReg);
663 /* FIXME: some constants are named so we need a constants map*/
664 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
665 if (param & D3DVS_ADDRMODE_RELATIVE) {
666 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
668 sprintf(tmpReg, "const%lu", reg);
670 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
672 strcat(hwLine, tmpReg);
674 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
675 sprintf(tmpReg, "A%lu", reg);
676 strcat(hwLine, tmpReg);
679 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
680 strcat(hwLine, tmpReg);
684 strcat(hwLine, "result.color.primary");
686 strcat(hwLine, "result.color.secondary");
689 case D3DSPR_TEXCRDOUT:
690 sprintf(tmpReg, "result.texcoord[%lu]", reg);
691 strcat(hwLine, tmpReg);
694 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
699 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
701 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
705 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
707 switch(usage & 0xFFFF) {
708 case D3DDECLUSAGE_POSITION:
709 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
710 TRACE("Setting position to %d\n", arrayNo);
711 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
712 This->namedArrays = TRUE;
714 /* TODO: position indexes go from 0-8!!*/
715 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
716 /* robots uses positions up to 8, the position arrays are just packed.*/
717 if ((usage & 0xF0000) >> 16 > 1) {
718 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
720 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
721 This->declaredArrays = TRUE;
724 case D3DDECLUSAGE_BLENDINDICES:
725 /* not supported by openGL */
726 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
727 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
728 This->declaredArrays = TRUE;
729 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
731 case D3DDECLUSAGE_BLENDWEIGHT:
732 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
733 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
734 This->namedArrays = TRUE;
735 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
737 case D3DDECLUSAGE_NORMAL:
738 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
739 TRACE("Setting normal to %d\n", arrayNo);
740 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
741 This->namedArrays = TRUE;
743 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
744 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
745 This->declaredArrays = TRUE;
748 case D3DDECLUSAGE_PSIZE:
749 TRACE("Setting PSIZE to %d\n", arrayNo);
750 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
751 This->namedArrays = TRUE;
752 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
754 case D3DDECLUSAGE_COLOR:
755 if((usage & 0xF0000) >> 16 == 0) {
756 TRACE("Setting DIFFUSE to %d\n", arrayNo);
757 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
758 This->namedArrays = TRUE;
760 TRACE("Setting SPECULAR to %d\n", arrayNo);
761 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
762 This->namedArrays = TRUE;
765 case D3DDECLUSAGE_TEXCOORD:
766 This->namedArrays = TRUE;
767 /* only 7 texture coords have been designed for, so run a quick sanity check */
768 if ((usage & 0xF0000) >> 16 > 7) {
769 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
771 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
772 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
775 /* The following aren't supported by openGL,
776 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
777 this should be caught in the first pass */
778 case D3DDECLUSAGE_TANGENT:
779 TRACE("Setting TANGENT to %d\n", arrayNo);
780 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
781 This->declaredArrays = TRUE;
783 case D3DDECLUSAGE_BINORMAL:
784 TRACE("Setting BINORMAL to %d\n", arrayNo);
785 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
786 This->declaredArrays = TRUE;
788 case D3DDECLUSAGE_TESSFACTOR:
789 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
790 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
791 This->declaredArrays = TRUE;
793 case D3DDECLUSAGE_POSITIONT:
794 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
795 FIXME("Setting positiont to %d\n", arrayNo);
796 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
797 This->namedArrays = TRUE;
799 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
800 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
801 This->declaredArrays = TRUE;
802 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
805 case D3DDECLUSAGE_FOG:
806 /* supported by OpenGL */
807 TRACE("Setting FOG to %d\n", arrayNo);
808 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
809 This->namedArrays = TRUE;
811 case D3DDECLUSAGE_DEPTH:
812 TRACE("Setting DEPTH to %d\n", arrayNo);
813 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
814 This->declaredArrays = TRUE;
816 case D3DDECLUSAGE_SAMPLE:
817 TRACE("Setting SAMPLE to %d\n", arrayNo);
818 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
819 This->declaredArrays = TRUE;
822 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
826 void vshader_set_version(
827 IWineD3DVertexShaderImpl *This,
830 DWORD major = (version >> 8) & 0x0F;
831 DWORD minor = version & 0x0F;
833 This->baseShader.hex_version = version;
834 This->baseShader.version = major * 10 + minor;
835 TRACE("vs_%lu_%lu\n", major, minor);
837 This->baseShader.limits.texture = 0;
839 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
840 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
842 switch (This->baseShader.version) {
844 case 11: This->baseShader.limits.temporary = 12;
845 This->baseShader.limits.constant_bool = 0;
846 This->baseShader.limits.constant_int = 0;
847 This->baseShader.limits.address = 1;
851 case 21: This->baseShader.limits.temporary = 12;
852 This->baseShader.limits.constant_bool = 16;
853 This->baseShader.limits.constant_int = 16;
854 This->baseShader.limits.address = 1;
857 case 30: This->baseShader.limits.temporary = 32;
858 This->baseShader.limits.constant_bool = 32;
859 This->baseShader.limits.constant_int = 32;
860 This->baseShader.limits.address = 1;
863 default: This->baseShader.limits.temporary = 12;
864 This->baseShader.limits.constant_bool = 0;
865 This->baseShader.limits.constant_int = 0;
866 This->baseShader.limits.address = 1;
867 FIXME("Unrecognized vertex shader version %lx!\n", version);
871 /* Map the opcode 1-to-1 to the GL code */
872 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
874 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
875 CONST SHADER_OPCODE* curOpcode = arg->opcode;
876 SHADER_BUFFER* buffer = arg->buffer;
877 DWORD dst = arg->dst;
878 DWORD* src = arg->src;
880 DWORD dst_regtype = shader_get_regtype(dst);
884 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
885 strcpy(tmpLine, "ARL");
887 strcpy(tmpLine, curOpcode->glname);
889 if (curOpcode->num_params > 0) {
890 vshader_program_add_param(This, dst, FALSE, tmpLine);
891 for (i = 1; i < curOpcode->num_params; ++i) {
892 strcat(tmpLine, ",");
893 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
896 shader_addline(buffer, "%s;\n", tmpLine);
899 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
901 DWORD dst = arg->dst;
902 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
904 SHADER_BUFFER* buffer = arg->buffer;
906 if (This->namedArrays) {
907 const char* attribName = "undefined";
908 switch(dst & 0xFFFF) {
909 case D3DDECLUSAGE_POSITION:
910 attribName = "vertex.position";
912 case D3DDECLUSAGE_BLENDINDICES:
913 /* not supported by openGL */
914 attribName = "vertex.blend";
916 case D3DDECLUSAGE_BLENDWEIGHT:
917 attribName = "vertex.weight";
919 case D3DDECLUSAGE_NORMAL:
920 attribName = "vertex.normal";
922 case D3DDECLUSAGE_PSIZE:
923 attribName = "vertex.psize";
925 case D3DDECLUSAGE_COLOR:
926 if((dst & 0xF0000) >> 16 == 0) {
927 attribName = "vertex.color";
929 attribName = "vertex.color.secondary";
932 case D3DDECLUSAGE_TEXCOORD:
936 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
937 attribName = tmpChar;
940 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
941 case D3DDECLUSAGE_TANGENT:
942 attribName = "vertex.tangent";
944 case D3DDECLUSAGE_BINORMAL:
945 attribName = "vertex.binormal";
947 case D3DDECLUSAGE_TESSFACTOR:
948 attribName = "vertex.tessfactor";
950 case D3DDECLUSAGE_POSITIONT:
951 attribName = "vertex.possitionT";
953 case D3DDECLUSAGE_FOG:
954 attribName = "vertex.fogcoord";
956 case D3DDECLUSAGE_DEPTH:
957 attribName = "vertex.depth";
959 case D3DDECLUSAGE_SAMPLE:
960 attribName = "vertex.sample";
963 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
966 sprintf(tmpLine, "ATTRIB ");
967 vshader_program_add_param(This, dst, FALSE, tmpLine);
968 if (This->namedArrays)
969 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
974 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
976 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
977 SHADER_BUFFER* buffer = arg->buffer;
978 DWORD reg = arg->dst;
980 shader_addline(buffer,
981 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
982 *((const float *)(arg->src + 0)),
983 *((const float *)(arg->src + 1)),
984 *((const float *)(arg->src + 2)),
985 *((const float *)(arg->src + 3)) );
987 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
990 /** Handles transforming all D3DSIO_M?x? opcodes for
991 Vertex shaders to ARB_vertex_program codes */
992 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
996 SHADER_OPCODE_ARG tmpArg;
998 /* Set constants for the temporary argument */
999 tmpArg.shader = arg->shader;
1000 tmpArg.buffer = arg->buffer;
1001 tmpArg.src[0] = arg->src[0];
1003 switch(arg->opcode->opcode) {
1006 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1010 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1014 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1018 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1022 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1028 for (i = 0; i < nComponents; i++) {
1029 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1030 tmpArg.src[1] = arg->src[1]+i;
1031 vshader_hw_map2gl(&tmpArg);
1035 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1036 or GLSL and send it to the card */
1037 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1038 IWineD3DVertexShader *iface,
1039 CONST DWORD *pFunction) {
1041 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1042 SHADER_BUFFER buffer;
1044 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1045 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1046 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1047 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1048 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1049 This->fixupVertexBufferSize = PGMSIZE;
1050 This->fixupVertexBuffer[0] = 0;
1052 buffer.buffer = This->device->fixupVertexBuffer;
1054 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1059 /* TODO: Optionally, generate the GLSL shader instead */
1060 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1061 /* Create the hw ARB shader */
1062 shader_addline(&buffer, "!!ARBvp1.0\n");
1064 /* Mesa supports only 95 constants */
1065 if (GL_VEND(MESA) || GL_VEND(WINE))
1066 This->baseShader.limits.constant_float =
1067 min(95, This->baseShader.limits.constant_float);
1069 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1070 This->baseShader.limits.constant_float,
1071 This->baseShader.limits.constant_float - 1);
1073 /** Call the base shader generation routine to generate most
1074 of the vertex shader string for us */
1075 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1077 shader_addline(&buffer, "END\n\0");
1079 /* TODO: change to resource.glObjectHandle or something like that */
1080 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1082 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1083 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1085 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1086 /* Create the program and check for errors */
1087 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1088 buffer.bsize, buffer.buffer));
1090 if (glGetError() == GL_INVALID_OPERATION) {
1092 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1093 FIXME("HW VertexShader Error at position %d: %s\n",
1094 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1095 This->baseShader.prgId = -1;
1099 #if 1 /* if were using the data buffer of device then we don't need to free it */
1100 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1104 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1106 * TODO: use the NV_vertex_program (or 1_1) extension
1107 * and specifics vendors (ARB_vertex_program??) variants for it
1112 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1113 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1115 /** Vertex Shader Temporary Registers */
1116 WINED3DSHADERVECTOR R[12];
1117 /*D3DSHADERSCALAR A0;*/
1118 WINED3DSHADERVECTOR A[1];
1119 /** temporary Vector for modifier management */
1120 WINED3DSHADERVECTOR d;
1121 WINED3DSHADERVECTOR s[3];
1123 const DWORD* pToken = This->baseShader.function;
1124 const SHADER_OPCODE* curOpcode = NULL;
1125 /** functions parameters */
1126 WINED3DSHADERVECTOR* p[6];
1127 WINED3DSHADERVECTOR* p_send[6];
1130 /** init temporary register */
1131 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1133 /* vshader_program_parse(vshader); */
1134 #if 0 /* Must not be 1 in cvs */
1136 TRACE_VSVECTOR(This->data->C[0]);
1137 TRACE_VSVECTOR(This->data->C[1]);
1138 TRACE_VSVECTOR(This->data->C[2]);
1139 TRACE_VSVECTOR(This->data->C[3]);
1140 TRACE_VSVECTOR(This->data->C[4]);
1141 TRACE_VSVECTOR(This->data->C[5]);
1142 TRACE_VSVECTOR(This->data->C[6]);
1143 TRACE_VSVECTOR(This->data->C[7]);
1144 TRACE_VSVECTOR(This->data->C[8]);
1145 TRACE_VSVECTOR(This->data->C[64]);
1146 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1147 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1148 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1149 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1150 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1151 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1152 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1153 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1154 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1157 TRACE_VSVECTOR(vshader->data->C[64]);
1158 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1160 /* the first dword is the version tag */
1161 /* TODO: parse it */
1163 if (shader_is_vshader_version(*pToken)) { /** version */
1166 while (D3DVS_END() != *pToken) {
1167 if (shader_is_comment(*pToken)) { /** comment */
1168 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1170 pToken += comment_len;
1173 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1175 if (NULL == curOpcode) {
1177 /* unknown current opcode ... */
1178 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1179 while (*pToken & 0x80000000) {
1181 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1183 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1184 shader_dump_param((IWineD3DBaseShader*) This, *pToken, i);
1191 if (curOpcode->num_params > 0) {
1192 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1193 for (i = 0; i < curOpcode->num_params; ++i) {
1194 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1195 DWORD regtype = shader_get_regtype(pToken[i]);
1199 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1203 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1204 p[i] = &input->V[reg];
1207 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1208 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1210 p[i] = &This->data->C[reg];
1213 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1215 ERR("cannot handle address registers != a0, forcing use of a0\n");
1218 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1221 case D3DSPR_RASTOUT:
1223 case D3DSRO_POSITION:
1224 p[i] = &output->oPos;
1227 p[i] = &output->oFog;
1229 case D3DSRO_POINT_SIZE:
1230 p[i] = &output->oPts;
1234 case D3DSPR_ATTROUT:
1235 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1236 p[i] = &output->oD[reg];
1238 case D3DSPR_TEXCRDOUT:
1239 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1240 p[i] = &output->oT[reg];
1242 /* TODO Decls and defs */
1251 if (i > 0) { /* input reg */
1252 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1253 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1255 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1256 /* TRACE("p[%d] not swizzled\n", i); */
1259 DWORD swizzle_x = swizzle & 0x03;
1260 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1261 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1262 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1263 /* TRACE("p[%d] swizzled\n", i); */
1264 float* tt = (float*) p[i];
1265 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1266 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1267 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1268 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1271 } else { /* output reg */
1272 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1275 p_send[i] = &d; /* to be post-processed for modifiers management */
1281 switch (curOpcode->num_params) {
1283 curOpcode->soft_fct();
1286 curOpcode->soft_fct(p_send[0]);
1289 curOpcode->soft_fct(p_send[0], p_send[1]);
1292 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1295 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1298 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1301 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1304 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1307 /* check if output reg modifier post-process */
1308 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1309 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1310 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1311 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1312 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1315 TRACE_VSVECTOR(output->oPos);
1316 TRACE_VSVECTOR(output->oD[0]);
1317 TRACE_VSVECTOR(output->oD[1]);
1318 TRACE_VSVECTOR(output->oT[0]);
1319 TRACE_VSVECTOR(output->oT[1]);
1320 TRACE_VSVECTOR(R[0]);
1321 TRACE_VSVECTOR(R[1]);
1322 TRACE_VSVECTOR(R[2]);
1323 TRACE_VSVECTOR(R[3]);
1324 TRACE_VSVECTOR(R[4]);
1325 TRACE_VSVECTOR(R[5]);
1328 /* to next opcode token */
1329 pToken += curOpcode->num_params;
1332 TRACE("End of current instruction:\n");
1333 TRACE_VSVECTOR(output->oPos);
1334 TRACE_VSVECTOR(output->oD[0]);
1335 TRACE_VSVECTOR(output->oD[1]);
1336 TRACE_VSVECTOR(output->oT[0]);
1337 TRACE_VSVECTOR(output->oT[1]);
1338 TRACE_VSVECTOR(R[0]);
1339 TRACE_VSVECTOR(R[1]);
1340 TRACE_VSVECTOR(R[2]);
1341 TRACE_VSVECTOR(R[3]);
1342 TRACE_VSVECTOR(R[4]);
1343 TRACE_VSVECTOR(R[5]);
1346 #if 0 /* Must not be 1 in cvs */
1348 TRACE_VSVECTOR(output->oPos);
1349 TRACE_VSVECTOR(output->oD[0]);
1350 TRACE_VSVECTOR(output->oD[1]);
1351 TRACE_VSVECTOR(output->oT[0]);
1352 TRACE_VSVECTOR(output->oT[1]);
1357 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1358 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1359 FIXME("(%p) : stub\n", This);
1363 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1364 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1365 FIXME("(%p) : stub\n", This);
1369 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1370 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1371 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1372 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1373 return WINED3DERR_INVALIDCALL;
1375 if (NULL == pConstantData) {
1376 return WINED3DERR_INVALIDCALL;
1378 FIXME("(%p) : stub\n", This);
1382 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1383 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1384 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1385 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1386 return WINED3DERR_INVALIDCALL;
1388 if (NULL == pConstantData) {
1389 return WINED3DERR_INVALIDCALL;
1391 FIXME("(%p) : stub\n", This);
1395 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1396 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1397 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1398 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1399 return WINED3DERR_INVALIDCALL;
1401 if (NULL == pConstantData) {
1402 return WINED3DERR_INVALIDCALL;
1404 FIXME("(%p) : stub\n", This);
1408 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1409 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1410 FIXME("(%p) : stub\n", This);
1416 /* *******************************************
1417 IWineD3DVertexShader IUnknown parts follow
1418 ******************************************* */
1419 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1421 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1422 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1423 if (IsEqualGUID(riid, &IID_IUnknown)
1424 || IsEqualGUID(riid, &IID_IWineD3DBase)
1425 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1426 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1427 IUnknown_AddRef(iface);
1432 return E_NOINTERFACE;
1435 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1436 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1437 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1438 return InterlockedIncrement(&This->ref);
1441 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1442 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1444 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1445 ref = InterlockedDecrement(&This->ref);
1447 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1448 HeapFree(GetProcessHeap(), 0, This);
1453 /* *******************************************
1454 IWineD3DVertexShader IWineD3DVertexShader parts follow
1455 ******************************************* */
1457 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1458 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1460 *parent = This->parent;
1461 IUnknown_AddRef(*parent);
1462 TRACE("(%p) : returning %p\n", This, *parent);
1466 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1467 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1468 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1469 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1470 TRACE("(%p) returning %p\n", This, *pDevice);
1474 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1475 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1476 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1478 if (NULL == pData) {
1479 *pSizeOfData = This->baseShader.functionLength;
1482 if (*pSizeOfData < This->baseShader.functionLength) {
1483 *pSizeOfData = This->baseShader.functionLength;
1484 return WINED3DERR_MOREDATA;
1486 if (NULL == This->baseShader.function) { /* no function defined */
1487 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1488 (*(DWORD **) pData) = NULL;
1490 if(This->baseShader.functionLength == 0){
1493 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1494 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1499 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1500 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1501 const DWORD* pToken = pFunction;
1502 const SHADER_OPCODE* curOpcode = NULL;
1505 TRACE("(%p) : Parsing programme\n", This);
1507 /* Initialise vertex input arrays */
1508 This->namedArrays = FALSE;
1509 This->declaredArrays = FALSE;
1510 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1511 This->arrayUsageMap[i] = -1;
1513 if (NULL != pToken) {
1514 while (D3DVS_END() != *pToken) {
1515 if (shader_is_vshader_version(*pToken)) { /** version */
1516 vshader_set_version(This, *pToken);
1521 if (shader_is_comment(*pToken)) { /** comment */
1522 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1524 TRACE("//%s\n", (char*)pToken);
1525 pToken += comment_len;
1526 len += comment_len + 1;
1529 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1532 if (NULL == curOpcode) {
1533 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1534 while (*pToken & 0x80000000) {
1535 /* unknown current opcode ... */
1536 FIXME("unrecognized opcode: %08lx", *pToken);
1543 if (curOpcode->opcode == D3DSIO_DCL) {
1545 DWORD usage = *pToken;
1546 DWORD param = *(pToken + 1);
1548 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1549 shader_program_dump_decl_usage(usage, param);
1550 shader_dump_ins_modifiers(param);
1552 shader_dump_param((IWineD3DBaseShader*) This, param, 0);
1557 if (curOpcode->opcode == D3DSIO_DEF) {
1558 TRACE("def c%lu = ", *pToken & 0xFF);
1561 TRACE("%f ,", *(float *)pToken);
1564 TRACE("%f ,", *(float *)pToken);
1567 TRACE("%f ,", *(float *)pToken);
1570 TRACE("%f", *(float *)pToken);
1574 TRACE("%s", curOpcode->name);
1575 if (curOpcode->num_params > 0) {
1576 shader_dump_ins_modifiers(*pToken);
1578 shader_dump_param((IWineD3DBaseShader*) This, *pToken, 0);
1581 for (i = 1; i < curOpcode->num_params; ++i) {
1583 shader_dump_param((IWineD3DBaseShader*) This, *pToken, 1);
1592 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1594 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1597 /* Handy for debugging using numbered arrays instead of named arrays */
1599 /* TODO: using numbered arrays for software shaders makes things easier */
1600 This->declaredArrays = TRUE;
1603 /* named arrays and declared arrays are mutually exclusive */
1604 if (This->declaredArrays)
1605 This->namedArrays = FALSE;
1607 /* Generate HW shader in needed */
1608 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1610 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1614 /* copy the function ... because it will certainly be released by application */
1615 if (NULL != pFunction) {
1616 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1617 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1619 This->baseShader.function = NULL;
1624 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1626 /*** IUnknown methods ***/
1627 IWineD3DVertexShaderImpl_QueryInterface,
1628 IWineD3DVertexShaderImpl_AddRef,
1629 IWineD3DVertexShaderImpl_Release,
1630 /*** IWineD3DBase methods ***/
1631 IWineD3DVertexShaderImpl_GetParent,
1632 /*** IWineD3DBaseShader methods ***/
1633 IWineD3DVertexShaderImpl_SetFunction,
1634 /*** IWineD3DVertexShader methods ***/
1635 IWineD3DVertexShaderImpl_GetDevice,
1636 IWineD3DVertexShaderImpl_GetFunction