d3d9: Add a test for GetContainer (Volumes & Surfaces).
[wine/wine64.git] / dlls / wined3d / vertexshader.c
blob09d1f788cc7edc143d864f18d56766af3ac3153a
1 /*
2 * shaders implementation
4 * Copyright 2002-2003 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2006 Ivan Gyurdiev
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
26 #include <math.h>
27 #include <stdio.h>
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
35 /* Shader debugging - Change the following line to enable debugging of software
36 vertex shaders */
37 #if 0 /* Musxt not be 1 in cvs version */
38 # define VSTRACE(A) TRACE A
39 # define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
40 #else
41 # define VSTRACE(A)
42 # define TRACE_VSVECTOR(name)
43 #endif
45 #if 1 /* FIXME : Needs sorting when vshader code moved in properly */
47 /**
48 * DirectX9 SDK download
49 * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
51 * Exploring D3DX
52 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
54 * Using Vertex Shaders
55 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
57 * Dx9 New
58 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
60 * Dx9 Shaders
61 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
62 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
63 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
64 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
66 * Dx9 D3DX
67 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
69 * FVF
70 * http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
72 * NVIDIA: DX8 Vertex Shader to NV Vertex Program
73 * http://developer.nvidia.com/view.asp?IO=vstovp
75 * NVIDIA: Memory Management with VAR
76 * http://developer.nvidia.com/view.asp?IO=var_memory_management
79 /* TODO: Vertex and Pixel shaders are almost identicle, the only exception being the way that some of the data is looked up or the availablity of some of the data i.e. some instructions are only valid for pshaders and some for vshaders
80 because of this the bulk of the software pipeline can be shared between pixel and vertex shaders... and it wouldn't supprise me if the programes can be cross compiled using a large body body shared code */
82 #define GLNAME_REQUIRE_GLSL ((const char *)1)
84 /*******************************
85 * vshader functions software VM
88 void vshader_add(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
89 d->x = s0->x + s1->x;
90 d->y = s0->y + s1->y;
91 d->z = s0->z + s1->z;
92 d->w = s0->w + s1->w;
93 VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
94 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
97 void vshader_dp3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
98 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
99 VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
100 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
103 void vshader_dp4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
104 d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
105 VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
106 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
109 void vshader_dst(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
110 d->x = 1.0f;
111 d->y = s0->y * s1->y;
112 d->z = s0->z;
113 d->w = s1->w;
114 VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
115 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
118 void vshader_expp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
119 union {
120 float f;
121 DWORD d;
122 } tmp;
124 tmp.f = floorf(s0->w);
125 d->x = powf(2.0f, tmp.f);
126 d->y = s0->w - tmp.f;
127 tmp.f = powf(2.0f, s0->w);
128 tmp.d &= 0xFFFFFF00U;
129 d->z = tmp.f;
130 d->w = 1.0f;
131 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
132 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
135 void vshader_lit(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
136 d->x = 1.0f;
137 d->y = (0.0f < s0->x) ? s0->x : 0.0f;
138 d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
139 d->w = 1.0f;
140 VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
141 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
144 void vshader_logp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
145 float tmp_f = fabsf(s0->w);
146 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
147 VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
148 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
151 void vshader_mad(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
152 d->x = s0->x * s1->x + s2->x;
153 d->y = s0->y * s1->y + s2->y;
154 d->z = s0->z * s1->z + s2->z;
155 d->w = s0->w * s1->w + s2->w;
156 VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
157 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, s2->x, s2->y, s2->z, s2->w, d->x, d->y, d->z, d->w));
160 void vshader_max(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
161 d->x = (s0->x >= s1->x) ? s0->x : s1->x;
162 d->y = (s0->y >= s1->y) ? s0->y : s1->y;
163 d->z = (s0->z >= s1->z) ? s0->z : s1->z;
164 d->w = (s0->w >= s1->w) ? s0->w : s1->w;
165 VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
166 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
169 void vshader_min(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
170 d->x = (s0->x < s1->x) ? s0->x : s1->x;
171 d->y = (s0->y < s1->y) ? s0->y : s1->y;
172 d->z = (s0->z < s1->z) ? s0->z : s1->z;
173 d->w = (s0->w < s1->w) ? s0->w : s1->w;
174 VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
175 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
178 void vshader_mov(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
179 d->x = s0->x;
180 d->y = s0->y;
181 d->z = s0->z;
182 d->w = s0->w;
183 VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
184 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
187 void vshader_mul(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
188 d->x = s0->x * s1->x;
189 d->y = s0->y * s1->y;
190 d->z = s0->z * s1->z;
191 d->w = s0->w * s1->w;
192 VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
193 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
196 void vshader_nop(void) {
197 /* NOPPPP ahhh too easy ;) */
198 VSTRACE(("executing nop\n"));
201 void vshader_rcp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
202 d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE_VAL : 1.0f / s0->w;
203 VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
204 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
207 void vshader_rsq(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
208 float tmp_f = fabsf(s0->w);
209 d->x = d->y = d->z = d->w = (0.0f == tmp_f) ? HUGE_VAL : ((1.0f != tmp_f) ? 1.0f / sqrtf(tmp_f) : 1.0f);
210 VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
211 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
214 void vshader_sge(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
215 d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
216 d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
217 d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
218 d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
219 VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
220 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
223 void vshader_slt(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
224 d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
225 d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
226 d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
227 d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
228 VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
229 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
232 void vshader_sub(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
233 d->x = s0->x - s1->x;
234 d->y = s0->y - s1->y;
235 d->z = s0->z - s1->z;
236 d->w = s0->w - s1->w;
237 VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
238 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
242 * Version 1.1 specific
245 void vshader_exp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
246 d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
247 VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
248 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
251 void vshader_log(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
252 float tmp_f = fabsf(s0->w);
253 d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE_VAL;
254 VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
255 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
258 void vshader_frc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
259 d->x = s0->x - floorf(s0->x);
260 d->y = s0->y - floorf(s0->y);
261 d->z = 0.0f;
262 d->w = 1.0f;
263 VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
264 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
267 typedef FLOAT D3DMATRIX44[4][4];
268 typedef FLOAT D3DMATRIX43[4][3];
269 typedef FLOAT D3DMATRIX34[3][4];
270 typedef FLOAT D3DMATRIX33[3][3];
271 typedef FLOAT D3DMATRIX23[2][3];
273 void vshader_m4x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, /*WINED3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
275 * Buggy CODE: here only if cast not work for copy/paste
276 WINED3DSHADERVECTOR* mat2 = mat1 + 1;
277 WINED3DSHADERVECTOR* mat3 = mat1 + 2;
278 WINED3DSHADERVECTOR* mat4 = mat1 + 3;
279 d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
280 d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
281 d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
282 d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
284 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
285 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
286 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
287 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
288 VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
289 VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
290 VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
291 VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
294 void vshader_m4x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
295 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
296 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
297 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
298 d->w = 1.0f;
299 VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
300 VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
301 VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
302 VSTRACE(("executing m4x3(4): (%f) (%f) \n", s0->w, d->w));
305 void vshader_m3x4(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
306 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
307 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
308 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
309 d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
310 VSTRACE(("executing m3x4(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
311 VSTRACE(("executing m3x4(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
312 VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
313 VSTRACE(("executing m3x4(4): mat=(%f, %f, %f) (%f) (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
316 void vshader_m3x3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
317 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
318 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
319 d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
320 d->w = 1.0f;
321 VSTRACE(("executing m3x3(1): mat=(%f, %f, %f) s0=(%f) d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
322 VSTRACE(("executing m3x3(2): mat=(%f, %f, %f) (%f) (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
323 VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X (%f) = (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
324 VSTRACE(("executing m3x3(4): (%f) \n", d->w));
327 void vshader_m3x2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, D3DMATRIX23 mat) {
328 FIXME("check\n");
329 d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
330 d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
331 d->z = 0.0f;
332 d->w = 1.0f;
336 * Version 2.0 specific
338 void vshader_lrp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
339 d->x = s0->x * (s1->x - s2->x) + s2->x;
340 d->y = s0->y * (s1->y - s2->y) + s2->y;
341 d->z = s0->z * (s1->z - s2->z) + s2->z;
342 d->w = s0->w * (s1->w - s2->w) + s2->w;
345 void vshader_crs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
346 d->x = s0->y * s1->z - s0->z * s1->y;
347 d->y = s0->z * s1->x - s0->x * s1->z;
348 d->z = s0->x * s1->y - s0->y * s1->x;
349 d->w = 0.9f; /* w is undefined, so set it to something safeish */
351 VSTRACE(("executing crs: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
352 s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
355 void vshader_abs(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
357 d->x = fabsf(s0->x);
358 d->y = fabsf(s0->y);
359 d->z = fabsf(s0->z);
360 d->w = fabsf(s0->w);
361 VSTRACE(("executing abs: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
362 s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
365 /* Stubs */
367 /* Def is C[n] = {n.nf, n.nf, n.nf, n.nf} */
368 void vshader_def(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
369 FIXME(" : Stub\n");
372 void vshader_call(WINED3DSHADERVECTOR* d) {
373 FIXME(" : Stub\n");
376 void vshader_callnz(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
377 FIXME(" : Stub\n");
380 void vshader_loop(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
381 FIXME(" : Stub\n");
384 void vshader_ret(void) {
385 FIXME(" : Stub\n");
388 void vshader_endloop(void) {
389 FIXME(" : Stub\n");
392 void vshader_dcl(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
393 FIXME(" : Stub\n");
396 void vshader_pow(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
397 FIXME(" : Stub\n");
400 void vshader_sng(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
401 FIXME(" : Stub\n");
404 void vshader_nrm(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
405 FIXME(" : Stub\n");
408 void vshader_sincos3(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
409 FIXME(" : Stub\n");
412 void vshader_sincos2(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2) {
413 FIXME(" : Stub\n");
416 void vshader_rep(WINED3DSHADERVECTOR* d) {
417 FIXME(" : Stub\n");
420 void vshader_endrep(void) {
421 FIXME(" : Stub\n");
424 void vshader_if(WINED3DSHADERVECTOR* d) {
425 FIXME(" : Stub\n");
428 void vshader_ifc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
429 FIXME(" : Stub\n");
432 void vshader_else(void) {
433 FIXME(" : Stub\n");
436 void vshader_label(WINED3DSHADERVECTOR* d) {
437 FIXME(" : Stub\n");
440 void vshader_endif(void) {
441 FIXME(" : Stub\n");
444 void vshader_break(void) {
445 FIXME(" : Stub\n");
448 void vshader_breakc(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0) {
449 FIXME(" : Stub\n");
452 void vshader_breakp(WINED3DSHADERVECTOR* d) {
453 FIXME(" : Stub\n");
456 void vshader_mova(WINED3DSHADERVECTOR* d) {
457 FIXME(" : Stub\n");
460 void vshader_defb(WINED3DSHADERVECTOR* d) {
461 FIXME(" : Stub\n");
464 void vshader_defi(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1, WINED3DSHADERVECTOR* s2, WINED3DSHADERVECTOR* s3) {
465 FIXME(" : Stub\n");
468 void vshader_texldd(WINED3DSHADERVECTOR* d) {
469 FIXME(" : Stub\n");
472 void vshader_setp(WINED3DSHADERVECTOR* d, WINED3DSHADERVECTOR* s0, WINED3DSHADERVECTOR* s1) {
473 FIXME(" : Stub\n");
476 void vshader_texldl(WINED3DSHADERVECTOR* d) {
477 FIXME(" : Stub\n");
480 /* Prototype */
481 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
482 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg);
483 void vshader_hw_def(SHADER_OPCODE_ARG* arg);
484 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
487 * log, exp, frc, m*x* seems to be macros ins ... to see
489 CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
491 /* Arithmetic */
492 {D3DSIO_NOP, "nop", "NOP", 0, vshader_nop, vshader_hw_map2gl, NULL, 0, 0},
493 {D3DSIO_MOV, "mov", "MOV", 2, vshader_mov, vshader_hw_map2gl, NULL, 0, 0},
494 {D3DSIO_ADD, "add", "ADD", 3, vshader_add, vshader_hw_map2gl, NULL, 0, 0},
495 {D3DSIO_SUB, "sub", "SUB", 3, vshader_sub, vshader_hw_map2gl, NULL, 0, 0},
496 {D3DSIO_MAD, "mad", "MAD", 4, vshader_mad, vshader_hw_map2gl, NULL, 0, 0},
497 {D3DSIO_MUL, "mul", "MUL", 3, vshader_mul, vshader_hw_map2gl, NULL, 0, 0},
498 {D3DSIO_RCP, "rcp", "RCP", 2, vshader_rcp, vshader_hw_map2gl, NULL, 0, 0},
499 {D3DSIO_RSQ, "rsq", "RSQ", 2, vshader_rsq, vshader_hw_map2gl, NULL, 0, 0},
500 {D3DSIO_DP3, "dp3", "DP3", 3, vshader_dp3, vshader_hw_map2gl, NULL, 0, 0},
501 {D3DSIO_DP4, "dp4", "DP4", 3, vshader_dp4, vshader_hw_map2gl, NULL, 0, 0},
502 {D3DSIO_MIN, "min", "MIN", 3, vshader_min, vshader_hw_map2gl, NULL, 0, 0},
503 {D3DSIO_MAX, "max", "MAX", 3, vshader_max, vshader_hw_map2gl, NULL, 0, 0},
504 {D3DSIO_SLT, "slt", "SLT", 3, vshader_slt, vshader_hw_map2gl, NULL, 0, 0},
505 {D3DSIO_SGE, "sge", "SGE", 3, vshader_sge, vshader_hw_map2gl, NULL, 0, 0},
506 {D3DSIO_ABS, "abs", "ABS", 2, vshader_abs, vshader_hw_map2gl, NULL, 0, 0},
507 {D3DSIO_EXP, "exp", "EX2", 2, vshader_exp, vshader_hw_map2gl, NULL, 0, 0},
508 {D3DSIO_LOG, "log", "LG2", 2, vshader_log, vshader_hw_map2gl, NULL, 0, 0},
509 {D3DSIO_EXPP, "expp", "EXP", 2, vshader_expp, vshader_hw_map2gl, NULL, 0, 0},
510 {D3DSIO_LOGP, "logp", "LOG", 2, vshader_logp, vshader_hw_map2gl, NULL, 0, 0},
511 {D3DSIO_LIT, "lit", "LIT", 2, vshader_lit, vshader_hw_map2gl, NULL, 0, 0},
512 {D3DSIO_DST, "dst", "DST", 3, vshader_dst, vshader_hw_map2gl, NULL, 0, 0},
513 {D3DSIO_LRP, "lrp", "LRP", 4, vshader_lrp, NULL, NULL, 0, 0},
514 {D3DSIO_FRC, "frc", "FRC", 2, vshader_frc, vshader_hw_map2gl, NULL, 0, 0},
515 {D3DSIO_POW, "pow", "POW", 3, vshader_pow, NULL, NULL, 0, 0},
516 {D3DSIO_CRS, "crs", "XPS", 3, vshader_crs, NULL, NULL, 0, 0},
517 /* TODO: sng can possibly be performed a s
518 RCP tmp, vec
519 MUL out, tmp, vec*/
520 {D3DSIO_SGN, "sng", NULL, 2, vshader_sng, NULL, NULL, 0, 0},
521 /* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
522 DP3 tmp , vec, vec;
523 RSQ tmp, tmp.x;
524 MUL vec.xyz, vec, tmp;
525 but I think this is better because it accounts for w properly.
526 DP3 tmp , vec, vec;
527 RSQ tmp, tmp.x;
528 MUL vec, vec, tmp;
531 {D3DSIO_NRM, "nrm", NULL, 2, vshader_nrm, NULL, NULL, 0, 0},
532 {D3DSIO_SINCOS, "sincos", NULL, 4, vshader_sincos2, NULL, NULL, D3DVS_VERSION(2,0), D3DVS_VERSION(2,0)},
533 {D3DSIO_SINCOS, "sincos", NULL, 2, vshader_sincos3, NULL, NULL, D3DVS_VERSION(3,0), -1},
535 /* Matrix */
536 {D3DSIO_M4x4, "m4x4", "undefined", 3, vshader_m4x4, vshader_hw_mnxn, NULL, 0, 0},
537 {D3DSIO_M4x3, "m4x3", "undefined", 3, vshader_m4x3, vshader_hw_mnxn, NULL, 0, 0},
538 {D3DSIO_M3x4, "m3x4", "undefined", 3, vshader_m3x4, vshader_hw_mnxn, NULL, 0, 0},
539 {D3DSIO_M3x3, "m3x3", "undefined", 3, vshader_m3x3, vshader_hw_mnxn, NULL, 0, 0},
540 {D3DSIO_M3x2, "m3x2", "undefined", 3, vshader_m3x2, vshader_hw_mnxn, NULL, 0, 0},
542 /* Declare registers */
543 {D3DSIO_DCL, "dcl", NULL, 2, vshader_dcl, vshader_hw_dcl, NULL, 0, 0},
545 /* Constant definitions */
546 {D3DSIO_DEF, "def", NULL, 5, vshader_def, vshader_hw_def, NULL, 0, 0},
547 {D3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 2, vshader_defb, NULL, NULL, 0, 0},
548 {D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 5, vshader_defi, NULL, NULL, 0, 0},
550 /* Flow control - requires GLSL or software shaders */
551 {D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 1, vshader_rep, NULL, NULL, 0, 0},
552 {D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, vshader_endrep, NULL, NULL, 0, 0},
553 {D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 1, vshader_if, NULL, NULL, 0, 0},
554 {D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 2, vshader_ifc, NULL, NULL, 0, 0},
555 {D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, vshader_else, NULL, NULL, 0, 0},
556 {D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, vshader_endif, NULL, NULL, 0, 0},
557 {D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, vshader_break, NULL, NULL, 0, 0},
558 {D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 2, vshader_breakc, NULL, NULL, 0, 0},
559 {D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 1, vshader_breakp, NULL, NULL, 0, 0},
560 {D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 1, vshader_call, NULL, NULL, 0, 0},
561 {D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 2, vshader_callnz, NULL, NULL, 0, 0},
562 {D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 2, vshader_loop, NULL, NULL, 0, 0},
563 {D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, vshader_ret, NULL, NULL, 0, 0},
564 {D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, vshader_endloop, NULL, NULL, 0, 0},
565 {D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 1, vshader_label, NULL, NULL, 0, 0},
567 {D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 2, vshader_mova, NULL, NULL, 0, 0},
568 {D3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 3, vshader_setp, NULL, NULL, 0, 0},
569 {D3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 2, vshader_texldl, NULL, NULL, 0, 0},
570 {0, NULL, NULL, 0, NULL, NULL, 0, 0}
573 inline static void vshader_program_add_output_param_swizzle(const DWORD param, int is_color, char *hwLine) {
574 /** operand output */
575 if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
576 strcat(hwLine, ".");
577 if (param & D3DSP_WRITEMASK_0) { strcat(hwLine, "x"); }
578 if (param & D3DSP_WRITEMASK_1) { strcat(hwLine, "y"); }
579 if (param & D3DSP_WRITEMASK_2) { strcat(hwLine, "z"); }
580 if (param & D3DSP_WRITEMASK_3) { strcat(hwLine, "w"); }
584 inline static void vshader_program_add_input_param_swizzle(const DWORD param, int is_color, char *hwLine) {
585 static const char swizzle_reg_chars_color_fix[] = "zyxw";
586 static const char swizzle_reg_chars[] = "xyzw";
587 const char* swizzle_regs = NULL;
588 char tmpReg[255];
590 /** operand input */
591 DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
592 DWORD swizzle_x = swizzle & 0x03;
593 DWORD swizzle_y = (swizzle >> 2) & 0x03;
594 DWORD swizzle_z = (swizzle >> 4) & 0x03;
595 DWORD swizzle_w = (swizzle >> 6) & 0x03;
597 if (is_color) {
598 swizzle_regs = swizzle_reg_chars_color_fix;
599 } else {
600 swizzle_regs = swizzle_reg_chars;
604 * swizzle bits fields:
605 * WWZZYYXX
607 if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
608 if (is_color) {
609 sprintf(tmpReg, ".%c%c%c%c",
610 swizzle_regs[swizzle_x],
611 swizzle_regs[swizzle_y],
612 swizzle_regs[swizzle_z],
613 swizzle_regs[swizzle_w]);
614 strcat(hwLine, tmpReg);
616 return ;
618 if (swizzle_x == swizzle_y &&
619 swizzle_x == swizzle_z &&
620 swizzle_x == swizzle_w)
622 sprintf(tmpReg, ".%c", swizzle_regs[swizzle_x]);
623 strcat(hwLine, tmpReg);
624 } else {
625 sprintf(tmpReg, ".%c%c%c%c",
626 swizzle_regs[swizzle_x],
627 swizzle_regs[swizzle_y],
628 swizzle_regs[swizzle_z],
629 swizzle_regs[swizzle_w]);
630 strcat(hwLine, tmpReg);
634 inline static void vshader_program_add_param(IWineD3DVertexShaderImpl *This, const DWORD param, BOOL is_input, char *hwLine) {
635 /* oPos, oFog and oPts in D3D */
636 static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" };
638 DWORD reg = param & D3DSP_REGNUM_MASK;
639 DWORD regtype = shader_get_regtype(param);
640 char tmpReg[255];
641 BOOL is_color = FALSE;
643 if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
644 strcat(hwLine, " -");
645 } else {
646 strcat(hwLine, " ");
649 switch (regtype) {
650 case D3DSPR_TEMP:
651 sprintf(tmpReg, "R%lu", reg);
652 strcat(hwLine, tmpReg);
653 break;
654 case D3DSPR_INPUT:
655 if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
656 || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
657 is_color = TRUE;
659 /* if the attributes come in as named dcl's then use a named vertex (called namedVertexN) */
660 if (This->namedArrays) {
661 sprintf(tmpReg, "namedVertex%lu", reg);
662 } else {
663 /* otherwise the input is on a numbered attribute so use opengl numbered attributes */
664 sprintf(tmpReg, "vertex.attrib[%lu]", reg);
666 strcat(hwLine, tmpReg);
667 break;
668 case D3DSPR_CONST:
669 /* FIXME: some constants are named so we need a constants map*/
670 if (This->constantsUsedBitmap[reg] == VS_CONSTANT_CONSTANT) {
671 if (param & D3DVS_ADDRMODE_RELATIVE) {
672 FIXME("Relative addressing not expected for a named constant %lu\n", reg);
674 sprintf(tmpReg, "C%lu", reg);
675 } else {
676 sprintf(tmpReg, "C[%s%lu]", (param & D3DVS_ADDRMODE_RELATIVE) ? "A0.x + " : "", reg);
678 strcat(hwLine, tmpReg);
679 break;
680 case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
681 sprintf(tmpReg, "A%lu", reg);
682 strcat(hwLine, tmpReg);
683 break;
684 case D3DSPR_RASTOUT:
685 sprintf(tmpReg, "%s", hwrastout_reg_names[reg]);
686 strcat(hwLine, tmpReg);
687 break;
688 case D3DSPR_ATTROUT:
689 if (reg==0) {
690 strcat(hwLine, "result.color.primary");
691 } else {
692 strcat(hwLine, "result.color.secondary");
694 break;
695 case D3DSPR_TEXCRDOUT:
696 sprintf(tmpReg, "result.texcoord[%lu]", reg);
697 strcat(hwLine, tmpReg);
698 break;
699 default:
700 FIXME("Unknown reg type %ld %ld\n", regtype, reg);
701 strcat(hwLine, "unrecognized_register");
702 break;
705 if (!is_input) {
706 vshader_program_add_output_param_swizzle(param, is_color, hwLine);
707 } else {
708 vshader_program_add_input_param_swizzle(param, is_color, hwLine);
712 static void vshader_parse_input_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
714 switch(usage & 0xFFFF) {
715 case D3DDECLUSAGE_POSITION:
716 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
717 TRACE("Setting position to %d\n", arrayNo);
718 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION] = arrayNo;
719 This->namedArrays = TRUE;
720 } else {
721 /* TODO: position indexes go from 0-8!!*/
722 TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
723 /* robots uses positions up to 8, the position arrays are just packed.*/
724 if ((usage & 0xF0000) >> 16 > 1) {
725 TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
727 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
728 This->declaredArrays = TRUE;
730 break;
731 case D3DDECLUSAGE_BLENDINDICES:
732 /* not supported by openGL */
733 TRACE("Setting BLENDINDICES to %d\n", arrayNo);
734 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
735 This->declaredArrays = TRUE;
736 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
737 break;
738 case D3DDECLUSAGE_BLENDWEIGHT:
739 TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
740 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = arrayNo;
741 This->namedArrays = TRUE;
742 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
743 break;
744 case D3DDECLUSAGE_NORMAL:
745 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
746 TRACE("Setting normal to %d\n", arrayNo);
747 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL] = arrayNo;
748 This->namedArrays = TRUE;
749 } else {
750 TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
751 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2] = arrayNo;
752 This->declaredArrays = TRUE;
754 break;
755 case D3DDECLUSAGE_PSIZE:
756 TRACE("Setting PSIZE to %d\n", arrayNo);
757 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE] = arrayNo;
758 This->namedArrays = TRUE;
759 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
760 break;
761 case D3DDECLUSAGE_COLOR:
762 if((usage & 0xF0000) >> 16 == 0) {
763 TRACE("Setting DIFFUSE to %d\n", arrayNo);
764 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] = arrayNo;
765 This->namedArrays = TRUE;
766 } else {
767 TRACE("Setting SPECULAR to %d\n", arrayNo);
768 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
769 This->namedArrays = TRUE;
771 break;
772 case D3DDECLUSAGE_TEXCOORD:
773 This->namedArrays = TRUE;
774 /* only 7 texture coords have been designed for, so run a quick sanity check */
775 if ((usage & 0xF0000) >> 16 > 7) {
776 FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
777 } else {
778 TRACE("Setting TEXCOORD %d to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
779 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
781 break;
782 /* The following aren't supported by openGL,
783 if we get them then everything needs to be mapped to numbered attributes instead of named ones.
784 this should be caught in the first pass */
785 case D3DDECLUSAGE_TANGENT:
786 TRACE("Setting TANGENT to %d\n", arrayNo);
787 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT] = arrayNo;
788 This->declaredArrays = TRUE;
789 break;
790 case D3DDECLUSAGE_BINORMAL:
791 TRACE("Setting BINORMAL to %d\n", arrayNo);
792 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL] = arrayNo;
793 This->declaredArrays = TRUE;
794 break;
795 case D3DDECLUSAGE_TESSFACTOR:
796 TRACE("Setting TESSFACTOR to %d\n", arrayNo);
797 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR] = arrayNo;
798 This->declaredArrays = TRUE;
799 break;
800 case D3DDECLUSAGE_POSITIONT:
801 if((usage & 0xF0000) >> 16 == 0) { /* tween data */
802 FIXME("Setting positiont to %d\n", arrayNo);
803 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
804 This->namedArrays = TRUE;
805 } else {
806 FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
807 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
808 This->declaredArrays = TRUE;
809 if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
811 break;
812 case D3DDECLUSAGE_FOG:
813 /* supported by OpenGL */
814 TRACE("Setting FOG to %d\n", arrayNo);
815 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG] = arrayNo;
816 This->namedArrays = TRUE;
817 break;
818 case D3DDECLUSAGE_DEPTH:
819 TRACE("Setting DEPTH to %d\n", arrayNo);
820 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH] = arrayNo;
821 This->declaredArrays = TRUE;
822 break;
823 case D3DDECLUSAGE_SAMPLE:
824 TRACE("Setting SAMPLE to %d\n", arrayNo);
825 This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE] = arrayNo;
826 This->declaredArrays = TRUE;
827 break;
828 default:
829 FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
833 void vshader_set_version(
834 IWineD3DVertexShaderImpl *This,
835 DWORD version) {
837 DWORD major = (version >> 8) & 0x0F;
838 DWORD minor = version & 0x0F;
840 This->baseShader.hex_version = version;
841 This->baseShader.version = major * 10 + minor;
842 TRACE("vs_%lu_%lu\n", major, minor);
844 This->baseShader.limits.texture = 0;
845 This->baseShader.limits.attributes = 16;
847 /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
848 This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
850 switch (This->baseShader.version) {
851 case 10:
852 case 11: This->baseShader.limits.temporary = 12;
853 This->baseShader.limits.constant_bool = 0;
854 This->baseShader.limits.constant_int = 0;
855 This->baseShader.limits.address = 1;
856 break;
858 case 20:
859 case 21: This->baseShader.limits.temporary = 12;
860 This->baseShader.limits.constant_bool = 16;
861 This->baseShader.limits.constant_int = 16;
862 This->baseShader.limits.address = 1;
863 break;
865 case 30: This->baseShader.limits.temporary = 32;
866 This->baseShader.limits.constant_bool = 32;
867 This->baseShader.limits.constant_int = 32;
868 This->baseShader.limits.address = 1;
869 break;
871 default: This->baseShader.limits.temporary = 12;
872 This->baseShader.limits.constant_bool = 0;
873 This->baseShader.limits.constant_int = 0;
874 This->baseShader.limits.address = 1;
875 FIXME("Unrecognized vertex shader version %lx!\n", version);
879 /* Map the opcode 1-to-1 to the GL code */
880 void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg) {
882 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) arg->shader;
883 CONST SHADER_OPCODE* curOpcode = arg->opcode;
884 SHADER_BUFFER* buffer = arg->buffer;
885 DWORD dst = arg->dst;
886 DWORD* src = arg->src;
888 DWORD dst_regtype = shader_get_regtype(dst);
889 char tmpLine[256];
890 unsigned int i;
892 if (curOpcode->opcode == D3DSIO_MOV && dst_regtype == D3DSPR_ADDR)
893 strcpy(tmpLine, "ARL");
894 else
895 strcpy(tmpLine, curOpcode->glname);
897 if (curOpcode->num_params > 0) {
898 vshader_program_add_param(This, dst, FALSE, tmpLine);
899 for (i = 1; i < curOpcode->num_params; ++i) {
900 strcat(tmpLine, ",");
901 vshader_program_add_param(This, src[i-1], TRUE, tmpLine);
904 shader_addline(buffer, "%s;\n", tmpLine);
907 void vshader_hw_dcl(SHADER_OPCODE_ARG* arg) {
909 DWORD dst = arg->dst;
910 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
911 char tmpLine[256];
912 SHADER_BUFFER* buffer = arg->buffer;
914 if (This->namedArrays) {
915 const char* attribName = "undefined";
916 switch(dst & 0xFFFF) {
917 case D3DDECLUSAGE_POSITION:
918 attribName = "vertex.position";
919 break;
920 case D3DDECLUSAGE_BLENDINDICES:
921 /* not supported by openGL */
922 attribName = "vertex.blend";
923 break;
924 case D3DDECLUSAGE_BLENDWEIGHT:
925 attribName = "vertex.weight";
926 break;
927 case D3DDECLUSAGE_NORMAL:
928 attribName = "vertex.normal";
929 break;
930 case D3DDECLUSAGE_PSIZE:
931 attribName = "vertex.psize";
932 break;
933 case D3DDECLUSAGE_COLOR:
934 if((dst & 0xF0000) >> 16 == 0) {
935 attribName = "vertex.color";
936 } else {
937 attribName = "vertex.color.secondary";
939 break;
940 case D3DDECLUSAGE_TEXCOORD:
942 char tmpChar[100];
943 tmpChar[0] = 0;
944 sprintf(tmpChar,"vertex.texcoord[%lu]",(dst & 0xF0000) >> 16);
945 attribName = tmpChar;
946 break;
948 /* The following aren't directly supported by openGL, so shouldn't come up using namedarrays. */
949 case D3DDECLUSAGE_TANGENT:
950 attribName = "vertex.tangent";
951 break;
952 case D3DDECLUSAGE_BINORMAL:
953 attribName = "vertex.binormal";
954 break;
955 case D3DDECLUSAGE_TESSFACTOR:
956 attribName = "vertex.tessfactor";
957 break;
958 case D3DDECLUSAGE_POSITIONT:
959 attribName = "vertex.possitionT";
960 break;
961 case D3DDECLUSAGE_FOG:
962 attribName = "vertex.fogcoord";
963 break;
964 case D3DDECLUSAGE_DEPTH:
965 attribName = "vertex.depth";
966 break;
967 case D3DDECLUSAGE_SAMPLE:
968 attribName = "vertex.sample";
969 break;
970 default:
971 FIXME("Unrecognised dcl %08lx", dst & 0xFFFF);
974 sprintf(tmpLine, "ATTRIB ");
975 vshader_program_add_param(This, dst, FALSE, tmpLine);
976 if (This->namedArrays)
977 shader_addline(buffer, "%s = %s;\n", tmpLine, attribName);
982 void vshader_hw_def(SHADER_OPCODE_ARG* arg) {
984 IWineD3DVertexShaderImpl* shader = (IWineD3DVertexShaderImpl*) arg->shader;
985 SHADER_BUFFER* buffer = arg->buffer;
986 DWORD reg = arg->dst;
988 shader_addline(buffer,
989 "PARAM C%lu = { %f, %f, %f, %f };\n", reg & 0xFF,
990 *((const float *)(arg->src + 0)),
991 *((const float *)(arg->src + 1)),
992 *((const float *)(arg->src + 2)),
993 *((const float *)(arg->src + 3)) );
995 shader->constantsUsedBitmap[reg & 0xFF] = VS_CONSTANT_CONSTANT;
998 /** Handles transforming all D3DSIO_M?x? opcodes for
999 Vertex shaders to ARB_vertex_program codes */
1000 void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) {
1002 int i;
1003 int nComponents = 0;
1004 SHADER_OPCODE_ARG tmpArg;
1006 /* Set constants for the temporary argument */
1007 tmpArg.shader = arg->shader;
1008 tmpArg.buffer = arg->buffer;
1009 tmpArg.src[0] = arg->src[0];
1011 switch(arg->opcode->opcode) {
1012 case D3DSIO_M4x4:
1013 nComponents = 4;
1014 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1015 break;
1016 case D3DSIO_M4x3:
1017 nComponents = 3;
1018 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1019 break;
1020 case D3DSIO_M3x4:
1021 nComponents = 4;
1022 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1023 break;
1024 case D3DSIO_M3x3:
1025 nComponents = 3;
1026 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1027 break;
1028 case D3DSIO_M3x2:
1029 nComponents = 2;
1030 tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1031 break;
1032 default:
1033 break;
1036 for (i = 0; i < nComponents; i++) {
1037 tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1038 tmpArg.src[1] = arg->src[1]+i;
1039 vshader_hw_map2gl(&tmpArg);
1043 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
1044 or GLSL and send it to the card */
1045 inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
1046 IWineD3DVertexShader *iface,
1047 CONST DWORD *pFunction) {
1049 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1050 SHADER_BUFFER buffer;
1052 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
1053 it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
1054 if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
1055 HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
1056 This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
1057 This->fixupVertexBufferSize = PGMSIZE;
1058 This->fixupVertexBuffer[0] = 0;
1060 buffer.buffer = This->device->fixupVertexBuffer;
1061 #else
1062 buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
1063 #endif
1064 buffer.bsize = 0;
1065 buffer.lineNo = 0;
1067 if (wined3d_settings.shader_mode == SHADER_GLSL) {
1069 /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
1070 GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
1072 /* Generate the bulk of the shader code */
1073 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1075 shader_addline(&buffer, "}\n\0");
1077 TRACE("Compiling shader object %u\n", shader_obj);
1078 GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
1079 GL_EXTCALL(glCompileShaderARB(shader_obj));
1080 print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
1082 /* Store the shader object */
1083 This->baseShader.prgId = shader_obj;
1085 } else if (wined3d_settings.shader_mode == SHADER_ARB) {
1087 /* Create the hw ARB shader */
1088 shader_addline(&buffer, "!!ARBvp1.0\n");
1090 /* Mesa supports only 95 constants */
1091 if (GL_VEND(MESA) || GL_VEND(WINE))
1092 This->baseShader.limits.constant_float =
1093 min(95, This->baseShader.limits.constant_float);
1095 /** Call the base shader generation routine to generate most
1096 of the vertex shader string for us */
1097 generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
1099 shader_addline(&buffer, "END\n\0");
1101 /* TODO: change to resource.glObjectHandle or something like that */
1102 GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
1104 TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
1105 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
1107 TRACE("Created hw vertex shader, prg=%d\n", This->baseShader.prgId);
1108 /* Create the program and check for errors */
1109 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
1110 buffer.bsize, buffer.buffer));
1112 if (glGetError() == GL_INVALID_OPERATION) {
1113 GLint errPos;
1114 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
1115 FIXME("HW VertexShader Error at position %d: %s\n",
1116 errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
1117 This->baseShader.prgId = -1;
1121 #if 1 /* if were using the data buffer of device then we don't need to free it */
1122 HeapFree(GetProcessHeap(), 0, buffer.buffer);
1123 #endif
1126 BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1128 * TODO: use the NV_vertex_program (or 1_1) extension
1129 * and specifics vendors (ARB_vertex_program??) variants for it
1131 return TRUE;
1134 HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
1135 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1136 DWORD opcode_token;
1138 /** Vertex Shader Temporary Registers */
1139 WINED3DSHADERVECTOR R[12];
1140 /*D3DSHADERSCALAR A0;*/
1141 WINED3DSHADERVECTOR A[1];
1142 /** temporary Vector for modifier management */
1143 WINED3DSHADERVECTOR d;
1144 WINED3DSHADERVECTOR s[3];
1145 /** parser datas */
1146 const DWORD* pToken = This->baseShader.function;
1147 const SHADER_OPCODE* curOpcode = NULL;
1148 /** functions parameters */
1149 WINED3DSHADERVECTOR* p[6];
1150 WINED3DSHADERVECTOR* p_send[6];
1151 DWORD i;
1153 /** init temporary register */
1154 memset(R, 0, 12 * sizeof(WINED3DSHADERVECTOR));
1156 /* vshader_program_parse(vshader); */
1157 #if 0 /* Must not be 1 in cvs */
1158 TRACE("Input:\n");
1159 TRACE_VSVECTOR(This->data->C[0]);
1160 TRACE_VSVECTOR(This->data->C[1]);
1161 TRACE_VSVECTOR(This->data->C[2]);
1162 TRACE_VSVECTOR(This->data->C[3]);
1163 TRACE_VSVECTOR(This->data->C[4]);
1164 TRACE_VSVECTOR(This->data->C[5]);
1165 TRACE_VSVECTOR(This->data->C[6]);
1166 TRACE_VSVECTOR(This->data->C[7]);
1167 TRACE_VSVECTOR(This->data->C[8]);
1168 TRACE_VSVECTOR(This->data->C[64]);
1169 TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
1170 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
1171 TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
1172 TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
1173 TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
1174 TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
1175 TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
1176 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
1177 TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
1178 #endif
1180 TRACE_VSVECTOR(vshader->data->C[64]);
1181 /* TODO: Run through all the tokens and find and labels, if, endifs, loops etc...., and make a labels list */
1183 /* the first dword is the version tag */
1184 /* TODO: parse it */
1186 if (shader_is_vshader_version(*pToken)) { /** version */
1187 ++pToken;
1189 while (D3DVS_END() != *pToken) {
1190 if (shader_is_comment(*pToken)) { /** comment */
1191 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1192 ++pToken;
1193 pToken += comment_len;
1194 continue ;
1197 opcode_token = *pToken++;
1198 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1200 if (NULL == curOpcode) {
1201 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1202 pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1203 /* return FALSE; */
1205 } else {
1206 if (curOpcode->num_params > 0) {
1207 /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */
1208 for (i = 0; i < curOpcode->num_params; ++i) {
1209 DWORD reg = pToken[i] & D3DSP_REGNUM_MASK;
1210 DWORD regtype = shader_get_regtype(pToken[i]);
1212 switch (regtype) {
1213 case D3DSPR_TEMP:
1214 /* TRACE("p[%d]=R[%d]\n", i, reg); */
1215 p[i] = &R[reg];
1216 break;
1217 case D3DSPR_INPUT:
1218 /* TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]); */
1219 p[i] = &input->V[reg];
1220 break;
1221 case D3DSPR_CONST:
1222 if (pToken[i] & D3DVS_ADDRMODE_RELATIVE) {
1223 p[i] = &This->data->C[(DWORD) A[0].x + reg];
1224 } else {
1225 p[i] = &This->data->C[reg];
1227 break;
1228 case D3DSPR_ADDR: /* case D3DSPR_TEXTURE: */
1229 if (0 != reg) {
1230 ERR("cannot handle address registers != a0, forcing use of a0\n");
1231 reg = 0;
1233 /* TRACE("p[%d]=A[%d]\n", i, reg); */
1234 p[i] = &A[reg];
1235 break;
1236 case D3DSPR_RASTOUT:
1237 switch (reg) {
1238 case D3DSRO_POSITION:
1239 p[i] = &output->oPos;
1240 break;
1241 case D3DSRO_FOG:
1242 p[i] = &output->oFog;
1243 break;
1244 case D3DSRO_POINT_SIZE:
1245 p[i] = &output->oPts;
1246 break;
1248 break;
1249 case D3DSPR_ATTROUT:
1250 /* TRACE("p[%d]=oD[%d]\n", i, reg); */
1251 p[i] = &output->oD[reg];
1252 break;
1253 case D3DSPR_TEXCRDOUT:
1254 /* TRACE("p[%d]=oT[%d]\n", i, reg); */
1255 p[i] = &output->oT[reg];
1256 break;
1257 /* TODO Decls and defs */
1258 #if 0
1259 case D3DSPR_DCL:
1260 case D3DSPR_DEF:
1261 #endif
1262 default:
1263 break;
1266 if (i > 0) { /* input reg */
1267 DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
1268 UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
1270 if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
1271 /* TRACE("p[%d] not swizzled\n", i); */
1272 p_send[i] = p[i];
1273 } else {
1274 DWORD swizzle_x = swizzle & 0x03;
1275 DWORD swizzle_y = (swizzle >> 2) & 0x03;
1276 DWORD swizzle_z = (swizzle >> 4) & 0x03;
1277 DWORD swizzle_w = (swizzle >> 6) & 0x03;
1278 /* TRACE("p[%d] swizzled\n", i); */
1279 float* tt = (float*) p[i];
1280 s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
1281 s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
1282 s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
1283 s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
1284 p_send[i] = &s[i];
1286 } else { /* output reg */
1287 if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
1288 p_send[i] = p[i];
1289 } else {
1290 p_send[i] = &d; /* to be post-processed for modifiers management */
1296 switch (curOpcode->num_params) {
1297 case 0:
1298 curOpcode->soft_fct();
1299 break;
1300 case 1:
1301 curOpcode->soft_fct(p_send[0]);
1302 break;
1303 case 2:
1304 curOpcode->soft_fct(p_send[0], p_send[1]);
1305 break;
1306 case 3:
1307 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
1308 break;
1309 case 4:
1310 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
1311 break;
1312 case 5:
1313 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
1314 break;
1315 case 6:
1316 curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4], p_send[5]);
1317 break;
1318 default:
1319 ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
1322 /* check if output reg modifier post-process */
1323 if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
1324 if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x;
1325 if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y;
1326 if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z;
1327 if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w;
1329 #if 0
1330 TRACE_VSVECTOR(output->oPos);
1331 TRACE_VSVECTOR(output->oD[0]);
1332 TRACE_VSVECTOR(output->oD[1]);
1333 TRACE_VSVECTOR(output->oT[0]);
1334 TRACE_VSVECTOR(output->oT[1]);
1335 TRACE_VSVECTOR(R[0]);
1336 TRACE_VSVECTOR(R[1]);
1337 TRACE_VSVECTOR(R[2]);
1338 TRACE_VSVECTOR(R[3]);
1339 TRACE_VSVECTOR(R[4]);
1340 TRACE_VSVECTOR(R[5]);
1341 #endif
1343 /* to next opcode token */
1344 pToken += curOpcode->num_params;
1346 #if 0
1347 TRACE("End of current instruction:\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 TRACE_VSVECTOR(R[0]);
1354 TRACE_VSVECTOR(R[1]);
1355 TRACE_VSVECTOR(R[2]);
1356 TRACE_VSVECTOR(R[3]);
1357 TRACE_VSVECTOR(R[4]);
1358 TRACE_VSVECTOR(R[5]);
1359 #endif
1361 #if 0 /* Must not be 1 in cvs */
1362 TRACE("Output:\n");
1363 TRACE_VSVECTOR(output->oPos);
1364 TRACE_VSVECTOR(output->oD[0]);
1365 TRACE_VSVECTOR(output->oD[1]);
1366 TRACE_VSVECTOR(output->oT[0]);
1367 TRACE_VSVECTOR(output->oT[1]);
1368 #endif
1369 return WINED3D_OK;
1372 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, CONST FLOAT *pConstantData, UINT Vector4fCount) {
1373 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1374 FIXME("(%p) : stub\n", This);
1375 return WINED3D_OK;
1378 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantF(IWineD3DVertexShader *iface, UINT StartRegister, FLOAT *pConstantData, UINT Vector4fCount) {
1379 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1380 FIXME("(%p) : stub\n", This);
1381 return WINED3D_OK;
1384 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
1385 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1386 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1387 ERR("(%p) : SetVertexShaderConstantI C[%u] invalid\n", This, StartRegister);
1388 return WINED3DERR_INVALIDCALL;
1390 if (NULL == pConstantData) {
1391 return WINED3DERR_INVALIDCALL;
1393 FIXME("(%p) : stub\n", This);
1394 return WINED3D_OK;
1397 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantI(IWineD3DVertexShader *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
1398 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1399 TRACE("(%p) : C[%u] count=%u\n", This, StartRegister, Vector4iCount);
1400 if (StartRegister + Vector4iCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1401 return WINED3DERR_INVALIDCALL;
1403 if (NULL == pConstantData) {
1404 return WINED3DERR_INVALIDCALL;
1406 FIXME("(%p) : stub\n", This);
1407 return WINED3D_OK;
1410 HRESULT WINAPI IWineD3DVertexShaderImpl_SetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
1411 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1412 if (StartRegister + BoolCount > WINED3D_VSHADER_MAX_CONSTANTS) {
1413 ERR("(%p) : SetVertexShaderConstantB C[%u] invalid\n", This, StartRegister);
1414 return WINED3DERR_INVALIDCALL;
1416 if (NULL == pConstantData) {
1417 return WINED3DERR_INVALIDCALL;
1419 FIXME("(%p) : stub\n", This);
1420 return WINED3D_OK;
1423 HRESULT WINAPI IWineD3DVertexShaderImpl_GetConstantB(IWineD3DVertexShader *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
1424 IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl *)iface;
1425 FIXME("(%p) : stub\n", This);
1426 return WINED3D_OK;
1429 #endif
1431 /* *******************************************
1432 IWineD3DVertexShader IUnknown parts follow
1433 ******************************************* */
1434 HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj)
1436 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1437 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1438 if (IsEqualGUID(riid, &IID_IUnknown)
1439 || IsEqualGUID(riid, &IID_IWineD3DBase)
1440 || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1441 || IsEqualGUID(riid, &IID_IWineD3DVertexShader)) {
1442 IUnknown_AddRef(iface);
1443 *ppobj = This;
1444 return S_OK;
1446 *ppobj = NULL;
1447 return E_NOINTERFACE;
1450 ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
1451 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1452 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
1453 return InterlockedIncrement(&This->ref);
1456 ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
1457 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1458 ULONG ref;
1459 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
1460 ref = InterlockedDecrement(&This->ref);
1461 if (ref == 0) {
1462 if (This->vertexDeclaration) IWineD3DVertexDeclaration_Release(This->vertexDeclaration);
1463 HeapFree(GetProcessHeap(), 0, This);
1465 return ref;
1468 /* *******************************************
1469 IWineD3DVertexShader IWineD3DVertexShader parts follow
1470 ******************************************* */
1472 HRESULT WINAPI IWineD3DVertexShaderImpl_GetParent(IWineD3DVertexShader *iface, IUnknown** parent){
1473 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1475 *parent = This->parent;
1476 IUnknown_AddRef(*parent);
1477 TRACE("(%p) : returning %p\n", This, *parent);
1478 return WINED3D_OK;
1481 HRESULT WINAPI IWineD3DVertexShaderImpl_GetDevice(IWineD3DVertexShader* iface, IWineD3DDevice **pDevice){
1482 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
1483 IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
1484 *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
1485 TRACE("(%p) returning %p\n", This, *pDevice);
1486 return WINED3D_OK;
1489 HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* impl, VOID* pData, UINT* pSizeOfData) {
1490 IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)impl;
1491 FIXME("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
1493 if (NULL == pData) {
1494 *pSizeOfData = This->baseShader.functionLength;
1495 return WINED3D_OK;
1497 if (*pSizeOfData < This->baseShader.functionLength) {
1498 *pSizeOfData = This->baseShader.functionLength;
1499 return WINED3DERR_MOREDATA;
1501 if (NULL == This->baseShader.function) { /* no function defined */
1502 TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
1503 (*(DWORD **) pData) = NULL;
1504 } else {
1505 if(This->baseShader.functionLength == 0){
1508 TRACE("(%p) : GetFunction copying to %p\n", This, pData);
1509 memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
1511 return WINED3D_OK;
1514 HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) {
1515 IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface;
1516 const DWORD* pToken = pFunction;
1517 const SHADER_OPCODE* curOpcode = NULL;
1518 DWORD opcode_token;
1519 DWORD len = 0;
1520 DWORD i;
1521 TRACE("(%p) : Parsing programme\n", This);
1523 /* Initialise vertex input arrays */
1524 This->namedArrays = FALSE;
1525 This->declaredArrays = FALSE;
1526 for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
1527 This->arrayUsageMap[i] = -1;
1529 if (NULL != pToken) {
1530 while (D3DVS_END() != *pToken) {
1531 if (shader_is_vshader_version(*pToken)) { /** version */
1532 vshader_set_version(This, *pToken);
1533 ++pToken;
1534 ++len;
1535 continue;
1537 if (shader_is_comment(*pToken)) { /** comment */
1538 DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
1539 ++pToken;
1540 TRACE("//%s\n", (char*)pToken);
1541 pToken += comment_len;
1542 len += comment_len + 1;
1543 continue;
1546 opcode_token = *pToken++;
1547 curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token);
1548 len++;
1550 if (NULL == curOpcode) {
1551 int tokens_read;
1553 FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
1554 tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken);
1555 pToken += tokens_read;
1556 len += tokens_read;
1558 } else {
1559 if (curOpcode->opcode == D3DSIO_DCL) {
1561 DWORD usage = *pToken;
1562 DWORD param = *(pToken + 1);
1563 DWORD regtype = shader_get_regtype(param);
1565 if (regtype == D3DSPR_INPUT)
1566 vshader_parse_input_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
1567 shader_program_dump_decl_usage(usage, param);
1568 shader_dump_ins_modifiers(param);
1569 TRACE(" ");
1570 shader_dump_param((IWineD3DBaseShader*) This, param, 0, 0);
1571 pToken += 2;
1572 len += 2;
1574 } else if (curOpcode->opcode == D3DSIO_DEF) {
1576 unsigned int offset = shader_get_float_offset(*pToken);
1578 TRACE("def c%u = %f, %f, %f, %f", offset,
1579 *(float *)(pToken + 1),
1580 *(float *)(pToken + 2),
1581 *(float *)(pToken + 3),
1582 *(float *)(pToken + 4));
1584 pToken += 5;
1585 len += 5;
1587 } else if (curOpcode->opcode == D3DSIO_DEFI) {
1589 TRACE("defi i%lu = %ld, %ld, %ld, %ld", *pToken & D3DSP_REGNUM_MASK,
1590 (long) *(pToken + 1),
1591 (long) *(pToken + 2),
1592 (long) *(pToken + 3),
1593 (long) *(pToken + 4));
1595 pToken += 5;
1596 len += 5;
1598 } else if (curOpcode->opcode == D3DSIO_DEFB) {
1600 TRACE("defb b%lu = %s", *pToken & D3DSP_REGNUM_MASK,
1601 *(pToken + 1)? "true": "false");
1603 pToken += 2;
1604 len += 2;
1606 } else {
1608 DWORD param, addr_token;
1609 int tokens_read;
1611 /* Print out predication source token first - it follows
1612 * the destination token. */
1613 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1614 TRACE("(");
1615 shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
1616 TRACE(") ");
1619 TRACE("%s", curOpcode->name);
1620 if (curOpcode->num_params > 0) {
1622 /* Destination token */
1623 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1624 pToken, &param, &addr_token);
1625 pToken += tokens_read;
1626 len += tokens_read;
1628 shader_dump_ins_modifiers(param);
1629 TRACE(" ");
1630 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
1632 /* Predication token - already printed out, just skip it */
1633 if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
1634 pToken++;
1635 len++;
1638 /* Other source tokens */
1639 for (i = 1; i < curOpcode->num_params; ++i) {
1641 tokens_read = shader_get_param((IWineD3DBaseShader*) This,
1642 pToken, &param, &addr_token);
1643 pToken += tokens_read;
1644 len += tokens_read;
1646 TRACE(", ");
1647 shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 1);
1651 TRACE("\n");
1654 This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
1655 } else {
1656 This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
1659 /* Handy for debugging using numbered arrays instead of named arrays */
1660 #if 1
1661 /* TODO: using numbered arrays for software shaders makes things easier */
1662 This->declaredArrays = TRUE;
1663 #endif
1665 /* named arrays and declared arrays are mutually exclusive */
1666 if (This->declaredArrays)
1667 This->namedArrays = FALSE;
1669 /* Generate HW shader in needed */
1670 if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
1671 #if 1
1672 IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
1673 #endif
1676 /* copy the function ... because it will certainly be released by application */
1677 if (NULL != pFunction) {
1678 This->baseShader.function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
1679 memcpy((void *)This->baseShader.function, pFunction, This->baseShader.functionLength);
1680 } else {
1681 This->baseShader.function = NULL;
1683 return WINED3D_OK;
1686 const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1688 /*** IUnknown methods ***/
1689 IWineD3DVertexShaderImpl_QueryInterface,
1690 IWineD3DVertexShaderImpl_AddRef,
1691 IWineD3DVertexShaderImpl_Release,
1692 /*** IWineD3DBase methods ***/
1693 IWineD3DVertexShaderImpl_GetParent,
1694 /*** IWineD3DBaseShader methods ***/
1695 IWineD3DVertexShaderImpl_SetFunction,
1696 /*** IWineD3DVertexShader methods ***/
1697 IWineD3DVertexShaderImpl_GetDevice,
1698 IWineD3DVertexShaderImpl_GetFunction