wined3d: Implement IWineD3DDevice::SetFrontBackBuffers.
[wine/multimedia.git] / dlls / wined3d / vertexshader.c
blob13bc9817ddb6eef292892d05ab87029995a78c4f
1 /*
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
23 #include "config.h"
25 #include <math.h>
26 #include <stdio.h>
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
35 vertex shaders */
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)
39 #else
40 # define VSTRACE(A)
41 # define TRACE_VSVECTOR(name)
42 #endif
44 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
46 /**
47 * DirectX9 SDK download
48 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
50 * Exploring D3DX
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
56 * Dx9 New
57 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
59 * Dx9 Shaders
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
65 * Dx9 D3DX
66 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
68 * FVF
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) {
88 d->x = s0->x + s1->x;
89 d->y = s0->y + s1->y;
90 d->z = s0->z + s1->z;
91 d->w = s0->w + s1->w;
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) {
109 d->x = 1.0f;
110 d->y = s0->y * s1->y;
111 d->z = s0->z;
112 d->w = s1->w;
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) {
118 union {
119 float f;
120 DWORD d;
121 } tmp;
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;
128 d->z = tmp.f;
129 d->w = 1.0f;
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) {
135 d->x = 1.0f;
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;
138 d->w = 1.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) {
178 d->x = s0->x;
179 d->y = s0->y;
180 d->z = s0->z;
181 d->w = s0->w;
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);
260 d->z = 0.0f;
261 d->w = 1.0f;
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;
297 d->w = 1.0f;
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;
319 d->w = 1.0f;
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) {
327 FIXME("check\n");
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;
330 d->z = 0.0f;
331 d->w = 1.0f;
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) {
356 d->x = fabsf(s0->x);
357 d->y = fabsf(s0->y);
358 d->z = fabsf(s0->z);
359 d->w = fabsf(s0->w);
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));
364 /* Stubs */
366 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
367 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
368 FIXME(" : Stub\n");
371 void vshader_call(WINED3DSHADERVECTOR* d) {
372 FIXME(" : Stub\n");
375 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
376 FIXME(" : Stub\n");
379 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
380 FIXME(" : Stub\n");
383 void vshader_ret(void) {
384 FIXME(" : Stub\n");
387 void vshader_endloop(void) {
388 FIXME(" : Stub\n");
391 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
392 FIXME(" : Stub\n");
395 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
396 FIXME(" : Stub\n");
399 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
400 FIXME(" : Stub\n");
403 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
404 FIXME(" : Stub\n");
407 void vshader_sincos(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
408 FIXME(" : Stub\n");
411 void vshader_rep(WINED3DSHADERVECTOR* d) {
412 FIXME(" : Stub\n");
415 void vshader_endrep(void) {
416 FIXME(" : Stub\n");
419 void vshader_if(WINED3DSHADERVECTOR* d) {
420 FIXME(" : Stub\n");
423 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
424 FIXME(" : Stub\n");
427 void vshader_else(void) {
428 FIXME(" : Stub\n");
431 void vshader_label(WINED3DSHADERVECTOR* d) {
432 FIXME(" : Stub\n");
435 void vshader_endif(void) {
436 FIXME(" : Stub\n");
439 void vshader_break(void) {
440 FIXME(" : Stub\n");
443 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
444 FIXME(" : Stub\n");
447 void vshader_breakp(WINED3DSHADERVECTOR* d) {
448 FIXME(" : Stub\n");
451 void vshader_mova(WINED3DSHADERVECTOR* d) {
452 FIXME(" : Stub\n");
455 void vshader_defb(WINED3DSHADERVECTOR* d) {
456 FIXME(" : Stub\n");
459 void vshader_defi(WINED3DSHADERVECTOR* d) {
460 FIXME(" : Stub\n");
463 void vshader_texldd(WINED3DSHADERVECTOR* d) {
464 FIXME(" : Stub\n");
467 void vshader_setp(WINED3DSHADERVECTOR* d) {
468 FIXME(" : Stub\n");
471 void vshader_texldl(WINED3DSHADERVECTOR* d) {
472 FIXME(" : Stub\n");
475 /* Prototype */
476 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
477 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
478 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
479 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
482 * log, exp, frc, m*x* seems to be macros ins ... to see
484 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
486 /* Arithmetic */
487 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, NULL, 0, 0},
488 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
489 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
490 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
491 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
492 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
511 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
512 /* TODO: sng can possibly be performed a s
513 RCP tmp, vec
514 MUL out, tmp, vec*/
515 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
516 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
517 DP3 tmp , vec, vec;
518 RSQ tmp, tmp.x;
519 MUL vec.xyz, vec, tmp;
520 but I think this is better because it accounts for w properly.
521 DP3 tmp , vec, vec;
522 RSQ tmp, tmp.x;
523 MUL vec, vec, tmp;
526 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, NULL, 0, 0},
527 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos, NULL, NULL, 0, 0},
529 /* Matrix */
530 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
531 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
532 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
533 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
534 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
536 /* Declare registers */
537 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
539 /* Constant definitions */
540 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
541 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
542 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 2, vshader_defi, NULL, NULL, 0, 0},
544 /* Flow control - requires GLSL or software shaders */
545 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
546 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
547 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
548 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
549 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
550 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
551 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
552 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
553 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
554 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
555 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
556 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
557 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
558 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
559 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
561 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
562 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 2, vshader_setp, NULL, NULL, 0, 0},
563 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
564 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
567 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
568 /** operand output */
569 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
570 strcat(hwLine, ".");
571 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
572 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
573 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
574 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
578 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
579 static const char swizzle_reg_chars_color_fix[] = "zyxw";
580 static const char swizzle_reg_chars[] = "xyzw";
581 const char* swizzle_regs = NULL;
582 char tmpReg[255];
584 /** operand input */
585 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
586 DWORD swizzle_x = swizzle & 0x03;
587 DWORD swizzle_y = (swizzle >> 2) & 0x03;
588 DWORD swizzle_z = (swizzle >> 4) & 0x03;
589 DWORD swizzle_w = (swizzle >> 6) & 0x03;
591 if (is_color) {
592 swizzle_regs = swizzle_reg_chars_color_fix;
593 } else {
594 swizzle_regs = swizzle_reg_chars;
598 * swizzle bits fields:
599 * WWZZYYXX
601 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
602 if (is_color) {
603 sprintf(tmpReg, ".%c%c%c%c",
604 swizzle_regs[swizzle_x],
605 swizzle_regs[swizzle_y],
606 swizzle_regs[swizzle_z],
607 swizzle_regs[swizzle_w]);
608 strcat(hwLine, tmpReg);
610 return ;
612 if (swizzle_x == swizzle_y &&
613 swizzle_x == swizzle_z &&
614 swizzle_x == swizzle_w)
616 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
617 strcat(hwLine, tmpReg);
618 } else {
619 sprintf(tmpReg, ".%c%c%c%c",
620 swizzle_regs[swizzle_x],
621 swizzle_regs[swizzle_y],
622 swizzle_regs[swizzle_z],
623 swizzle_regs[swizzle_w]);
624 strcat(hwLine, tmpReg);
628 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
629 /* oPos, oFog and oPts in D3D */
630 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
632 DWORD reg = param & D3DSP_REGNUM_MASK;
633 DWORD regtype = shader_get_regtype(param);
634 char tmpReg[255];
635 BOOL is_color = FALSE;
637 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
638 strcat(hwLine, " -");
639 } else {
640 strcat(hwLine, " ");
643 switch (regtype) {
644 case D3DSPR_TEMP:
645 sprintf(tmpReg, "R%lu", reg);
646 strcat(hwLine, tmpReg);
647 break;
648 case D3DSPR_INPUT:
649 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
650 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
651 is_color = TRUE;
653 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
654 if (This->namedArrays) {
655 sprintf(tmpReg, "namedVertex%lu", reg);
656 } else {
657 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
658 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
660 strcat(hwLine, tmpReg);
661 break;
662 case D3DSPR_CONST:
663 /* FIXME: some constants are named so we need a constants map*/
664 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
665 if (param & D3DVS_ADDRMODE_RELATIVE) {
666 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
668 sprintf(tmpReg, "const%lu", reg);
669 } else {
670 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
672 strcat(hwLine, tmpReg);
673 break;
674 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
675 sprintf(tmpReg, "A%lu", reg);
676 strcat(hwLine, tmpReg);
677 break;
678 case D3DSPR_RASTOUT:
679 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
680 strcat(hwLine, tmpReg);
681 break;
682 case D3DSPR_ATTROUT:
683 if (reg==0) {
684 strcat(hwLine, "result.color.primary");
685 } else {
686 strcat(hwLine, "result.color.secondary");
688 break;
689 case D3DSPR_TEXCRDOUT:
690 sprintf(tmpReg, "result.texcoord[%lu]", reg);
691 strcat(hwLine, tmpReg);
692 break;
693 default:
694 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
695 break;
698 if (!is_input) {
699 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
700 } else {
701 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
705 static void parse_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
707 switch(usage & 0xFFFF) {
708 case D3DDECLUSAGE_POSITION:
709 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
710 TRACE("Setting position to %d\n", arrayNo);
711 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
712 This->namedArrays = TRUE;
713 } else {
714 /* TODO: position indexes go from 0-8!!*/
715 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
716 /* robots uses positions up to 8, the position arrays are just packed.*/
717 if ((usage & 0xF0000) >> 16 > 1) {
718 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
720 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
721 This->declaredArrays = TRUE;
723 break;
724 case D3DDECLUSAGE_BLENDINDICES:
725 /* not supported by openGL */
726 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
727 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
728 This->declaredArrays = TRUE;
729 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
730 break;
731 case D3DDECLUSAGE_BLENDWEIGHT:
732 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
733 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
734 This->namedArrays = TRUE;
735 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
736 break;
737 case D3DDECLUSAGE_NORMAL:
738 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
739 TRACE("Setting normal to %d\n", arrayNo);
740 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
741 This->namedArrays = TRUE;
742 } else {
743 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
744 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
745 This->declaredArrays = TRUE;
747 break;
748 case D3DDECLUSAGE_PSIZE:
749 TRACE("Setting PSIZE to %d\n", arrayNo);
750 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
751 This->namedArrays = TRUE;
752 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
753 break;
754 case D3DDECLUSAGE_COLOR:
755 if((usage & 0xF0000) >> 16 == 0) {
756 TRACE("Setting DIFFUSE to %d\n", arrayNo);
757 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
758 This->namedArrays = TRUE;
759 } else {
760 TRACE("Setting SPECULAR to %d\n", arrayNo);
761 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
762 This->namedArrays = TRUE;
764 break;
765 case D3DDECLUSAGE_TEXCOORD:
766 This->namedArrays = TRUE;
767 /* only 7 texture coords have been designed for, so run a quick sanity check */
768 if ((usage & 0xF0000) >> 16 > 7) {
769 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
770 } else {
771 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
772 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
774 break;
775 /* The following aren't supported by openGL,
776 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
777 this should be caught in the first pass */
778 case D3DDECLUSAGE_TANGENT:
779 TRACE("Setting TANGENT to %d\n", arrayNo);
780 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
781 This->declaredArrays = TRUE;
782 break;
783 case D3DDECLUSAGE_BINORMAL:
784 TRACE("Setting BINORMAL to %d\n", arrayNo);
785 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
786 This->declaredArrays = TRUE;
787 break;
788 case D3DDECLUSAGE_TESSFACTOR:
789 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
790 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
791 This->declaredArrays = TRUE;
792 break;
793 case D3DDECLUSAGE_POSITIONT:
794 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
795 FIXME("Setting positiont to %d\n", arrayNo);
796 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
797 This->namedArrays = TRUE;
798 } else {
799 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
800 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
801 This->declaredArrays = TRUE;
802 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
804 break;
805 case D3DDECLUSAGE_FOG:
806 /* supported by OpenGL */
807 TRACE("Setting FOG to %d\n", arrayNo);
808 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
809 This->namedArrays = TRUE;
810 break;
811 case D3DDECLUSAGE_DEPTH:
812 TRACE("Setting DEPTH to %d\n", arrayNo);
813 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
814 This->declaredArrays = TRUE;
815 break;
816 case D3DDECLUSAGE_SAMPLE:
817 TRACE("Setting SAMPLE to %d\n", arrayNo);
818 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
819 This->declaredArrays = TRUE;
820 break;
821 default:
822 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
826 void vshader_set_version(
827 IWineD3DVertexShaderImpl *This,
828 DWORD version) {
830 DWORD major = (version >> 8) & 0x0F;
831 DWORD minor = version & 0x0F;
833 This->baseShader.hex_version = version;
834 This->baseShader.version = major * 10 + minor;
835 TRACE("vs_%lu_%lu\n", major, minor);
837 This->baseShader.limits.texture = 0;
839 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
840 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
842 switch (This->baseShader.version) {
843 case 10:
844 case 11: This->baseShader.limits.temporary = 12;
845 This->baseShader.limits.constant_bool = 0;
846 This->baseShader.limits.constant_int = 0;
847 This->baseShader.limits.address = 1;
848 break;
850 case 20:
851 case 21: This->baseShader.limits.temporary = 12;
852 This->baseShader.limits.constant_bool = 16;
853 This->baseShader.limits.constant_int = 16;
854 This->baseShader.limits.address = 1;
855 break;
857 case 30: This->baseShader.limits.temporary = 32;
858 This->baseShader.limits.constant_bool = 32;
859 This->baseShader.limits.constant_int = 32;
860 This->baseShader.limits.address = 1;
861 break;
863 default: This->baseShader.limits.temporary = 12;
864 This->baseShader.limits.constant_bool = 0;
865 This->baseShader.limits.constant_int = 0;
866 This->baseShader.limits.address = 1;
867 FIXME("Unrecognized vertex shader version %lx!\n", version);
871 /* Map the opcode 1-to-1 to the GL code */
872 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
874 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
875 CONST SHADER_OPCODE* curOpcode = arg->opcode;
876 SHADER_BUFFER* buffer = arg->buffer;
877 DWORD dst = arg->dst;
878 DWORD* src = arg->src;
880 DWORD dst_regtype = shader_get_regtype(dst);
881 char tmpLine[256];
882 unsigned int i;
884 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
885 strcpy(tmpLine, "ARL");
886 else
887 strcpy(tmpLine, curOpcode->glname);
889 if (curOpcode->num_params > 0) {
890 vshader_program_add_param(This, dst, FALSE, tmpLine);
891 for (i = 1; i < curOpcode->num_params; ++i) {
892 strcat(tmpLine, ",");
893 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
896 shader_addline(buffer, "%s;\n", tmpLine);
899 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
901 DWORD dst = arg->dst;
902 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
903 char tmpLine[256];
904 SHADER_BUFFER* buffer = arg->buffer;
906 if (This->namedArrays) {
907 const char* attribName = "undefined";
908 switch(dst & 0xFFFF) {
909 case D3DDECLUSAGE_POSITION:
910 attribName = "vertex.position";
911 break;
912 case D3DDECLUSAGE_BLENDINDICES:
913 /* not supported by openGL */
914 attribName = "vertex.blend";
915 break;
916 case D3DDECLUSAGE_BLENDWEIGHT:
917 attribName = "vertex.weight";
918 break;
919 case D3DDECLUSAGE_NORMAL:
920 attribName = "vertex.normal";
921 break;
922 case D3DDECLUSAGE_PSIZE:
923 attribName = "vertex.psize";
924 break;
925 case D3DDECLUSAGE_COLOR:
926 if((dst & 0xF0000) >> 16 == 0) {
927 attribName = "vertex.color";
928 } else {
929 attribName = "vertex.color.secondary";
931 break;
932 case D3DDECLUSAGE_TEXCOORD:
934 char tmpChar[100];
935 tmpChar[0] = 0;
936 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
937 attribName = tmpChar;
938 break;
940 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
941 case D3DDECLUSAGE_TANGENT:
942 attribName = "vertex.tangent";
943 break;
944 case D3DDECLUSAGE_BINORMAL:
945 attribName = "vertex.binormal";
946 break;
947 case D3DDECLUSAGE_TESSFACTOR:
948 attribName = "vertex.tessfactor";
949 break;
950 case D3DDECLUSAGE_POSITIONT:
951 attribName = "vertex.possitionT";
952 break;
953 case D3DDECLUSAGE_FOG:
954 attribName = "vertex.fogcoord";
955 break;
956 case D3DDECLUSAGE_DEPTH:
957 attribName = "vertex.depth";
958 break;
959 case D3DDECLUSAGE_SAMPLE:
960 attribName = "vertex.sample";
961 break;
962 default:
963 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
966 sprintf(tmpLine, "ATTRIB ");
967 vshader_program_add_param(This, dst, FALSE, tmpLine);
968 if (This->namedArrays)
969 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
974 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
976 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
977 SHADER_BUFFER* buffer = arg->buffer;
978 DWORD reg = arg->dst;
980 shader_addline(buffer,
981 "PARAM const%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
982 *((const float *)(arg->src + 0)),
983 *((const float *)(arg->src + 1)),
984 *((const float *)(arg->src + 2)),
985 *((const float *)(arg->src + 3)) );
987 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
990 /** Handles transforming all D3DSIO_M?x? opcodes for
991 Vertex shaders to ARB_vertex_program codes */
992 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
994 int i;
995 int nComponents = 0;
996 SHADER_OPCODE_ARG tmpArg;
998 /* Set constants for the temporary argument */
999 tmpArg.shader = arg->shader;
1000 tmpArg.buffer = arg->buffer;
1001 tmpArg.src[0] = arg->src[0];
1003 switch(arg->opcode->opcode) {
1004 case D3DSIO_M4x4:
1005 nComponents = 4;
1006 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1007 break;
1008 case D3DSIO_M4x3:
1009 nComponents = 3;
1010 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1011 break;
1012 case D3DSIO_M3x4:
1013 nComponents = 4;
1014 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1015 break;
1016 case D3DSIO_M3x3:
1017 nComponents = 3;
1018 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1019 break;
1020 case D3DSIO_M3x2:
1021 nComponents = 2;
1022 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1023 break;
1024 default:
1025 break;
1028 for (i = 0; i < nComponents; i++) {
1029 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1030 tmpArg.src[1] = arg->src[1]+i;
1031 vshader_hw_map2gl(&tmpArg);
1035 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1036 or GLSL and send it to the card */
1037 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1038 IWineD3DVertexShader *iface,
1039 CONST DWORD *pFunction) {
1041 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1042 SHADER_BUFFER buffer;
1044 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1045 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1046 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1047 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1048 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1049 This->fixupVertexBufferSize = PGMSIZE;
1050 This->fixupVertexBuffer[0] = 0;
1052 buffer.buffer = This->device->fixupVertexBuffer;
1053 #else
1054 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1055 #endif
1056 buffer.bsize = 0;
1057 buffer.lineNo = 0;
1059 /* TODO: Optionally, generate the GLSL shader instead */
1060 if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1061 /* Create the hw ARB shader */
1062 shader_addline(&buffer, "!!ARBvp1.0\n");
1064 /* Mesa supports only 95 constants */
1065 if (GL_VEND(MESA) || GL_VEND(WINE))
1066 This->baseShader.limits.constant_float =
1067 min(95, This->baseShader.limits.constant_float);
1069 shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
1070 This->baseShader.limits.constant_float,
1071 This->baseShader.limits.constant_float - 1);
1073 /** Call the base shader generation routine to generate most
1074 of the vertex shader string for us */
1075 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1077 shader_addline(&buffer, "END\n\0");
1079 /* TODO: change to resource.glObjectHandle or something like that */
1080 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1082 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1083 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1085 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1086 /* Create the program and check for errors */
1087 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1088 buffer.bsize, buffer.buffer));
1090 if (glGetError() == GL_INVALID_OPERATION) {
1091 GLint errPos;
1092 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1093 FIXME("HW VertexShader Error at position %d: %s\n",
1094 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1095 This->baseShader.prgId = -1;
1099 #if 1 /* if were using the data buffer of device then we don't need to free it */
1100 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1101 #endif
1104 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1106 * TODO: use the NV_vertex_program (or 1_1) extension
1107 * and specifics vendors (ARB_vertex_program??) variants for it
1109 return TRUE;
1112 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1113 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1115 /** Vertex Shader Temporary Registers */
1116 WINED3DSHADERVECTOR R[12];
1117 /*D3DSHADERSCALAR A0;*/
1118 WINED3DSHADERVECTOR A[1];
1119 /** temporary Vector for modifier management */
1120 WINED3DSHADERVECTOR d;
1121 WINED3DSHADERVECTOR s[3];
1122 /** parser datas */
1123 const DWORD* pToken = This->baseShader.function;
1124 const SHADER_OPCODE* curOpcode = NULL;
1125 /** functions parameters */
1126 WINED3DSHADERVECTOR* p[4];
1127 WINED3DSHADERVECTOR* p_send[4];
1128 DWORD i;
1130 /** init temporary register */
1131 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1133 /* vshader_program_parse(vshader); */
1134 #if 0 /* Must not be 1 in cvs */
1135 TRACE("Input:\n");
1136 TRACE_VSVECTOR(This->data->C[0]);
1137 TRACE_VSVECTOR(This->data->C[1]);
1138 TRACE_VSVECTOR(This->data->C[2]);
1139 TRACE_VSVECTOR(This->data->C[3]);
1140 TRACE_VSVECTOR(This->data->C[4]);
1141 TRACE_VSVECTOR(This->data->C[5]);
1142 TRACE_VSVECTOR(This->data->C[6]);
1143 TRACE_VSVECTOR(This->data->C[7]);
1144 TRACE_VSVECTOR(This->data->C[8]);
1145 TRACE_VSVECTOR(This->data->C[64]);
1146 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1147 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1148 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1149 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1150 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1151 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1152 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1153 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1154 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1155 #endif
1157 TRACE_VSVECTOR(vshader->data->C[64]);
1158 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1160 /* the first dword is the version tag */
1161 /* TODO: parse it */
1163 if (shader_is_vshader_version(*pToken)) { /** version */
1164 ++pToken;
1166 while (D3DVS_END() != *pToken) {
1167 if (shader_is_comment(*pToken)) { /** comment */
1168 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1169 ++pToken;
1170 pToken += comment_len;
1171 continue ;
1173 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1174 ++pToken;
1175 if (NULL == curOpcode) {
1176 i = 0;
1177 /* unknown current opcode ... */
1178 /* TODO: Think of a name for 0x80000000 and replace its use with a constant */
1179 while (*pToken & 0x80000000) {
1180 if (i == 0) {
1181 FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1));
1183 FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken);
1184 shader_dump_param((IWineD3DBaseShader*) This, *pToken, i);
1185 TRACE("\n");
1186 ++i;
1187 ++pToken;
1189 /* return FALSE; */
1190 } else {
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]);
1197 switch (regtype) {
1198 case D3DSPR_TEMP:
1199 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1200 p[i] = &R[reg];
1201 break;
1202 case D3DSPR_INPUT:
1203 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1204 p[i] = &input->V[reg];
1205 break;
1206 case D3DSPR_CONST:
1207 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1208 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1209 } else {
1210 p[i] = &This->data->C[reg];
1212 break;
1213 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1214 if (0 != reg) {
1215 ERR("cannot handle address registers != a0, forcing use of a0\n");
1216 reg = 0;
1218 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1219 p[i] = &A[reg];
1220 break;
1221 case D3DSPR_RASTOUT:
1222 switch (reg) {
1223 case D3DSRO_POSITION:
1224 p[i] = &output->oPos;
1225 break;
1226 case D3DSRO_FOG:
1227 p[i] = &output->oFog;
1228 break;
1229 case D3DSRO_POINT_SIZE:
1230 p[i] = &output->oPts;
1231 break;
1233 break;
1234 case D3DSPR_ATTROUT:
1235 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1236 p[i] = &output->oD[reg];
1237 break;
1238 case D3DSPR_TEXCRDOUT:
1239 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1240 p[i] = &output->oT[reg];
1241 break;
1242 /* TODO Decls and defs */
1243 #if 0
1244 case D3DSPR_DCL:
1245 case D3DSPR_DEF:
1246 #endif
1247 default:
1248 break;
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); */
1257 p_send[i] = p[i];
1258 } else {
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];
1269 p_send[i] = &s[i];
1271 } else { /* output reg */
1272 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1273 p_send[i] = p[i];
1274 } else {
1275 p_send[i] = &d; /* to be post-processed for modifiers management */
1281 switch (curOpcode->num_params) {
1282 case 0:
1283 curOpcode->soft_fct();
1284 break;
1285 case 1:
1286 curOpcode->soft_fct(p_send[0]);
1287 break;
1288 case 2:
1289 curOpcode->soft_fct(p_send[0], p_send[1]);
1290 break;
1291 case 3:
1292 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1293 break;
1294 case 4:
1295 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1296 break;
1297 case 5:
1298 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1299 break;
1300 case 6:
1301 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1302 break;
1303 default:
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;
1314 #if 0
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]);
1326 #endif
1328 /* to next opcode token */
1329 pToken += curOpcode->num_params;
1331 #if 0
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]);
1344 #endif
1346 #if 0 /* Must not be 1 in cvs */
1347 TRACE("Output:\n");
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]);
1353 #endif
1354 return WINED3D_OK;
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);
1360 return WINED3D_OK;
1363 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1364 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1365 FIXME("(%p) : stub\n", This);
1366 return WINED3D_OK;
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);
1379 return WINED3D_OK;
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);
1392 return WINED3D_OK;
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);
1405 return WINED3D_OK;
1408 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1409 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1410 FIXME("(%p) : stub\n", This);
1411 return WINED3D_OK;
1414 #endif
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);
1428 *ppobj = This;
1429 return S_OK;
1431 *ppobj = NULL;
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;
1443 ULONG ref;
1444 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1445 ref = InterlockedDecrement(&This->ref);
1446 if (ref == 0) {
1447 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1448 HeapFree(GetProcessHeap(), 0, This);
1450 return ref;
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);
1463 return WINED3D_OK;
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);
1471 return WINED3D_OK;
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;
1480 return WINED3D_OK;
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;
1489 } else {
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);
1496 return WINED3D_OK;
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;
1503 DWORD len = 0;
1504 DWORD i;
1505 TRACE("(%p) : Parsing programme\n", This);
1507 /* Initialise vertex input arrays */
1508 This->namedArrays = FALSE;
1509 This->declaredArrays = FALSE;
1510 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1511 This->arrayUsageMap[i] = -1;
1513 if (NULL != pToken) {
1514 while (D3DVS_END() != *pToken) {
1515 if (shader_is_vshader_version(*pToken)) { /** version */
1516 vshader_set_version(This, *pToken);
1517 ++pToken;
1518 ++len;
1519 continue;
1521 if (shader_is_comment(*pToken)) { /** comment */
1522 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1523 ++pToken;
1524 TRACE("//%s\n", (char*)pToken);
1525 pToken += comment_len;
1526 len += comment_len + 1;
1527 continue;
1529 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
1530 ++pToken;
1531 ++len;
1532 if (NULL == curOpcode) {
1533 /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
1534 while (*pToken & 0x80000000) {
1535 /* unknown current opcode ... */
1536 FIXME("unrecognized opcode: %08lx", *pToken);
1537 ++pToken;
1538 ++len;
1539 TRACE("\n");
1542 } else {
1543 if (curOpcode->opcode == D3DSIO_DCL) {
1545 DWORD usage = *pToken;
1546 DWORD param = *(pToken + 1);
1548 parse_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1549 shader_program_dump_decl_usage(usage, param);
1550 shader_dump_ins_modifiers(param);
1551 TRACE(" ");
1552 shader_dump_param((IWineD3DBaseShader*) This, param, 0);
1553 pToken += 2;
1554 len += 2;
1556 } else
1557 if (curOpcode->opcode == D3DSIO_DEF) {
1558 TRACE("def c%lu = ", *pToken & 0xFF);
1559 ++pToken;
1560 ++len;
1561 TRACE("%f ,", *(float *)pToken);
1562 ++pToken;
1563 ++len;
1564 TRACE("%f ,", *(float *)pToken);
1565 ++pToken;
1566 ++len;
1567 TRACE("%f ,", *(float *)pToken);
1568 ++pToken;
1569 ++len;
1570 TRACE("%f", *(float *)pToken);
1571 ++pToken;
1572 ++len;
1573 } else {
1574 TRACE("%s", curOpcode->name);
1575 if (curOpcode->num_params > 0) {
1576 shader_dump_ins_modifiers(*pToken);
1577 TRACE(" ");
1578 shader_dump_param((IWineD3DBaseShader*) This, *pToken, 0);
1579 ++pToken;
1580 ++len;
1581 for (i = 1; i < curOpcode->num_params; ++i) {
1582 TRACE(", ");
1583 shader_dump_param((IWineD3DBaseShader*) This, *pToken, 1);
1584 ++pToken;
1585 ++len;
1589 TRACE("\n");
1592 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1593 } else {
1594 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1597 /* Handy for debugging using numbered arrays instead of named arrays */
1598 #if 1
1599 /* TODO: using numbered arrays for software shaders makes things easier */
1600 This->declaredArrays = TRUE;
1601 #endif
1603 /* named arrays and declared arrays are mutually exclusive */
1604 if (This->declaredArrays)
1605 This->namedArrays = FALSE;
1607 /* Generate HW shader in needed */
1608 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1609 #if 1
1610 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1611 #endif
1614 /* copy the function ... because it will certainly be released by application */
1615 if (NULL != pFunction) {
1616 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1617 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1618 } else {
1619 This->baseShader.function = NULL;
1621 return WINED3D_OK;
1624 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1626 /*** IUnknown methods ***/
1627 IWineD3DVertexShaderImpl_QueryInterface,
1628 IWineD3DVertexShaderImpl_AddRef,
1629 IWineD3DVertexShaderImpl_Release,
1630 /*** IWineD3DBase methods ***/
1631 IWineD3DVertexShaderImpl_GetParent,
1632 /*** IWineD3DBaseShader methods ***/
1633 IWineD3DVertexShaderImpl_SetFunction,
1634 /*** IWineD3DVertexShader methods ***/
1635 IWineD3DVertexShaderImpl_GetDevice,
1636 IWineD3DVertexShaderImpl_GetFunction