2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006 Ivan Gyurdiev
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
35 /* Shader debugging - Change the following line to enable debugging of software
37 #if 0 /* Musxt not be 1 in cvs version */
38 # define VSTRACE(A) TRACE A
39 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
42 # define TRACE_VSVECTOR(name)
45 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
48 * DirectX9 SDK download
49 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
52 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
54 * Using Vertex Shaders
55 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
58 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
64 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
67 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
70 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
72 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
73 * http://developer.nvidia.com/view.asp?IO=vstovp
75 * NVIDIA: Memory Management with VAR
76 * http://developer.nvidia.com/view.asp?IO=var_memory_management
79 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
80 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
82 #define GLNAME_REQUIRE_GLSL ((const char *)1)
84 /*******************************
85 * vshader functions software VM
88 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
93 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
94 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
97 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
98 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
99 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
100 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
103 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
104 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
105 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
106 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
109 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
111 d->y = s0->y * s1->y;
114 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
115 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
118 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
124 tmp.f = floorf(s0->w);
125 d->x = powf(2.0f, tmp.f);
126 d->y = s0->w - tmp.f;
127 tmp.f = powf(2.0f, s0->w);
128 tmp.d &= 0xFFFFFF00U;
131 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
132 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
135 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
137 d->y = (0.0f < s0->x) ? s0->x : 0.0f;
138 d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
140 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
141 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
144 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
145 float tmp_f = fabsf(s0->w);
146 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
147 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
148 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
151 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
152 d->x = s0->x * s1->x + s2->x;
153 d->y = s0->y * s1->y + s2->y;
154 d->z = s0->z * s1->z + s2->z;
155 d->w = s0->w * s1->w + s2->w;
156 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
157 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, s2->x, s2->y, s2->z, s2->w, d->x, d->y, d->z, d->w));
160 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
161 d->x = (s0->x >= s1->x) ? s0->x : s1->x;
162 d->y = (s0->y >= s1->y) ? s0->y : s1->y;
163 d->z = (s0->z >= s1->z) ? s0->z : s1->z;
164 d->w = (s0->w >= s1->w) ? s0->w : s1->w;
165 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
166 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
169 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
170 d->x = (s0->x < s1->x) ? s0->x : s1->x;
171 d->y = (s0->y < s1->y) ? s0->y : s1->y;
172 d->z = (s0->z < s1->z) ? s0->z : s1->z;
173 d->w = (s0->w < s1->w) ? s0->w : s1->w;
174 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
175 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
178 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
183 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
184 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
187 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
188 d->x = s0->x * s1->x;
189 d->y = s0->y * s1->y;
190 d->z = s0->z * s1->z;
191 d->w = s0->w * s1->w;
192 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
193 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
196 void vshader_nop(void) {
197 /* NOPPPP ahhh too easy ;) */
198 VSTRACE(("executing nop\n"));
201 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
202 d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
203 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
207 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
208 float tmp_f = fabsf(s0->w);
209 d->x = d->y = d->z = d->w = (0.0f == tmp_f) ? HUGE_VAL : ((1.0f != tmp_f) ? 1.0f / sqrtf(tmp_f) : 1.0f);
210 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
211 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
214 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
215 d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
216 d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
217 d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
218 d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
219 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
220 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
223 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
224 d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
225 d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
226 d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
227 d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
228 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
229 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
232 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
233 d->x = s0->x - s1->x;
234 d->y = s0->y - s1->y;
235 d->z = s0->z - s1->z;
236 d->w = s0->w - s1->w;
237 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
238 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
242 * Version 1.1 specific
245 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
246 d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
247 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
248 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
251 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
252 float tmp_f = fabsf(s0->w);
253 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
254 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
255 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
258 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
259 d->x = s0->x - floorf(s0->x);
260 d->y = s0->y - floorf(s0->y);
263 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
264 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
267 typedef FLOAT D3DMATRIX44[4][4];
268 typedef FLOAT D3DMATRIX43[4][3];
269 typedef FLOAT D3DMATRIX34[3][4];
270 typedef FLOAT D3DMATRIX33[3][3];
271 typedef FLOAT D3DMATRIX23[2][3];
273 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
275 * Buggy CODE: here only if cast not work for copy/paste
276 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
277 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
278 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
279 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
280 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
281 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
282 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
284 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
285 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
286 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
287 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
288 VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
289 VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
290 VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
291 VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
294 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
295 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
299 VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
300 VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
301 VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
302 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
305 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
307 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
308 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
309 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
310 VSTRACE(("executing m3x4(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
311 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
312 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
313 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
316 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
321 VSTRACE(("executing m3x3(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
322 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
324 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
327 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
329 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
330 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
336 * Version 2.0 specific
338 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
339 d->x = s0->x * (s1->x - s2->x) + s2->x;
340 d->y = s0->y * (s1->y - s2->y) + s2->y;
341 d->z = s0->z * (s1->z - s2->z) + s2->z;
342 d->w = s0->w * (s1->w - s2->w) + s2->w;
345 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
346 d->x = s0->y * s1->z - s0->z * s1->y;
347 d->y = s0->z * s1->x - s0->x * s1->z;
348 d->z = s0->x * s1->y - s0->y * s1->x;
349 d->w = 0.9f; /* w is undefined, so set it to something safeish */
351 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
352 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
355 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
361 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
362 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
367 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
368 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
372 void vshader_call(WINED3DSHADERVECTOR* d) {
376 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
380 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
384 void vshader_ret(void) {
388 void vshader_endloop(void) {
392 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
396 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
400 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408 void vshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
412 void vshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
416 void vshader_rep(WINED3DSHADERVECTOR* d) {
420 void vshader_endrep(void) {
424 void vshader_if(WINED3DSHADERVECTOR* d) {
428 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
432 void vshader_else(void) {
436 void vshader_label(WINED3DSHADERVECTOR* d) {
440 void vshader_endif(void) {
444 void vshader_break(void) {
448 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
452 void vshader_breakp(WINED3DSHADERVECTOR* d) {
456 void vshader_mova(WINED3DSHADERVECTOR* d) {
460 void vshader_defb(WINED3DSHADERVECTOR* d) {
464 void vshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
468 void vshader_texldd(WINED3DSHADERVECTOR* d) {
472 void vshader_setp(WINED3DSHADERVECTOR* d) {
476 void vshader_texldl(WINED3DSHADERVECTOR* d) {
481 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
482 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
483 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
484 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
487 * log, exp, frc, m*x* seems to be macros ins ... to see
489 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
492 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
511 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
512 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
513 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, NULL, NULL, 0, 0},
514 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
515 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
516 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
517 /* TODO: sng can possibly be performed a s
520 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
521 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
524 MUL vec.xyz, vec, tmp;
525 but I think this is better because it accounts for w properly.
531 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, NULL, 0, 0},
532 {D3DSIO_SINCOS, "sincos", NULL, 4, vshader_sincos2, NULL, NULL, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
533 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos3, NULL, NULL, D3DVS_VERSION(3,0), -1},
536 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
537 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
538 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
539 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
540 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
542 /* Declare registers */
543 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
545 /* Constant definitions */
546 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
547 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
548 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 5, vshader_defi, NULL, NULL, 0, 0},
550 /* Flow control - requires GLSL or software shaders */
551 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
552 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
553 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
554 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
555 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
556 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
557 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
558 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
559 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
560 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
561 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
562 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
563 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
564 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
565 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
567 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
568 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, NULL, 0, 0},
569 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
570 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
573 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
574 /** operand output */
575 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
577 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
578 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
579 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
580 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
584 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
585 static const char swizzle_reg_chars_color_fix[] = "zyxw";
586 static const char swizzle_reg_chars[] = "xyzw";
587 const char* swizzle_regs = NULL;
591 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
592 DWORD swizzle_x = swizzle & 0x03;
593 DWORD swizzle_y = (swizzle >> 2) & 0x03;
594 DWORD swizzle_z = (swizzle >> 4) & 0x03;
595 DWORD swizzle_w = (swizzle >> 6) & 0x03;
598 swizzle_regs = swizzle_reg_chars_color_fix;
600 swizzle_regs = swizzle_reg_chars;
604 * swizzle bits fields:
607 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
609 sprintf(tmpReg, ".%c%c%c%c",
610 swizzle_regs[swizzle_x],
611 swizzle_regs[swizzle_y],
612 swizzle_regs[swizzle_z],
613 swizzle_regs[swizzle_w]);
614 strcat(hwLine, tmpReg);
618 if (swizzle_x == swizzle_y &&
619 swizzle_x == swizzle_z &&
620 swizzle_x == swizzle_w)
622 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
623 strcat(hwLine, tmpReg);
625 sprintf(tmpReg, ".%c%c%c%c",
626 swizzle_regs[swizzle_x],
627 swizzle_regs[swizzle_y],
628 swizzle_regs[swizzle_z],
629 swizzle_regs[swizzle_w]);
630 strcat(hwLine, tmpReg);
634 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
635 /* oPos, oFog and oPts in D3D */
636 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
638 DWORD reg = param & D3DSP_REGNUM_MASK;
639 DWORD regtype = shader_get_regtype(param);
641 BOOL is_color = FALSE;
643 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
644 strcat(hwLine, " -");
651 sprintf(tmpReg, "R%lu", reg);
652 strcat(hwLine, tmpReg);
655 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
656 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
659 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
660 if (This->namedArrays) {
661 sprintf(tmpReg, "namedVertex%lu", reg);
663 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
664 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
666 strcat(hwLine, tmpReg);
669 /* FIXME: some constants are named so we need a constants map*/
670 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
671 if (param & D3DVS_ADDRMODE_RELATIVE) {
672 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
674 sprintf(tmpReg, "const%lu", reg);
676 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
678 strcat(hwLine, tmpReg);
680 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
681 sprintf(tmpReg, "A%lu", reg);
682 strcat(hwLine, tmpReg);
685 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
686 strcat(hwLine, tmpReg);
690 strcat(hwLine, "result.color.primary");
692 strcat(hwLine, "result.color.secondary");
695 case D3DSPR_TEXCRDOUT:
696 sprintf(tmpReg, "result.texcoord[%lu]", reg);
697 strcat(hwLine, tmpReg);
700 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
701 strcat(hwLine, "unrecognized_register");
706 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
708 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
712 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
714 switch(usage & 0xFFFF) {
715 case D3DDECLUSAGE_POSITION:
716 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
717 TRACE("Setting position to %d\n", arrayNo);
718 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
719 This->namedArrays = TRUE;
721 /* TODO: position indexes go from 0-8!!*/
722 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
723 /* robots uses positions up to 8, the position arrays are just packed.*/
724 if ((usage & 0xF0000) >> 16 > 1) {
725 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
727 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
728 This->declaredArrays = TRUE;
731 case D3DDECLUSAGE_BLENDINDICES:
732 /* not supported by openGL */
733 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
734 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
735 This->declaredArrays = TRUE;
736 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
738 case D3DDECLUSAGE_BLENDWEIGHT:
739 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
740 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
741 This->namedArrays = TRUE;
742 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
744 case D3DDECLUSAGE_NORMAL:
745 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
746 TRACE("Setting normal to %d\n", arrayNo);
747 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
748 This->namedArrays = TRUE;
750 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
751 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
752 This->declaredArrays = TRUE;
755 case D3DDECLUSAGE_PSIZE:
756 TRACE("Setting PSIZE to %d\n", arrayNo);
757 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
758 This->namedArrays = TRUE;
759 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
761 case D3DDECLUSAGE_COLOR:
762 if((usage & 0xF0000) >> 16 == 0) {
763 TRACE("Setting DIFFUSE to %d\n", arrayNo);
764 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
765 This->namedArrays = TRUE;
767 TRACE("Setting SPECULAR to %d\n", arrayNo);
768 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
769 This->namedArrays = TRUE;
772 case D3DDECLUSAGE_TEXCOORD:
773 This->namedArrays = TRUE;
774 /* only 7 texture coords have been designed for, so run a quick sanity check */
775 if ((usage & 0xF0000) >> 16 > 7) {
776 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
778 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
779 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
782 /* The following aren't supported by openGL,
783 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
784 this should be caught in the first pass */
785 case D3DDECLUSAGE_TANGENT:
786 TRACE("Setting TANGENT to %d\n", arrayNo);
787 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
788 This->declaredArrays = TRUE;
790 case D3DDECLUSAGE_BINORMAL:
791 TRACE("Setting BINORMAL to %d\n", arrayNo);
792 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
793 This->declaredArrays = TRUE;
795 case D3DDECLUSAGE_TESSFACTOR:
796 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
797 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
798 This->declaredArrays = TRUE;
800 case D3DDECLUSAGE_POSITIONT:
801 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
802 FIXME("Setting positiont to %d\n", arrayNo);
803 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
804 This->namedArrays = TRUE;
806 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
807 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
808 This->declaredArrays = TRUE;
809 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
812 case D3DDECLUSAGE_FOG:
813 /* supported by OpenGL */
814 TRACE("Setting FOG to %d\n", arrayNo);
815 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
816 This->namedArrays = TRUE;
818 case D3DDECLUSAGE_DEPTH:
819 TRACE("Setting DEPTH to %d\n", arrayNo);
820 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
821 This->declaredArrays = TRUE;
823 case D3DDECLUSAGE_SAMPLE:
824 TRACE("Setting SAMPLE to %d\n", arrayNo);
825 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
826 This->declaredArrays = TRUE;
829 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
833 void vshader_set_version(
834 IWineD3DVertexShaderImpl *This,
837 DWORD major = (version >> 8) & 0x0F;
838 DWORD minor = version & 0x0F;
840 This->baseShader.hex_version = version;
841 This->baseShader.version = major * 10 + minor;
842 TRACE("vs_%lu_%lu\n", major, minor);
844 This->baseShader.limits.texture = 0;
846 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
847 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
849 switch (This->baseShader.version) {
851 case 11: This->baseShader.limits.temporary = 12;
852 This->baseShader.limits.constant_bool = 0;
853 This->baseShader.limits.constant_int = 0;
854 This->baseShader.limits.address = 1;
858 case 21: This->baseShader.limits.temporary = 12;
859 This->baseShader.limits.constant_bool = 16;
860 This->baseShader.limits.constant_int = 16;
861 This->baseShader.limits.address = 1;
864 case 30: This->baseShader.limits.temporary = 32;
865 This->baseShader.limits.constant_bool = 32;
866 This->baseShader.limits.constant_int = 32;
867 This->baseShader.limits.address = 1;
870 default: This->baseShader.limits.temporary = 12;
871 This->baseShader.limits.constant_bool = 0;
872 This->baseShader.limits.constant_int = 0;
873 This->baseShader.limits.address = 1;
874 FIXME("Unrecognized vertex shader version %lx!\n", version);
878 /* Map the opcode 1-to-1 to the GL code */
879 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
881 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
882 CONST SHADER_OPCODE* curOpcode = arg->opcode;
883 SHADER_BUFFER* buffer = arg->buffer;
884 DWORD dst = arg->dst;
885 DWORD* src = arg->src;
887 DWORD dst_regtype = shader_get_regtype(dst);
891 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
892 strcpy(tmpLine, "ARL");
894 strcpy(tmpLine, curOpcode->glname);
896 if (curOpcode->num_params > 0) {
897 vshader_program_add_param(This, dst, FALSE, tmpLine);
898 for (i = 1; i < curOpcode->num_params; ++i) {
899 strcat(tmpLine, ",");
900 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
903 shader_addline(buffer, "%s;\n", tmpLine);
906 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
908 DWORD dst = arg->dst;
909 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
911 SHADER_BUFFER* buffer = arg->buffer;
913 if (This->namedArrays) {
914 const char* attribName = "undefined";
915 switch(dst & 0xFFFF) {
916 case D3DDECLUSAGE_POSITION:
917 attribName = "vertex.position";
919 case D3DDECLUSAGE_BLENDINDICES:
920 /* not supported by openGL */
921 attribName = "vertex.blend";
923 case D3DDECLUSAGE_BLENDWEIGHT:
924 attribName = "vertex.weight";
926 case D3DDECLUSAGE_NORMAL:
927 attribName = "vertex.normal";
929 case D3DDECLUSAGE_PSIZE:
930 attribName = "vertex.psize";
932 case D3DDECLUSAGE_COLOR:
933 if((dst & 0xF0000) >> 16 == 0) {
934 attribName = "vertex.color";
936 attribName = "vertex.color.secondary";
939 case D3DDECLUSAGE_TEXCOORD:
943 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
944 attribName = tmpChar;
947 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
948 case D3DDECLUSAGE_TANGENT:
949 attribName = "vertex.tangent";
951 case D3DDECLUSAGE_BINORMAL:
952 attribName = "vertex.binormal";
954 case D3DDECLUSAGE_TESSFACTOR:
955 attribName = "vertex.tessfactor";
957 case D3DDECLUSAGE_POSITIONT:
958 attribName = "vertex.possitionT";
960 case D3DDECLUSAGE_FOG:
961 attribName = "vertex.fogcoord";
963 case D3DDECLUSAGE_DEPTH:
964 attribName = "vertex.depth";
966 case D3DDECLUSAGE_SAMPLE:
967 attribName = "vertex.sample";
970 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
973 sprintf(tmpLine, "ATTRIB ");
974 vshader_program_add_param(This, dst, FALSE, tmpLine);
975 if (This->namedArrays)
976 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
981 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
983 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
984 SHADER_BUFFER* buffer = arg->buffer;
985 DWORD reg = arg->dst;
987 shader_addline(buffer,
988 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
989 *((const float *)(arg->src + 0)),
990 *((const float *)(arg->src + 1)),
991 *((const float *)(arg->src + 2)),
992 *((const float *)(arg->src + 3)) );
994 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
997 /** Handles transforming all D3DSIO_M?x? opcodes for
998 Vertex shaders to ARB_vertex_program codes */
999 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1002 int nComponents = 0;
1003 SHADER_OPCODE_ARG tmpArg;
1005 /* Set constants for the temporary argument */
1006 tmpArg.shader = arg->shader;
1007 tmpArg.buffer = arg->buffer;
1008 tmpArg.src[0] = arg->src[0];
1010 switch(arg->opcode->opcode) {
1013 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1017 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1021 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1025 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1029 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1035 for (i = 0; i < nComponents; i++) {
1036 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1037 tmpArg.src[1] = arg->src[1]+i;
1038 vshader_hw_map2gl(&tmpArg);
1042 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1043 or GLSL and send it to the card */
1044 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1045 IWineD3DVertexShader *iface,
1046 CONST DWORD *pFunction) {
1048 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1049 SHADER_BUFFER buffer;
1051 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1052 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1053 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1054 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1055 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1056 This->fixupVertexBufferSize = PGMSIZE;
1057 This->fixupVertexBuffer[0] = 0;
1059 buffer.buffer = This->device->fixupVertexBuffer;
1061 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1066 /* TODO: Optionally, generate the GLSL shader instead */
1067 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1068 /* Create the hw ARB shader */
1069 shader_addline(&buffer, "!!ARBvp1.0\n");
1071 /* Mesa supports only 95 constants */
1072 if (GL_VEND(MESA) || GL_VEND(WINE))
1073 This->baseShader.limits.constant_float =
1074 min(95, This->baseShader.limits.constant_float);
1076 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1077 This->baseShader.limits.constant_float,
1078 This->baseShader.limits.constant_float - 1);
1080 /** Call the base shader generation routine to generate most
1081 of the vertex shader string for us */
1082 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1084 shader_addline(&buffer, "END\n\0");
1086 /* TODO: change to resource.glObjectHandle or something like that */
1087 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1089 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1090 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1092 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1093 /* Create the program and check for errors */
1094 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1095 buffer.bsize, buffer.buffer));
1097 if (glGetError() == GL_INVALID_OPERATION) {
1099 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1100 FIXME("HW VertexShader Error at position %d: %s\n",
1101 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1102 This->baseShader.prgId = -1;
1106 #if 1 /* if were using the data buffer of device then we don't need to free it */
1107 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1111 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1113 * TODO: use the NV_vertex_program (or 1_1) extension
1114 * and specifics vendors (ARB_vertex_program??) variants for it
1119 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1120 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1123 /** Vertex Shader Temporary Registers */
1124 WINED3DSHADERVECTOR R[12];
1125 /*D3DSHADERSCALAR A0;*/
1126 WINED3DSHADERVECTOR A[1];
1127 /** temporary Vector for modifier management */
1128 WINED3DSHADERVECTOR d;
1129 WINED3DSHADERVECTOR s[3];
1131 const DWORD* pToken = This->baseShader.function;
1132 const SHADER_OPCODE* curOpcode = NULL;
1133 /** functions parameters */
1134 WINED3DSHADERVECTOR* p[6];
1135 WINED3DSHADERVECTOR* p_send[6];
1138 /** init temporary register */
1139 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1141 /* vshader_program_parse(vshader); */
1142 #if 0 /* Must not be 1 in cvs */
1144 TRACE_VSVECTOR(This->data->C[0]);
1145 TRACE_VSVECTOR(This->data->C[1]);
1146 TRACE_VSVECTOR(This->data->C[2]);
1147 TRACE_VSVECTOR(This->data->C[3]);
1148 TRACE_VSVECTOR(This->data->C[4]);
1149 TRACE_VSVECTOR(This->data->C[5]);
1150 TRACE_VSVECTOR(This->data->C[6]);
1151 TRACE_VSVECTOR(This->data->C[7]);
1152 TRACE_VSVECTOR(This->data->C[8]);
1153 TRACE_VSVECTOR(This->data->C[64]);
1154 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1155 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1156 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1157 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1158 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1159 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1160 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1161 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1162 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1165 TRACE_VSVECTOR(vshader->data->C[64]);
1166 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1168 /* the first dword is the version tag */
1169 /* TODO: parse it */
1171 if (shader_is_vshader_version(*pToken)) { /** version */
1174 while (D3DVS_END() != *pToken) {
1175 if (shader_is_comment(*pToken)) { /** comment */
1176 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1178 pToken += comment_len;
1182 opcode_token = *pToken++;
1183 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1185 if (NULL == curOpcode) {
1186 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1187 pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
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;
1506 TRACE("(%p) : Parsing programme\n", This);
1508 /* Initialise vertex input arrays */
1509 This->namedArrays = FALSE;
1510 This->declaredArrays = FALSE;
1511 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1512 This->arrayUsageMap[i] = -1;
1514 if (NULL != pToken) {
1515 while (D3DVS_END() != *pToken) {
1516 if (shader_is_vshader_version(*pToken)) { /** version */
1517 vshader_set_version(This, *pToken);
1522 if (shader_is_comment(*pToken)) { /** comment */
1523 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1525 TRACE("//%s\n", (char*)pToken);
1526 pToken += comment_len;
1527 len += comment_len + 1;
1531 opcode_token = *pToken++;
1532 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1535 if (NULL == curOpcode) {
1538 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1539 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1540 pToken += tokens_read;
1544 if (curOpcode->opcode == D3DSIO_DCL) {
1546 DWORD usage = *pToken;
1547 DWORD param = *(pToken + 1);
1549 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1550 shader_program_dump_decl_usage(usage, param);
1551 shader_dump_ins_modifiers(param);
1553 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1558 if (curOpcode->opcode == D3DSIO_DEF) {
1559 TRACE("def c%lu = ", *pToken & 0xFF);
1562 TRACE("%f ,", *(float *)pToken);
1565 TRACE("%f ,", *(float *)pToken);
1568 TRACE("%f ,", *(float *)pToken);
1571 TRACE("%f", *(float *)pToken);
1576 DWORD param, addr_token;
1579 TRACE("%s", curOpcode->name);
1580 if (curOpcode->num_params > 0) {
1582 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1583 pToken, ¶m, &addr_token);
1584 pToken += tokens_read;
1587 shader_dump_ins_modifiers(param);
1589 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1591 for (i = 1; i < curOpcode->num_params; ++i) {
1593 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1594 pToken, ¶m, &addr_token);
1595 pToken += tokens_read;
1599 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1606 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1608 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1611 /* Handy for debugging using numbered arrays instead of named arrays */
1613 /* TODO: using numbered arrays for software shaders makes things easier */
1614 This->declaredArrays = TRUE;
1617 /* named arrays and declared arrays are mutually exclusive */
1618 if (This->declaredArrays)
1619 This->namedArrays = FALSE;
1621 /* Generate HW shader in needed */
1622 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1624 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1628 /* copy the function ... because it will certainly be released by application */
1629 if (NULL != pFunction) {
1630 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1631 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1633 This->baseShader.function = NULL;
1638 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1640 /*** IUnknown methods ***/
1641 IWineD3DVertexShaderImpl_QueryInterface,
1642 IWineD3DVertexShaderImpl_AddRef,
1643 IWineD3DVertexShaderImpl_Release,
1644 /*** IWineD3DBase methods ***/
1645 IWineD3DVertexShaderImpl_GetParent,
1646 /*** IWineD3DBaseShader methods ***/
1647 IWineD3DVertexShaderImpl_SetFunction,
1648 /*** IWineD3DVertexShader methods ***/
1649 IWineD3DVertexShaderImpl_GetDevice,
1650 IWineD3DVertexShaderImpl_GetFunction