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));
365 void vshader_texcoord(WINED3DSHADERVECTOR* d) {
369 void vshader_texkill(WINED3DSHADERVECTOR* d) {
373 void vshader_tex(WINED3DSHADERVECTOR* d) {
376 void vshader_texld(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
380 void vshader_texbem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
384 void vshader_texbeml(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
388 void vshader_texreg2ar(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
392 void vshader_texreg2gb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
396 void vshader_texm3x2pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
400 void vshader_texm3x2tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404 void vshader_texm3x3pad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408 void vshader_texm3x3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
412 void vshader_texm3x3diff(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
416 void vshader_texm3x3spec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
420 void vshader_texm3x3vspec(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424 void vshader_cnd(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
428 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
429 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
433 void vshader_texreg2rgb(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
437 void vshader_texdp3tex(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
441 void vshader_texm3x2depth(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
445 void vshader_texdp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449 void vshader_texm3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
453 void vshader_texdepth(WINED3DSHADERVECTOR* d) {
457 void vshader_cmp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
461 void vshader_bem(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
465 void vshader_call(WINED3DSHADERVECTOR* d) {
469 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
473 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
477 void vshader_ret(WINED3DSHADERVECTOR* d) {
481 void vshader_endloop(WINED3DSHADERVECTOR* d) {
485 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
489 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
493 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
497 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
501 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
505 void vshader_rep(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
509 void vshader_endrep(void) {
513 void vshader_if(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
517 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
521 void vshader_else(WINED3DSHADERVECTOR* d) {
525 void vshader_label(WINED3DSHADERVECTOR* d) {
529 void vshader_endif(WINED3DSHADERVECTOR* d) {
533 void vshader_break(WINED3DSHADERVECTOR* d) {
537 void vshader_breakc(WINED3DSHADERVECTOR* d) {
541 void vshader_mova(WINED3DSHADERVECTOR* d) {
545 void vshader_defb(WINED3DSHADERVECTOR* d) {
549 void vshader_defi(WINED3DSHADERVECTOR* d) {
553 void vshader_dp2add(WINED3DSHADERVECTOR* d) {
557 void vshader_dsx(WINED3DSHADERVECTOR* d) {
561 void vshader_dsy(WINED3DSHADERVECTOR* d) {
565 void vshader_texldd(WINED3DSHADERVECTOR* d) {
569 void vshader_setp(WINED3DSHADERVECTOR* d) {
573 void vshader_texldl(WINED3DSHADERVECTOR* d) {
577 void vshader_breakp(WINED3DSHADERVECTOR* d) {
583 * log, exp, frc, m*x* seems to be macros ins ... to see
585 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
586 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, 0, 0},
587 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, 0, 0},
588 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, 0, 0},
589 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, 0, 0},
590 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, 0, 0},
591 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, 0, 0},
592 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, 0, 0},
593 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, 0, 0},
594 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, 0, 0},
595 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, 0, 0},
596 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, 0, 0},
597 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, 0, 0},
598 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, 0, 0},
599 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, 0, 0},
600 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, 0, 0},
601 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, 0, 0},
602 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, 0, 0},
603 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, 0, 0},
604 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, 0, 0},
605 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, 0, 0},
606 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, 0, 0},
607 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, 0, 0},
608 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, 0, 0},
609 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, 0, 0},
610 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, 0, 0},
611 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, 0, 0},
612 /** FIXME: use direct access so add the others opcodes as stubs */
613 /* NOTE: gl function is currently NULL for calls and loops because they are not yet supported
614 They can be easily managed in software by introducing a call/loop stack and should be possible to implement in glsl ol NV_shader's */
615 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, 0, 0},
616 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, 0, 0},
617 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, 0, 0},
618 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, 0, 0},
619 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, 0, 0},
620 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, 0, 0},
621 /* DCL is a specil operation */
622 {D3DSIO_DCL, "dcl", NULL, 1, vshader_dcl, 0, 0},
623 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, 0, 0},
624 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, 0, 0},
625 /* TODO: sng can possibly be performed as
628 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, 0, 0},
629 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
632 MUL vec.xyz, vec, tmp;
633 but I think this is better because it accounts for w properly.
639 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, 0, 0},
640 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, 0, 0},
641 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 2, vshader_rep, 0, 0},
642 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, 0, 0},
643 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 2, vshader_if, 0, 0},
644 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, 0, 0},
645 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 2, vshader_else, 0, 0},
646 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 2, vshader_endif, 0, 0},
647 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 2, vshader_break, 0, 0},
648 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, 0, 0},
649 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, 0, 0},
650 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, 0, 0},
651 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, 0, 0},
653 {D3DSIO_TEXCOORD, "texcoord", GLNAME_REQUIRE_GLSL, 1, vshader_texcoord, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
654 {D3DSIO_TEXCOORD, "texcrd", GLNAME_REQUIRE_GLSL, 2, vshader_texcoord, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
655 {D3DSIO_TEXKILL, "texkill", GLNAME_REQUIRE_GLSL, 1, vshader_texkill, D3DPS_VERSION(1,0), D3DPS_VERSION(1,4)},
656 {D3DSIO_TEX, "tex", GLNAME_REQUIRE_GLSL, 1, vshader_tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
657 {D3DSIO_TEX, "texld", GLNAME_REQUIRE_GLSL, 2, vshader_texld, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
658 {D3DSIO_TEXBEM, "texbem", GLNAME_REQUIRE_GLSL, 2, vshader_texbem, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
659 {D3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 2, vshader_texbeml, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
660 {D3DSIO_TEXREG2AR,"texreg2ar",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2ar, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
661 {D3DSIO_TEXREG2GB,"texreg2gb",GLNAME_REQUIRE_GLSL, 2, vshader_texreg2gb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
662 {D3DSIO_TEXM3x2PAD, "texm3x2pad", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2pad, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
663 {D3DSIO_TEXM3x2TEX, "texm3x2tex", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2tex, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
664 {D3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3diff, D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)},
665 {D3DSIO_TEXM3x3SPEC, "texm3x3spec", GLNAME_REQUIRE_GLSL, 3, vshader_texm3x3spec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
666 {D3DSIO_TEXM3x3VSPEC, "texm3x3vspe", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3vspec, D3DPS_VERSION(1,0), D3DPS_VERSION(1,3)},
668 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, 0, 0},
669 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, 0, 0},
670 {D3DSIO_CND, "cnd", GLNAME_REQUIRE_GLSL, 4, vshader_cnd, D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
671 /* def is a special operation */
672 {D3DSIO_DEF, "def", NULL, 5, vshader_def, D3DPS_VERSION(1,0), D3DPS_VERSION(3,0)},
673 {D3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 2, vshader_texreg2rgb, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
674 {D3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3tex, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
675 {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x2depth,D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)},
676 {D3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 2, vshader_texdp3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
677 {D3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 2, vshader_texm3x3, D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
678 {D3DSIO_TEXDEPTH, "texdepth", GLNAME_REQUIRE_GLSL,1, vshader_texdepth, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
679 {D3DSIO_CMP, "cmp", GLNAME_REQUIRE_GLSL, 4, vshader_cmp, D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
680 {D3DSIO_BEM, "bem", GLNAME_REQUIRE_GLSL, 3, vshader_bem, D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
681 /* TODO: dp2add can be made out of multiple instuctions */
682 {D3DSIO_DP2ADD, "dp2add", GLNAME_REQUIRE_GLSL, 2, vshader_dp2add, 0, 0},
683 {D3DSIO_DSX, "dsx", GLNAME_REQUIRE_GLSL, 2, vshader_dsx, 0, 0},
684 {D3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 2, vshader_dsy, 0, 0},
685 {D3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 2, vshader_texldd, 0, 0},
686 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, 0, 0},
687 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, 0, 0},
688 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 2, vshader_breakp, 0, 0},
689 {D3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, vshader_nop, 0, 0},
690 {0, NULL, NULL, 0, NULL, 0, 0}
694 inline static const SHADER_OPCODE* vshader_program_get_opcode(IWineD3DVertexShaderImpl *This, const DWORD code) {
696 const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
698 /** TODO: use dichotomic search or hash table */
699 while (NULL != shader_ins[i].name) {
700 if ((code & D3DSI_OPCODE_MASK) == shader_ins[i].opcode) {
701 return &shader_ins[i];
705 FIXME("Unsupported opcode %lx\n",code);
709 inline static void vshader_program_dump_param(const DWORD param, int input) {
710 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
711 static const char swizzle_reg_chars[] = "xyzw";
713 DWORD reg = param & 0x00001FFF;
714 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
716 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
720 TRACE("R[%lu]", reg);
726 TRACE("C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
728 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
729 TRACE("a[%lu]", reg);
732 TRACE("%s", rastout_reg_names[reg]);
735 TRACE("oD[%lu]", reg);
737 case D3DSPR_TEXCRDOUT:
738 TRACE("oT[%lu]", reg);
741 FIXME("Unknown %lu %u reg %lu\n",regtype, D3DSPR_ATTROUT, reg);
746 /** operand output */
747 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
748 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
749 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
750 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
751 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
755 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
756 DWORD swizzle_x = swizzle & 0x03;
757 DWORD swizzle_y = (swizzle >> 2) & 0x03;
758 DWORD swizzle_z = (swizzle >> 4) & 0x03;
759 DWORD swizzle_w = (swizzle >> 6) & 0x03;
761 * swizzle bits fields:
764 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
765 if (swizzle_x == swizzle_y &&
766 swizzle_x == swizzle_z &&
767 swizzle_x == swizzle_w) {
768 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
771 swizzle_reg_chars[swizzle_x],
772 swizzle_reg_chars[swizzle_y],
773 swizzle_reg_chars[swizzle_z],
774 swizzle_reg_chars[swizzle_w]);
780 inline static void vshader_program_dump_vs_param(const DWORD param, int input) {
781 static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
782 static const char swizzle_reg_chars[] = "xyzw";
783 /* the unknown mask is for bits not yet accounted for by any other mask... */
784 #define UNKNOWN_MASK 0xC000
786 /* for registeres about 7 we have to add on bits 11 and 12 to get the correct register */
787 #define EXTENDED_REG 0x1800
789 DWORD reg = param & D3DSP_REGNUM_MASK; /* 0x00001FFF; isn't this D3DSP_REGNUM_MASK? */
790 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & EXTENDED_REG) >> 8);
792 if(param & UNKNOWN_MASK) { /* if this register has any of the unknown bits set then report them*/
793 FIXME("Unknown bits set regtype %lx , %lx, UK(%lx)\n", regtype, (param & EXTENDED_REG), param & UNKNOWN_MASK);
796 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
798 switch (regtype /*<< D3DSP_REGTYPE_SHIFT*/) {
806 TRACE("c%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
808 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
812 TRACE("%s", rastout_reg_names[reg]);
817 case D3DSPR_TEXCRDOUT:
820 case D3DSPR_CONSTINT:
821 TRACE("i%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
823 case D3DSPR_CONSTBOOL:
824 TRACE("b%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
830 TRACE("aL%s%lu", (param & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
833 FIXME("Unknown %lu reg %lu\n",regtype, reg);
838 /** operand output */
839 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
840 if (param & D3DSP_WRITEMASK_0) TRACE(".x");
841 if (param & D3DSP_WRITEMASK_1) TRACE(".y");
842 if (param & D3DSP_WRITEMASK_2) TRACE(".z");
843 if (param & D3DSP_WRITEMASK_3) TRACE(".w");
847 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
848 DWORD swizzle_x = swizzle & 0x03;
849 DWORD swizzle_y = (swizzle >> 2) & 0x03;
850 DWORD swizzle_z = (swizzle >> 4) & 0x03;
851 DWORD swizzle_w = (swizzle >> 6) & 0x03;
853 * swizzle bits fields:
856 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
857 if (swizzle_x == swizzle_y &&
858 swizzle_x == swizzle_z &&
859 swizzle_x == swizzle_w) {
860 TRACE(".%c", swizzle_reg_chars[swizzle_x]);
863 swizzle_reg_chars[swizzle_x],
864 swizzle_reg_chars[swizzle_y],
865 swizzle_reg_chars[swizzle_z],
866 swizzle_reg_chars[swizzle_w]);
872 inline static void vshader_program_dump_decl_usage(IWineD3DVertexShaderImpl *This, DWORD token) {
874 switch(token & 0xFFFF) {
875 case D3DDECLUSAGE_POSITION:
876 TRACE("%s%ld ", "position",(token & 0xF0000) >> 16);
878 case D3DDECLUSAGE_BLENDINDICES:
879 TRACE("%s ", "blend");
881 case D3DDECLUSAGE_BLENDWEIGHT:
882 TRACE("%s ", "weight");
884 case D3DDECLUSAGE_NORMAL:
885 TRACE("%s%ld ", "normal",(token & 0xF0000) >> 16);
887 case D3DDECLUSAGE_PSIZE:
888 TRACE("%s ", "psize");
890 case D3DDECLUSAGE_COLOR:
891 if((token & 0xF0000) >> 16 == 0) {
892 TRACE("%s ", "color");
894 TRACE("%s ", "specular");
897 case D3DDECLUSAGE_TEXCOORD:
898 TRACE("%s%ld ", "texture", (token & 0xF0000) >> 16);
900 case D3DDECLUSAGE_TANGENT:
901 TRACE("%s ", "tangent");
903 case D3DDECLUSAGE_BINORMAL:
904 TRACE("%s ", "binormal");
906 case D3DDECLUSAGE_TESSFACTOR:
907 TRACE("%s ", "tessfactor");
909 case D3DDECLUSAGE_POSITIONT:
910 TRACE("%s%ld ", "positionT",(token & 0xF0000) >> 16);
912 case D3DDECLUSAGE_FOG:
915 case D3DDECLUSAGE_DEPTH:
916 TRACE("%s ", "depth");
918 case D3DDECLUSAGE_SAMPLE:
919 TRACE("%s ", "sample");
922 FIXME("Unrecognised dcl %08lx", token & 0xFFFF);
926 inline static BOOL vshader_is_version_token(DWORD token) {
927 return 0xFFFE0000 == (token & 0xFFFE0000);
930 inline static BOOL vshader_is_comment_token(DWORD token) {
931 return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
934 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
935 /** operand output */
936 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
938 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
939 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
940 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
941 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
945 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
946 static const char swizzle_reg_chars_color_fix[] = "zyxw";
947 static const char swizzle_reg_chars[] = "xyzw";
948 const char* swizzle_regs = NULL;
952 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
953 DWORD swizzle_x = swizzle & 0x03;
954 DWORD swizzle_y = (swizzle >> 2) & 0x03;
955 DWORD swizzle_z = (swizzle >> 4) & 0x03;
956 DWORD swizzle_w = (swizzle >> 6) & 0x03;
959 swizzle_regs = swizzle_reg_chars_color_fix;
961 swizzle_regs = swizzle_reg_chars;
965 * swizzle bits fields:
968 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
970 sprintf(tmpReg, ".%c%c%c%c",
971 swizzle_regs[swizzle_x],
972 swizzle_regs[swizzle_y],
973 swizzle_regs[swizzle_z],
974 swizzle_regs[swizzle_w]);
975 strcat(hwLine, tmpReg);
979 if (swizzle_x == swizzle_y &&
980 swizzle_x == swizzle_z &&
981 swizzle_x == swizzle_w)
983 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
984 strcat(hwLine, tmpReg);
986 sprintf(tmpReg, ".%c%c%c%c",
987 swizzle_regs[swizzle_x],
988 swizzle_regs[swizzle_y],
989 swizzle_regs[swizzle_z],
990 swizzle_regs[swizzle_w]);
991 strcat(hwLine, tmpReg);
995 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
996 /* oPos, oFog and oPts in D3D */
997 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
999 DWORD reg = param & 0x00001FFF;
1000 DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1002 BOOL is_color = FALSE;
1004 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
1005 strcat(hwLine, " -");
1007 strcat(hwLine, " ");
1012 sprintf(tmpReg, "T%lu", reg);
1013 strcat(hwLine, tmpReg);
1016 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
1017 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
1020 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
1021 if (This->namedArrays) {
1022 sprintf(tmpReg, "namedVertex%lu", reg);
1024 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
1025 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
1027 strcat(hwLine, tmpReg);
1030 /* FIXME: some constants are named so we need a constants map*/
1031 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
1032 if (param & D3DVS_ADDRMODE_RELATIVE) {
1033 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
1035 sprintf(tmpReg, "const%lu", reg);
1037 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
1039 strcat(hwLine, tmpReg);
1041 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
1042 sprintf(tmpReg, "A%lu", reg);
1043 strcat(hwLine, tmpReg);
1045 case D3DSPR_RASTOUT:
1046 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
1047 strcat(hwLine, tmpReg);
1049 case D3DSPR_ATTROUT:
1051 strcat(hwLine, "result.color.primary");
1053 strcat(hwLine, "result.color.secondary");
1056 case D3DSPR_TEXCRDOUT:
1057 sprintf(tmpReg, "result.texcoord[%lu]", reg);
1058 strcat(hwLine, tmpReg);
1061 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
1066 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
1068 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
1072 DWORD MacroExpansion[4*4];
1074 int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) {
1077 int nComponents = 0;
1079 switch(macro_opcode) {
1082 opcode = D3DSIO_DP4;
1086 opcode = D3DSIO_DP4;
1090 opcode = D3DSIO_DP3;
1094 opcode = D3DSIO_DP3;
1098 opcode = D3DSIO_DP3;
1103 for (i = 0; i < nComponents; i++) {
1104 MacroExpansion[i*4+0] = opcode;
1105 MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1106 MacroExpansion[i*4+2] = *(args+1);
1107 MacroExpansion[i*4+3] = (*(args+2))+i;
1112 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
1114 switch(usage & 0xFFFF) {
1115 case D3DDECLUSAGE_POSITION:
1116 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1117 TRACE("Setting position to %d\n", arrayNo);
1118 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
1119 This->namedArrays = TRUE;
1121 /* TODO: position indexes go from 0-8!!*/
1122 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1123 /* robots uses positions up to 8, the position arrays are just packed.*/
1124 if ((usage & 0xF0000) >> 16 > 1) {
1125 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
1127 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
1128 This->declaredArrays = TRUE;
1131 case D3DDECLUSAGE_BLENDINDICES:
1132 /* not supported by openGL */
1133 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
1134 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
1135 This->declaredArrays = TRUE;
1136 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
1138 case D3DDECLUSAGE_BLENDWEIGHT:
1139 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
1140 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
1141 This->namedArrays = TRUE;
1142 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
1144 case D3DDECLUSAGE_NORMAL:
1145 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1146 TRACE("Setting normal to %d\n", arrayNo);
1147 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
1148 This->namedArrays = TRUE;
1150 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1151 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
1152 This->declaredArrays = TRUE;
1155 case D3DDECLUSAGE_PSIZE:
1156 TRACE("Setting PSIZE to %d\n", arrayNo);
1157 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
1158 This->namedArrays = TRUE;
1159 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
1161 case D3DDECLUSAGE_COLOR:
1162 if((usage & 0xF0000) >> 16 == 0) {
1163 TRACE("Setting DIFFUSE to %d\n", arrayNo);
1164 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
1165 This->namedArrays = TRUE;
1167 TRACE("Setting SPECULAR to %d\n", arrayNo);
1168 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
1169 This->namedArrays = TRUE;
1172 case D3DDECLUSAGE_TEXCOORD:
1173 This->namedArrays = TRUE;
1174 /* only 7 texture coords have been designed for, so run a quick sanity check */
1175 if ((usage & 0xF0000) >> 16 > 7) {
1176 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
1178 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
1179 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
1182 /* The following aren't supported by openGL,
1183 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
1184 this should be caught in the first pass */
1185 case D3DDECLUSAGE_TANGENT:
1186 TRACE("Setting TANGENT to %d\n", arrayNo);
1187 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
1188 This->declaredArrays = TRUE;
1190 case D3DDECLUSAGE_BINORMAL:
1191 TRACE("Setting BINORMAL to %d\n", arrayNo);
1192 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
1193 This->declaredArrays = TRUE;
1195 case D3DDECLUSAGE_TESSFACTOR:
1196 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
1197 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
1198 This->declaredArrays = TRUE;
1200 case D3DDECLUSAGE_POSITIONT:
1201 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
1202 FIXME("Setting positiont to %d\n", arrayNo);
1203 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
1204 This->namedArrays = TRUE;
1206 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
1207 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
1208 This->declaredArrays = TRUE;
1209 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
1212 case D3DDECLUSAGE_FOG:
1213 /* supported by OpenGL */
1214 TRACE("Setting FOG to %d\n", arrayNo);
1215 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
1216 This->namedArrays = TRUE;
1218 case D3DDECLUSAGE_DEPTH:
1219 TRACE("Setting DEPTH to %d\n", arrayNo);
1220 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
1221 This->declaredArrays = TRUE;
1223 case D3DDECLUSAGE_SAMPLE:
1224 TRACE("Setting SAMPLE to %d\n", arrayNo);
1225 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
1226 This->declaredArrays = TRUE;
1229 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
1234 * Function parser ...
1237 inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
1238 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1239 const DWORD* pToken = pFunction;
1240 const DWORD* pSavedToken = NULL;
1241 const SHADER_OPCODE* curOpcode = NULL;
1244 unsigned lineNum = 0;
1245 char *pgmStr = NULL;
1247 DWORD nUseAddressRegister = 0;
1248 DWORD nUseTempRegister = 0;
1252 #if 0 /* TODO: loope register (just another address register ) */
1253 BOOL hasLoops = FALSE;
1256 #define PGMSIZE 65535
1257 /* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
1260 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1261 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1262 if (This->device->fixupVertexBufferSize < PGMSIZE) {
1263 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1264 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
1265 This->fixupVertexBufferSize = PGMSIZE;
1266 This->fixupVertexBuffer[0] = 0;
1268 pgmStr = This->device->fixupVertexBuffer;
1270 #define PNSTRCAT(_pgmStr, _tmpLine) { \
1271 int _tmpLineLen = strlen(_tmpLine); \
1272 if(_tmpLineLen + pgmLength > PGMSIZE) { \
1273 ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
1275 memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
1277 pgmLength += _tmpLineLen; \
1280 pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
1281 /* Initialise the shader */
1282 This->namedArrays = FALSE;
1283 This->declaredArrays = FALSE;
1284 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
1285 This->arrayUsageMap[i] = -1;
1287 /* set all the tmpsUsed to not used */
1288 memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
1290 /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
1291 This->highestConstant = -1;
1294 * First pass to determine what we need to declare:
1295 * - Temporary variables
1296 * - Address variables
1298 if (NULL != pToken) {
1299 while (D3DVS_END() != *pToken) {
1300 if (vshader_is_version_token(*pToken)) {
1305 if (vshader_is_comment_token(*pToken)) { /** comment */
1306 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1308 pToken += comment_len;
1311 curOpcode = vshader_program_get_opcode(This, *pToken);
1316 if (NULL == curOpcode) {
1317 while (*pToken & 0x80000000) {
1318 FIXME("unrecognized opcode: %08lx\n", *pToken);
1319 /* skip unrecognized opcode */
1323 if (curOpcode->opcode == D3DSIO_DCL){
1324 INT usage = *pToken++;
1325 INT arrayNo = (*pToken++ & 0x00001FFF);
1326 parse_decl_usage(This, usage, arrayNo);
1327 } else if(curOpcode->opcode == D3DSIO_DEF) {
1328 This->constantsUsedBitmap[*pToken & 0xFF] = VS_CONSTANT_CONSTANT;
1329 FIXME("Constant %ld\n", *pToken & 0xFF);
1337 /* Check to see if and tmp or addressing redisters are used */
1338 if (curOpcode->num_params > 0) {
1339 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1340 reg = ((*pToken) & 0x00001FFF);
1341 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1342 if (D3DSPR_TEMP == regtype){
1343 tmpsUsed[reg] = TRUE;
1344 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1347 for (i = 1; i < curOpcode->num_params; ++i) {
1348 regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT));
1349 reg = ((*pToken) & 0x00001FFF);
1350 if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
1351 if (D3DSPR_TEMP == regtype){
1352 tmpsUsed[reg] = TRUE;
1353 if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
1359 #if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
1360 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1361 FIXME("This shader requires gl shader language support\n");
1363 This->shaderLanguage = GLSHADER_GLSL;
1371 #define VSHADER_ALWAYS_NUMBERED
1374 #ifdef VSHADER_ALWAYS_NUMBERED /* handy for debugging using numbered arrays instead of named arrays */
1375 /* TODO: using numbered arrays for software shaders makes things easier */
1376 This->declaredArrays = TRUE;
1379 /* named arrays and declared arrays are mutually exclusive */
1380 if (This->declaredArrays) {
1381 This->namedArrays = FALSE;
1384 nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
1385 nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
1388 /** second pass, now generate */
1391 if (NULL != pToken) {
1394 if ((nRemInstr >= 0) && (--nRemInstr == -1))
1395 /* Macro is finished, continue normal path */
1396 pToken = pSavedToken;
1397 if (D3DVS_END() == *pToken)
1400 if (vshader_is_version_token(*pToken)) { /** version */
1401 /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
1402 int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
1406 TRACE("found version token vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
1408 /* Each release of vertex shaders has had different numbers of temp registers */
1411 case 11: numTemps=12;
1412 numConstants=96;/* min(GL_LIMITS(constants),96) */
1413 strcpy(tmpLine, "!!ARBvp1.0\n");
1414 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1416 /* FIXME: if there are no calls or loops then use ARBvp1 otherwise use GLSL instead
1417 TODO: see if there are any operations in vs2/3 that aren't supported by ARBvp
1418 TODO: only map the maximum possible number of constants supported by openGL and not the maximum required by d3d (even better only map the used constants)*/
1419 case 20: numTemps=12; /* min(GL_LIMITS(temps),12) */
1420 numConstants=96; /* min(GL_LIMITS(constants),256) */
1421 strcpy(tmpLine, "!!ARBvp1.0\n");
1422 FIXME("No work done yet to support vs2.0 in hw\n");
1423 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1425 case 21: numTemps=12; /* min(GL_LIMITS(temps),12) */
1426 numConstants=96; /* min(GL_LIMITS(constants),256) */
1427 strcpy(tmpLine, "!!ARBvp1.0\n");
1428 FIXME("No work done yet to support vs2.1 in hw\n");
1429 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1431 case 30: numTemps=32; /* min(GL_LIMITS(temps),32) */
1432 numConstants=96;/* min(GL_LIMITS(constants),256) */
1433 strcpy(tmpLine, "!!ARBvp3.0\n");
1434 FIXME("No work done yet to support vs3.0 in hw\n");
1435 TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1438 numTemps=12;/* min(GL_LIMITS(temps),12) */
1439 numConstants=96;/* min(GL_LIMITS(constants),96) */
1440 strcpy(tmpLine, "!!ARBvp1.0\n");
1441 FIXME("Unrecognized vertex shader version %d!\n", version);
1443 PNSTRCAT(pgmStr, tmpLine);
1447 /* This should be a bitmap so that only temp registers that are used are declared. */
1448 for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
1449 if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
1450 sprintf(tmpLine, "TEMP T%ld;\n", i);
1452 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1453 PNSTRCAT(pgmStr, tmpLine);
1457 /* TODO: loop register counts as an address register */
1458 for (i = 0; i < nUseAddressRegister; i++) {
1459 sprintf(tmpLine, "ADDRESS A%ld;\n", i);
1461 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1462 PNSTRCAT(pgmStr, tmpLine);
1465 /* Due to the dynamic constants binding mechanism, we need to declare
1466 * all the constants for relative addressing. */
1467 /* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
1468 if (GL_VEND(MESA) || GL_VEND(WINE)) {
1471 /* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
1472 Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
1474 sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
1475 TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1476 PNSTRCAT(pgmStr, tmpLine);
1483 if (vshader_is_comment_token(*pToken)) { /** comment */
1484 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1486 TRACE("#%s\n", (char*)pToken);
1487 pToken += comment_len;
1491 curOpcode = vshader_program_get_opcode(This, *pToken);
1493 if (NULL == curOpcode) {
1494 /* unknown current opcode ... (shouldn't be any!) */
1495 while (*pToken & 0x80000000) {
1496 FIXME("unrecognized opcode: %08lx\n", *pToken);
1499 } else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
1500 /* if the token isn't supported by this cross compiler then skip it and its parameters */
1502 FIXME("Token %s requires greater functionality than Vertex_Progarm_ARB supports\n", curOpcode->name);
1503 pToken += curOpcode->num_params;
1505 } else if (D3DSIO_DEF == curOpcode->opcode) {
1507 /* Handle definitions here, they don't fit well with the
1508 * other instructions below [for now ] */
1511 sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
1512 sprintf(tmpChar,"%f ,", *(float *) (pToken + 1));
1513 strcat(tmpLine, tmpChar);
1514 sprintf(tmpChar,"%f ,", *(float *) (pToken + 2));
1515 strcat(tmpLine, tmpChar);
1516 sprintf(tmpChar,"%f ,", *(float *) (pToken + 3));
1517 strcat(tmpLine, tmpChar);
1518 sprintf(tmpChar,"%f}", *(float *) (pToken + 4));
1519 strcat(tmpLine, tmpChar);
1521 strcat(tmpLine,";\n");
1523 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1524 PNSTRCAT(pgmStr, tmpLine);
1529 } else if (D3DSIO_DCL == curOpcode->opcode) {
1531 /* Handle declarations here, they don't fit well with the
1532 * other instructions below [for now ] */
1534 if (This->namedArrays) {
1535 const char* attribName = "undefined";
1536 switch(*pToken & 0xFFFF) {
1537 case D3DDECLUSAGE_POSITION:
1538 attribName = "vertex.position";
1540 case D3DDECLUSAGE_BLENDINDICES:
1541 /* not supported by openGL */
1542 attribName = "vertex.blend";
1544 case D3DDECLUSAGE_BLENDWEIGHT:
1545 attribName = "vertex.weight";
1547 case D3DDECLUSAGE_NORMAL:
1548 attribName = "vertex.normal";
1550 case D3DDECLUSAGE_PSIZE:
1551 attribName = "vertex.psize";
1553 case D3DDECLUSAGE_COLOR:
1554 if((*pToken & 0xF0000) >> 16 == 0) {
1555 attribName = "vertex.color";
1557 attribName = "vertex.color.secondary";
1560 case D3DDECLUSAGE_TEXCOORD:
1564 sprintf(tmpChar,"vertex.texcoord[%lu]",(*pToken & 0xF0000) >> 16);
1565 attribName = tmpChar;
1568 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
1569 case D3DDECLUSAGE_TANGENT:
1570 attribName = "vertex.tangent";
1572 case D3DDECLUSAGE_BINORMAL:
1573 attribName = "vertex.binormal";
1575 case D3DDECLUSAGE_TESSFACTOR:
1576 attribName = "vertex.tessfactor";
1578 case D3DDECLUSAGE_POSITIONT:
1579 attribName = "vertex.possitionT";
1581 case D3DDECLUSAGE_FOG:
1582 attribName = "vertex.fogcoord";
1584 case D3DDECLUSAGE_DEPTH:
1585 attribName = "vertex.depth";
1587 case D3DDECLUSAGE_SAMPLE:
1588 attribName = "vertex.sample";
1591 FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
1596 sprintf(tmpLine, "ATTRIB ");
1597 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1599 sprintf(tmpChar," = %s", attribName);
1600 strcat(tmpLine, tmpChar);
1601 strcat(tmpLine,";\n");
1603 if (This->namedArrays) {
1604 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1605 PNSTRCAT(pgmStr, tmpLine);
1608 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
1612 /* eat the token so it doesn't generate a warning */
1620 /* Common Processing: ([instr] [dst] [src]*) */
1622 switch (curOpcode->opcode) {
1626 /* Address registers must be loaded with the ARL instruction */
1627 if ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) == D3DSPR_ADDR) {
1628 if (((*pToken) & 0x00001FFF) < nUseAddressRegister) {
1629 strcpy(tmpLine, "ARL");
1632 FIXME("(%p) Try to load A%ld an undeclared address register!\n", This, ((*pToken) & 0x00001FFF));
1654 strcpy(tmpLine, curOpcode->glname);
1661 /* Expand the macro and get nusprintf(tmpLine,mber of generated instruction */
1662 nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken);
1663 /* Save point to next instruction */
1664 pSavedToken = pToken + 3;
1665 /* Execute expanded macro */
1666 pToken = MacroExpansion;
1670 if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
1671 FIXME("Opcode %s requires Gl Shader languange 1.0\n", curOpcode->name);
1673 FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
1676 if (curOpcode->num_params > 0) {
1677 vshader_program_add_param(This, *pToken, FALSE, tmpLine);
1680 for (i = 1; i < curOpcode->num_params; ++i) {
1681 strcat(tmpLine, ",");
1682 vshader_program_add_param(This, *pToken, TRUE, tmpLine);
1686 strcat(tmpLine,";\n");
1688 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1689 PNSTRCAT(pgmStr, tmpLine);
1693 strcpy(tmpLine, "END\n");
1695 TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
1696 PNSTRCAT(pgmStr, tmpLine);
1699 /* finally null terminate the pgmStr*/
1700 pgmStr[pgmLength] = 0;
1702 /* Check that Vertex Shaders are supported */
1703 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1704 /* Create the hw shader */
1705 /* TODO: change to resource.glObjectHandel or something like that */
1706 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1707 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1708 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1710 /* Create the program and check for errors */
1711 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
1712 if (glGetError() == GL_INVALID_OPERATION) {
1714 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1715 FIXME("HW VertexShader Error at position %d: %s\n",
1716 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1717 This->baseShader.prgId = -1;
1720 #if 1 /* if were using the data buffer of device then we don't need to free it */
1721 HeapFree(GetProcessHeap(), 0, pgmStr);
1726 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1728 * TODO: use the NV_vertex_program (or 1_1) extension
1729 * and specifics vendors (ARB_vertex_program??) variants for it
1734 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1735 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1737 /** Vertex Shader Temporary Registers */
1738 WINED3DSHADERVECTOR R[12];
1739 /*D3DSHADERSCALAR A0;*/
1740 WINED3DSHADERVECTOR A[1];
1741 /** temporary Vector for modifier management */
1742 WINED3DSHADERVECTOR d;
1743 WINED3DSHADERVECTOR s[3];
1745 const DWORD* pToken = This->baseShader.function;
1746 const SHADER_OPCODE* curOpcode = NULL;
1747 /** functions parameters */
1748 WINED3DSHADERVECTOR* p[4];
1749 WINED3DSHADERVECTOR* p_send[4];
1752 /** init temporary register */
1753 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1755 /* vshader_program_parse(vshader); */
1756 #if 0 /* Must not be 1 in cvs */
1758 TRACE_VSVECTOR(This->data->C[0]);
1759 TRACE_VSVECTOR(This->data->C[1]);
1760 TRACE_VSVECTOR(This->data->C[2]);
1761 TRACE_VSVECTOR(This->data->C[3]);
1762 TRACE_VSVECTOR(This->data->C[4]);
1763 TRACE_VSVECTOR(This->data->C[5]);
1764 TRACE_VSVECTOR(This->data->C[6]);
1765 TRACE_VSVECTOR(This->data->C[7]);
1766 TRACE_VSVECTOR(This->data->C[8]);
1767 TRACE_VSVECTOR(This->data->C[64]);
1768 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1769 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1770 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1771 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1772 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1773 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1774 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1775 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1776 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1779 TRACE_VSVECTOR(vshader->data->C[64]);
1780 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1782 /* the first dword is the version tag */
1783 /* TODO: parse it */
1785 if (vshader_is_version_token(*pToken)) { /** version */
1788 while (D3DVS_END() != *pToken) {
1789 if (vshader_is_comment_token(*pToken)) { /** comment */
1790 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1792 pToken += comment_len;
1795 curOpcode = vshader_program_get_opcode(This, *pToken);
1797 if (NULL == curOpcode) {
1799 /* unknown current opcode ... */
1800 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1801 while (*pToken & 0x80000000) {
1803 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1805 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1806 vshader_program_dump_param(*pToken, i);
1813 if (curOpcode->num_params > 0) {
1814 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1815 for (i = 0; i < curOpcode->num_params; ++i) {
1816 DWORD reg = pToken[i] & 0x00001FFF;
1817 DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
1819 switch (regtype << D3DSP_REGTYPE_SHIFT) {
1821 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1825 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1826 p[i] = &input->V[reg];
1829 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1830 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1832 p[i] = &This->data->C[reg];
1835 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1837 ERR("cannot handle address registers != a0, forcing use of a0\n");
1840 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1843 case D3DSPR_RASTOUT:
1845 case D3DSRO_POSITION:
1846 p[i] = &output->oPos;
1849 p[i] = &output->oFog;
1851 case D3DSRO_POINT_SIZE:
1852 p[i] = &output->oPts;
1856 case D3DSPR_ATTROUT:
1857 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1858 p[i] = &output->oD[reg];
1860 case D3DSPR_TEXCRDOUT:
1861 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1862 p[i] = &output->oT[reg];
1864 /* TODO Decls and defs */
1873 if (i > 0) { /* input reg */
1874 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1875 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1877 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1878 /* TRACE("p[%d] not swizzled\n", i); */
1881 DWORD swizzle_x = swizzle & 0x03;
1882 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1883 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1884 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1885 /* TRACE("p[%d] swizzled\n", i); */
1886 float* tt = (float*) p[i];
1887 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1888 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1889 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1890 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1893 } else { /* output reg */
1894 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1897 p_send[i] = &d; /* to be post-processed for modifiers management */
1903 switch (curOpcode->num_params) {
1905 curOpcode->soft_fct();
1908 curOpcode->soft_fct(p_send[0]);
1911 curOpcode->soft_fct(p_send[0], p_send[1]);
1914 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1917 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1920 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1923 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1926 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1929 /* check if output reg modifier post-process */
1930 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1931 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1932 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1933 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1934 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1937 TRACE_VSVECTOR(output->oPos);
1938 TRACE_VSVECTOR(output->oD[0]);
1939 TRACE_VSVECTOR(output->oD[1]);
1940 TRACE_VSVECTOR(output->oT[0]);
1941 TRACE_VSVECTOR(output->oT[1]);
1942 TRACE_VSVECTOR(R[0]);
1943 TRACE_VSVECTOR(R[1]);
1944 TRACE_VSVECTOR(R[2]);
1945 TRACE_VSVECTOR(R[3]);
1946 TRACE_VSVECTOR(R[4]);
1947 TRACE_VSVECTOR(R[5]);
1950 /* to next opcode token */
1951 pToken += curOpcode->num_params;
1954 TRACE("End of current instruction:\n");
1955 TRACE_VSVECTOR(output->oPos);
1956 TRACE_VSVECTOR(output->oD[0]);
1957 TRACE_VSVECTOR(output->oD[1]);
1958 TRACE_VSVECTOR(output->oT[0]);
1959 TRACE_VSVECTOR(output->oT[1]);
1960 TRACE_VSVECTOR(R[0]);
1961 TRACE_VSVECTOR(R[1]);
1962 TRACE_VSVECTOR(R[2]);
1963 TRACE_VSVECTOR(R[3]);
1964 TRACE_VSVECTOR(R[4]);
1965 TRACE_VSVECTOR(R[5]);
1968 #if 0 /* Must not be 1 in cvs */
1970 TRACE_VSVECTOR(output->oPos);
1971 TRACE_VSVECTOR(output->oD[0]);
1972 TRACE_VSVECTOR(output->oD[1]);
1973 TRACE_VSVECTOR(output->oT[0]);
1974 TRACE_VSVECTOR(output->oT[1]);
1979 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1980 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1981 FIXME("(%p) : stub\n", This);
1985 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1986 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1987 FIXME("(%p) : stub\n", This);
1991 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1992 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1993 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1994 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1995 return WINED3DERR_INVALIDCALL;
1997 if (NULL == pConstantData) {
1998 return WINED3DERR_INVALIDCALL;
2000 FIXME("(%p) : stub\n", This);
2004 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
2005 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2006 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
2007 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2008 return WINED3DERR_INVALIDCALL;
2010 if (NULL == pConstantData) {
2011 return WINED3DERR_INVALIDCALL;
2013 FIXME("(%p) : stub\n", This);
2017 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
2018 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2019 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
2020 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
2021 return WINED3DERR_INVALIDCALL;
2023 if (NULL == pConstantData) {
2024 return WINED3DERR_INVALIDCALL;
2026 FIXME("(%p) : stub\n", This);
2030 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
2031 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
2032 FIXME("(%p) : stub\n", This);
2038 /* *******************************************
2039 IWineD3DVertexShader IUnknown parts follow
2040 ******************************************* */
2041 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
2043 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2044 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
2045 if (IsEqualGUID(riid, &IID_IUnknown)
2046 || IsEqualGUID(riid, &IID_IWineD3DBase)
2047 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
2048 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
2049 IUnknown_AddRef(iface);
2053 return E_NOINTERFACE;
2056 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
2057 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2058 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2059 return InterlockedIncrement(&This->ref);
2062 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
2063 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2065 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2066 ref = InterlockedDecrement(&This->ref);
2068 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
2069 HeapFree(GetProcessHeap(), 0, This);
2074 /* *******************************************
2075 IWineD3DVertexShader IWineD3DVertexShader parts follow
2076 ******************************************* */
2078 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
2079 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2081 *parent = This->parent;
2082 IUnknown_AddRef(*parent);
2083 TRACE("(%p) : returning %p\n", This, *parent);
2087 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
2088 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
2089 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
2090 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
2091 TRACE("(%p) returning %p\n", This, *pDevice);
2095 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
2096 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
2097 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
2099 if (NULL == pData) {
2100 *pSizeOfData = This->baseShader.functionLength;
2103 if (*pSizeOfData < This->baseShader.functionLength) {
2104 *pSizeOfData = This->baseShader.functionLength;
2105 return WINED3DERR_MOREDATA;
2107 if (NULL == This->baseShader.function) { /* no function defined */
2108 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
2109 (*(DWORD **) pData) = NULL;
2111 if(This->baseShader.functionLength == 0){
2114 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
2115 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
2120 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
2121 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
2122 const DWORD* pToken = pFunction;
2123 const SHADER_OPCODE* curOpcode = NULL;
2126 TRACE("(%p) : Parsing programme\n", This);
2128 if (NULL != pToken) {
2129 while (D3DVS_END() != *pToken) {
2130 if (vshader_is_version_token(*pToken)) { /** version */
2131 TRACE("vs_%lu_%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
2136 if (vshader_is_comment_token(*pToken)) { /** comment */
2137 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
2139 TRACE("//%s\n", (char*)pToken);
2140 pToken += comment_len;
2141 len += comment_len + 1;
2144 curOpcode = vshader_program_get_opcode(This, *pToken);
2147 if (NULL == curOpcode) {
2148 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
2149 while (*pToken & 0x80000000) {
2150 /* unknown current opcode ... */
2151 FIXME("unrecognized opcode: %08lx", *pToken);
2158 if (curOpcode->opcode == D3DSIO_DCL) {
2159 vshader_program_dump_decl_usage(This, *pToken);
2162 vshader_program_dump_vs_param(*pToken, 0);
2166 if (curOpcode->opcode == D3DSIO_DEF) {
2167 TRACE("def c%lu = ", *pToken & 0xFF);
2170 TRACE("%f ,", *(float *)pToken);
2173 TRACE("%f ,", *(float *)pToken);
2176 TRACE("%f ,", *(float *)pToken);
2179 TRACE("%f", *(float *)pToken);
2183 TRACE("%s ", curOpcode->name);
2184 if (curOpcode->num_params > 0) {
2185 vshader_program_dump_vs_param(*pToken, 0);
2188 for (i = 1; i < curOpcode->num_params; ++i) {
2190 vshader_program_dump_vs_param(*pToken, 1);
2199 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
2201 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
2204 /* Generate HW shader in needed */
2205 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
2207 IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
2211 /* copy the function ... because it will certainly be released by application */
2212 if (NULL != pFunction) {
2213 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
2214 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
2216 This->baseShader.function = NULL;
2221 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
2223 /*** IUnknown methods ***/
2224 IWineD3DVertexShaderImpl_QueryInterface,
2225 IWineD3DVertexShaderImpl_AddRef,
2226 IWineD3DVertexShaderImpl_Release,
2227 /*** IWineD3DBase methods ***/
2228 IWineD3DVertexShaderImpl_GetParent,
2229 /*** IWineD3DBaseShader methods ***/
2230 IWineD3DVertexShaderImpl_SetFunction,
2231 /*** IWineD3DVertexShader methods ***/
2232 IWineD3DVertexShaderImpl_GetDevice,
2233 IWineD3DVertexShaderImpl_GetFunction