[AMSTREAM] We don't need to define WIDL_C_INLINE_WRAPPERS here anymore.
[reactos.git] / dll / directx / wine / d3dx9_36 / effect.c
1 /*
2 * Copyright 2010 Christian Costa
3 * Copyright 2011 Rico Schüller
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "d3dx9_36_private.h"
21
22 #include <d3dcompiler.h>
23 #include <initguid.h>
24
25 /* Constants for special INT/FLOAT conversation */
26 #define INT_FLOAT_MULTI 255.0f
27 #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
28
29 static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
30
31 #define PARAMETER_FLAG_SHARED 1
32
33 #define INITIAL_POOL_SIZE 16
34
35 enum STATE_CLASS
36 {
37 SC_LIGHTENABLE,
38 SC_FVF,
39 SC_LIGHT,
40 SC_MATERIAL,
41 SC_NPATCHMODE,
42 SC_PIXELSHADER,
43 SC_RENDERSTATE,
44 SC_SETSAMPLER,
45 SC_SAMPLERSTATE,
46 SC_TEXTURE,
47 SC_TEXTURESTAGE,
48 SC_TRANSFORM,
49 SC_VERTEXSHADER,
50 SC_SHADERCONST,
51 SC_UNKNOWN,
52 };
53
54 enum MATERIAL_TYPE
55 {
56 MT_DIFFUSE,
57 MT_AMBIENT,
58 MT_SPECULAR,
59 MT_EMISSIVE,
60 MT_POWER,
61 };
62
63 enum LIGHT_TYPE
64 {
65 LT_TYPE,
66 LT_DIFFUSE,
67 LT_SPECULAR,
68 LT_AMBIENT,
69 LT_POSITION,
70 LT_DIRECTION,
71 LT_RANGE,
72 LT_FALLOFF,
73 LT_ATTENUATION0,
74 LT_ATTENUATION1,
75 LT_ATTENUATION2,
76 LT_THETA,
77 LT_PHI,
78 };
79
80 enum SHADER_CONSTANT_TYPE
81 {
82 SCT_VSFLOAT,
83 SCT_VSBOOL,
84 SCT_VSINT,
85 SCT_PSFLOAT,
86 SCT_PSBOOL,
87 SCT_PSINT,
88 };
89
90 enum STATE_TYPE
91 {
92 ST_CONSTANT,
93 ST_PARAMETER,
94 ST_FXLC,
95 ST_ARRAY_SELECTOR,
96 };
97
98 struct d3dx_object
99 {
100 UINT size;
101 void *data;
102 struct d3dx_parameter *param;
103 };
104
105 struct d3dx_state
106 {
107 UINT operation;
108 UINT index;
109 enum STATE_TYPE type;
110 struct d3dx_parameter parameter;
111 struct d3dx_parameter *referenced_param;
112 };
113
114 struct d3dx_sampler
115 {
116 UINT state_count;
117 struct d3dx_state *states;
118 };
119
120 struct d3dx_pass
121 {
122 char *name;
123 UINT state_count;
124 UINT annotation_count;
125
126 struct d3dx_state *states;
127 struct d3dx_parameter *annotations;
128
129 ULONG64 update_version;
130 };
131
132 struct d3dx_technique
133 {
134 char *name;
135 UINT pass_count;
136 UINT annotation_count;
137
138 struct d3dx_parameter *annotations;
139 struct d3dx_pass *passes;
140
141 struct IDirect3DStateBlock9 *saved_state;
142 };
143
144 struct d3dx9_base_effect
145 {
146 struct ID3DXEffectImpl *effect;
147
148 UINT parameter_count;
149 UINT technique_count;
150 UINT object_count;
151
152 struct d3dx_top_level_parameter *parameters;
153 struct d3dx_technique *techniques;
154 struct d3dx_object *objects;
155
156 struct d3dx_effect_pool *pool;
157 DWORD flags;
158
159 ULONG64 version_counter;
160 };
161
162 struct ID3DXEffectImpl
163 {
164 ID3DXEffect ID3DXEffect_iface;
165 LONG ref;
166
167 struct d3dx9_base_effect base_effect;
168
169 struct ID3DXEffectStateManager *manager;
170 struct IDirect3DDevice9 *device;
171 struct ID3DXEffectPool *pool;
172 struct d3dx_technique *active_technique;
173 struct d3dx_pass *active_pass;
174 BOOL started;
175 DWORD begin_flags;
176
177 D3DLIGHT9 current_light[8];
178 unsigned int light_updated;
179 D3DMATERIAL9 current_material;
180 BOOL material_updated;
181 };
182
183 #define INITIAL_SHARED_DATA_SIZE 4
184
185 struct d3dx_effect_pool
186 {
187 ID3DXEffectPool ID3DXEffectPool_iface;
188 LONG refcount;
189
190 struct d3dx_shared_data *shared_data;
191 unsigned int size;
192
193 ULONG64 version_counter;
194 };
195
196 struct ID3DXEffectCompilerImpl
197 {
198 ID3DXEffectCompiler ID3DXEffectCompiler_iface;
199 LONG ref;
200
201 struct d3dx9_base_effect base_effect;
202 };
203
204 static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *parameters,
205 const char *name);
206 static HRESULT d3dx9_parse_state(struct d3dx9_base_effect *base, struct d3dx_state *state,
207 const char *data, const char **ptr, struct d3dx_object *objects);
208 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
209
210 typedef BOOL (*walk_parameter_dep_func)(void *data, struct d3dx_parameter *param);
211
212 static const struct
213 {
214 enum STATE_CLASS class;
215 UINT op;
216 const char *name;
217 }
218 state_table[] =
219 {
220 /* Render states */
221 {SC_RENDERSTATE, D3DRS_ZENABLE, "D3DRS_ZENABLE"}, /* 0x0 */
222 {SC_RENDERSTATE, D3DRS_FILLMODE, "D3DRS_FILLMODE"},
223 {SC_RENDERSTATE, D3DRS_SHADEMODE, "D3DRS_SHADEMODE"},
224 {SC_RENDERSTATE, D3DRS_ZWRITEENABLE, "D3DRS_ZWRITEENABLE"},
225 {SC_RENDERSTATE, D3DRS_ALPHATESTENABLE, "D3DRS_ALPHATESTENABLE"},
226 {SC_RENDERSTATE, D3DRS_LASTPIXEL, "D3DRS_LASTPIXEL"},
227 {SC_RENDERSTATE, D3DRS_SRCBLEND, "D3DRS_SRCBLEND"},
228 {SC_RENDERSTATE, D3DRS_DESTBLEND, "D3DRS_DESTBLEND"},
229 {SC_RENDERSTATE, D3DRS_CULLMODE, "D3DRS_CULLMODE"},
230 {SC_RENDERSTATE, D3DRS_ZFUNC, "D3DRS_ZFUNC"},
231 {SC_RENDERSTATE, D3DRS_ALPHAREF, "D3DRS_ALPHAREF"},
232 {SC_RENDERSTATE, D3DRS_ALPHAFUNC, "D3DRS_ALPHAFUNC"},
233 {SC_RENDERSTATE, D3DRS_DITHERENABLE, "D3DRS_DITHERENABLE"},
234 {SC_RENDERSTATE, D3DRS_ALPHABLENDENABLE, "D3DRS_ALPHABLENDENABLE"},
235 {SC_RENDERSTATE, D3DRS_FOGENABLE, "D3DRS_FOGENABLE"},
236 {SC_RENDERSTATE, D3DRS_SPECULARENABLE, "D3DRS_SPECULARENABLE"},
237 {SC_RENDERSTATE, D3DRS_FOGCOLOR, "D3DRS_FOGCOLOR"}, /* 0x10 */
238 {SC_RENDERSTATE, D3DRS_FOGTABLEMODE, "D3DRS_FOGTABLEMODE"},
239 {SC_RENDERSTATE, D3DRS_FOGSTART, "D3DRS_FOGSTART"},
240 {SC_RENDERSTATE, D3DRS_FOGEND, "D3DRS_FOGEND"},
241 {SC_RENDERSTATE, D3DRS_FOGDENSITY, "D3DRS_FOGDENSITY"},
242 {SC_RENDERSTATE, D3DRS_RANGEFOGENABLE, "D3DRS_RANGEFOGENABLE"},
243 {SC_RENDERSTATE, D3DRS_STENCILENABLE, "D3DRS_STENCILENABLE"},
244 {SC_RENDERSTATE, D3DRS_STENCILFAIL, "D3DRS_STENCILFAIL"},
245 {SC_RENDERSTATE, D3DRS_STENCILZFAIL, "D3DRS_STENCILZFAIL"},
246 {SC_RENDERSTATE, D3DRS_STENCILPASS, "D3DRS_STENCILPASS"},
247 {SC_RENDERSTATE, D3DRS_STENCILFUNC, "D3DRS_STENCILFUNC"},
248 {SC_RENDERSTATE, D3DRS_STENCILREF, "D3DRS_STENCILREF"},
249 {SC_RENDERSTATE, D3DRS_STENCILMASK, "D3DRS_STENCILMASK"},
250 {SC_RENDERSTATE, D3DRS_STENCILWRITEMASK, "D3DRS_STENCILWRITEMASK"},
251 {SC_RENDERSTATE, D3DRS_TEXTUREFACTOR, "D3DRS_TEXTUREFACTOR"},
252 {SC_RENDERSTATE, D3DRS_WRAP0, "D3DRS_WRAP0"},
253 {SC_RENDERSTATE, D3DRS_WRAP1, "D3DRS_WRAP1"}, /* 0x20 */
254 {SC_RENDERSTATE, D3DRS_WRAP2, "D3DRS_WRAP2"},
255 {SC_RENDERSTATE, D3DRS_WRAP3, "D3DRS_WRAP3"},
256 {SC_RENDERSTATE, D3DRS_WRAP4, "D3DRS_WRAP4"},
257 {SC_RENDERSTATE, D3DRS_WRAP5, "D3DRS_WRAP5"},
258 {SC_RENDERSTATE, D3DRS_WRAP6, "D3DRS_WRAP6"},
259 {SC_RENDERSTATE, D3DRS_WRAP7, "D3DRS_WRAP7"},
260 {SC_RENDERSTATE, D3DRS_WRAP8, "D3DRS_WRAP8"},
261 {SC_RENDERSTATE, D3DRS_WRAP9, "D3DRS_WRAP9"},
262 {SC_RENDERSTATE, D3DRS_WRAP10, "D3DRS_WRAP10"},
263 {SC_RENDERSTATE, D3DRS_WRAP11, "D3DRS_WRAP11"},
264 {SC_RENDERSTATE, D3DRS_WRAP12, "D3DRS_WRAP12"},
265 {SC_RENDERSTATE, D3DRS_WRAP13, "D3DRS_WRAP13"},
266 {SC_RENDERSTATE, D3DRS_WRAP14, "D3DRS_WRAP14"},
267 {SC_RENDERSTATE, D3DRS_WRAP15, "D3DRS_WRAP15"},
268 {SC_RENDERSTATE, D3DRS_CLIPPING, "D3DRS_CLIPPING"},
269 {SC_RENDERSTATE, D3DRS_LIGHTING, "D3DRS_LIGHTING"}, /* 0x30 */
270 {SC_RENDERSTATE, D3DRS_AMBIENT, "D3DRS_AMBIENT"},
271 {SC_RENDERSTATE, D3DRS_FOGVERTEXMODE, "D3DRS_FOGVERTEXMODE"},
272 {SC_RENDERSTATE, D3DRS_COLORVERTEX, "D3DRS_COLORVERTEX"},
273 {SC_RENDERSTATE, D3DRS_LOCALVIEWER, "D3DRS_LOCALVIEWER"},
274 {SC_RENDERSTATE, D3DRS_NORMALIZENORMALS, "D3DRS_NORMALIZENORMALS"},
275 {SC_RENDERSTATE, D3DRS_DIFFUSEMATERIALSOURCE, "D3DRS_DIFFUSEMATERIALSOURCE"},
276 {SC_RENDERSTATE, D3DRS_SPECULARMATERIALSOURCE, "D3DRS_SPECULARMATERIALSOURCE"},
277 {SC_RENDERSTATE, D3DRS_AMBIENTMATERIALSOURCE, "D3DRS_AMBIENTMATERIALSOURCE"},
278 {SC_RENDERSTATE, D3DRS_EMISSIVEMATERIALSOURCE, "D3DRS_EMISSIVEMATERIALSOURCE"},
279 {SC_RENDERSTATE, D3DRS_VERTEXBLEND, "D3DRS_VERTEXBLEND"},
280 {SC_RENDERSTATE, D3DRS_CLIPPLANEENABLE, "D3DRS_CLIPPLANEENABLE"},
281 {SC_RENDERSTATE, D3DRS_POINTSIZE, "D3DRS_POINTSIZE"},
282 {SC_RENDERSTATE, D3DRS_POINTSIZE_MIN, "D3DRS_POINTSIZE_MIN"},
283 {SC_RENDERSTATE, D3DRS_POINTSIZE_MAX, "D3DRS_POINTSIZE_MAX"},
284 {SC_RENDERSTATE, D3DRS_POINTSPRITEENABLE, "D3DRS_POINTSPRITEENABLE"},
285 {SC_RENDERSTATE, D3DRS_POINTSCALEENABLE, "D3DRS_POINTSCALEENABLE"}, /* 0x40 */
286 {SC_RENDERSTATE, D3DRS_POINTSCALE_A, "D3DRS_POINTSCALE_A"},
287 {SC_RENDERSTATE, D3DRS_POINTSCALE_B, "D3DRS_POINTSCALE_B"},
288 {SC_RENDERSTATE, D3DRS_POINTSCALE_C, "D3DRS_POINTSCALE_C"},
289 {SC_RENDERSTATE, D3DRS_MULTISAMPLEANTIALIAS, "D3DRS_MULTISAMPLEANTIALIAS"},
290 {SC_RENDERSTATE, D3DRS_MULTISAMPLEMASK, "D3DRS_MULTISAMPLEMASK"},
291 {SC_RENDERSTATE, D3DRS_PATCHEDGESTYLE, "D3DRS_PATCHEDGESTYLE"},
292 {SC_RENDERSTATE, D3DRS_DEBUGMONITORTOKEN, "D3DRS_DEBUGMONITORTOKEN"},
293 {SC_RENDERSTATE, D3DRS_INDEXEDVERTEXBLENDENABLE, "D3DRS_INDEXEDVERTEXBLENDENABLE"},
294 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE, "D3DRS_COLORWRITEENABLE"},
295 {SC_RENDERSTATE, D3DRS_TWEENFACTOR, "D3DRS_TWEENFACTOR"},
296 {SC_RENDERSTATE, D3DRS_BLENDOP, "D3DRS_BLENDOP"},
297 {SC_RENDERSTATE, D3DRS_POSITIONDEGREE, "D3DRS_POSITIONDEGREE"},
298 {SC_RENDERSTATE, D3DRS_NORMALDEGREE, "D3DRS_NORMALDEGREE"},
299 {SC_RENDERSTATE, D3DRS_SCISSORTESTENABLE, "D3DRS_SCISSORTESTENABLE"},
300 {SC_RENDERSTATE, D3DRS_SLOPESCALEDEPTHBIAS, "D3DRS_SLOPESCALEDEPTHBIAS"},
301 {SC_RENDERSTATE, D3DRS_ANTIALIASEDLINEENABLE, "D3DRS_ANTIALIASEDLINEENABLE"}, /* 0x50 */
302 {SC_RENDERSTATE, D3DRS_MINTESSELLATIONLEVEL, "D3DRS_MINTESSELLATIONLEVEL"},
303 {SC_RENDERSTATE, D3DRS_MAXTESSELLATIONLEVEL, "D3DRS_MAXTESSELLATIONLEVEL"},
304 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_X, "D3DRS_ADAPTIVETESS_X"},
305 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Y, "D3DRS_ADAPTIVETESS_Y"},
306 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Z, "D3DRS_ADAPTIVETESS_Z"},
307 {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_W, "D3DRS_ADAPTIVETESS_W"},
308 {SC_RENDERSTATE, D3DRS_ENABLEADAPTIVETESSELLATION, "D3DRS_ENABLEADAPTIVETESSELLATION"},
309 {SC_RENDERSTATE, D3DRS_TWOSIDEDSTENCILMODE, "D3DRS_TWOSIDEDSTENCILMODE"},
310 {SC_RENDERSTATE, D3DRS_CCW_STENCILFAIL, "D3DRS_CCW_STENCILFAIL"},
311 {SC_RENDERSTATE, D3DRS_CCW_STENCILZFAIL, "D3DRS_CCW_STENCILZFAIL"},
312 {SC_RENDERSTATE, D3DRS_CCW_STENCILPASS, "D3DRS_CCW_STENCILPASS"},
313 {SC_RENDERSTATE, D3DRS_CCW_STENCILFUNC, "D3DRS_CCW_STENCILFUNC"},
314 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE1, "D3DRS_COLORWRITEENABLE1"},
315 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE2, "D3DRS_COLORWRITEENABLE2"},
316 {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE3, "D3DRS_COLORWRITEENABLE3"},
317 {SC_RENDERSTATE, D3DRS_BLENDFACTOR, "D3DRS_BLENDFACTOR"}, /* 0x60 */
318 {SC_RENDERSTATE, D3DRS_SRGBWRITEENABLE, "D3DRS_SRGBWRITEENABLE"},
319 {SC_RENDERSTATE, D3DRS_DEPTHBIAS, "D3DRS_DEPTHBIAS"},
320 {SC_RENDERSTATE, D3DRS_SEPARATEALPHABLENDENABLE, "D3DRS_SEPARATEALPHABLENDENABLE"},
321 {SC_RENDERSTATE, D3DRS_SRCBLENDALPHA, "D3DRS_SRCBLENDALPHA"},
322 {SC_RENDERSTATE, D3DRS_DESTBLENDALPHA, "D3DRS_DESTBLENDALPHA"},
323 {SC_RENDERSTATE, D3DRS_BLENDOPALPHA, "D3DRS_BLENDOPALPHA"},
324 /* Texture stages */
325 {SC_TEXTURESTAGE, D3DTSS_COLOROP, "D3DTSS_COLOROP"},
326 {SC_TEXTURESTAGE, D3DTSS_COLORARG0, "D3DTSS_COLORARG0"},
327 {SC_TEXTURESTAGE, D3DTSS_COLORARG1, "D3DTSS_COLORARG1"},
328 {SC_TEXTURESTAGE, D3DTSS_COLORARG2, "D3DTSS_COLORARG2"},
329 {SC_TEXTURESTAGE, D3DTSS_ALPHAOP, "D3DTSS_ALPHAOP"},
330 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG0, "D3DTSS_ALPHAARG0"},
331 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG1, "D3DTSS_ALPHAARG1"},
332 {SC_TEXTURESTAGE, D3DTSS_ALPHAARG2, "D3DTSS_ALPHAARG2"},
333 {SC_TEXTURESTAGE, D3DTSS_RESULTARG, "D3DTSS_RESULTARG"},
334 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT00, "D3DTSS_BUMPENVMAT00"}, /* 0x70 */
335 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT01, "D3DTSS_BUMPENVMAT01"},
336 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT10, "D3DTSS_BUMPENVMAT10"},
337 {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT11, "D3DTSS_BUMPENVMAT11"},
338 {SC_TEXTURESTAGE, D3DTSS_TEXCOORDINDEX, "D3DTSS_TEXCOORDINDEX"},
339 {SC_TEXTURESTAGE, D3DTSS_BUMPENVLSCALE, "D3DTSS_BUMPENVLSCALE"},
340 {SC_TEXTURESTAGE, D3DTSS_BUMPENVLOFFSET, "D3DTSS_BUMPENVLOFFSET"},
341 {SC_TEXTURESTAGE, D3DTSS_TEXTURETRANSFORMFLAGS, "D3DTSS_TEXTURETRANSFORMFLAGS"},
342 {SC_TEXTURESTAGE, D3DTSS_CONSTANT, "D3DTSS_CONSTANT"},
343 /* NPatchMode */
344 {SC_NPATCHMODE, 0, "NPatchMode"},
345 /* FVF */
346 {SC_FVF, 0, "FVF"},
347 /* Transform */
348 {SC_TRANSFORM, D3DTS_PROJECTION, "D3DTS_PROJECTION"},
349 {SC_TRANSFORM, D3DTS_VIEW, "D3DTS_VIEW"},
350 {SC_TRANSFORM, D3DTS_WORLD, "D3DTS_WORLD"},
351 {SC_TRANSFORM, D3DTS_TEXTURE0, "D3DTS_TEXTURE0"},
352 /* Material */
353 {SC_MATERIAL, MT_DIFFUSE, "MaterialDiffuse"},
354 {SC_MATERIAL, MT_AMBIENT, "MaterialAmbient"}, /* 0x80 */
355 {SC_MATERIAL, MT_SPECULAR, "MaterialSpecular"},
356 {SC_MATERIAL, MT_EMISSIVE, "MaterialEmissive"},
357 {SC_MATERIAL, MT_POWER, "MaterialPower"},
358 /* Light */
359 {SC_LIGHT, LT_TYPE, "LightType"},
360 {SC_LIGHT, LT_DIFFUSE, "LightDiffuse"},
361 {SC_LIGHT, LT_SPECULAR, "LightSpecular"},
362 {SC_LIGHT, LT_AMBIENT, "LightAmbient"},
363 {SC_LIGHT, LT_POSITION, "LightPosition"},
364 {SC_LIGHT, LT_DIRECTION, "LightDirection"},
365 {SC_LIGHT, LT_RANGE, "LightRange"},
366 {SC_LIGHT, LT_FALLOFF, "LightFallOff"},
367 {SC_LIGHT, LT_ATTENUATION0, "LightAttenuation0"},
368 {SC_LIGHT, LT_ATTENUATION1, "LightAttenuation1"},
369 {SC_LIGHT, LT_ATTENUATION2, "LightAttenuation2"},
370 {SC_LIGHT, LT_THETA, "LightTheta"},
371 {SC_LIGHT, LT_PHI, "LightPhi"}, /* 0x90 */
372 /* Lightenable */
373 {SC_LIGHTENABLE, 0, "LightEnable"},
374 /* Vertexshader */
375 {SC_VERTEXSHADER, 0, "Vertexshader"},
376 /* Pixelshader */
377 {SC_PIXELSHADER, 0, "Pixelshader"},
378 /* Shader constants */
379 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstantF"},
380 {SC_SHADERCONST, SCT_VSBOOL, "VertexShaderConstantB"},
381 {SC_SHADERCONST, SCT_VSINT, "VertexShaderConstantI"},
382 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant"},
383 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant1"},
384 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant2"},
385 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant3"},
386 {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant4"},
387 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstantF"},
388 {SC_SHADERCONST, SCT_PSBOOL, "PixelShaderConstantB"},
389 {SC_SHADERCONST, SCT_PSINT, "PixelShaderConstantI"},
390 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant"},
391 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant1"}, /* 0xa0 */
392 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant2"},
393 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant3"},
394 {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant4"},
395 /* Texture */
396 {SC_TEXTURE, 0, "Texture"},
397 /* Sampler states */
398 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSU, "AddressU"},
399 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSV, "AddressV"},
400 {SC_SAMPLERSTATE, D3DSAMP_ADDRESSW, "AddressW"},
401 {SC_SAMPLERSTATE, D3DSAMP_BORDERCOLOR, "BorderColor"},
402 {SC_SAMPLERSTATE, D3DSAMP_MAGFILTER, "MagFilter"},
403 {SC_SAMPLERSTATE, D3DSAMP_MINFILTER, "MinFilter"},
404 {SC_SAMPLERSTATE, D3DSAMP_MIPFILTER, "MipFilter"},
405 {SC_SAMPLERSTATE, D3DSAMP_MIPMAPLODBIAS, "MipMapLodBias"},
406 {SC_SAMPLERSTATE, D3DSAMP_MAXMIPLEVEL, "MaxMipLevel"},
407 {SC_SAMPLERSTATE, D3DSAMP_MAXANISOTROPY, "MaxAnisotropy"},
408 {SC_SAMPLERSTATE, D3DSAMP_SRGBTEXTURE, "SRGBTexture"},
409 {SC_SAMPLERSTATE, D3DSAMP_ELEMENTINDEX, "ElementIndex"}, /* 0xb0 */
410 {SC_SAMPLERSTATE, D3DSAMP_DMAPOFFSET, "DMAPOffset"},
411 /* Set sampler */
412 {SC_SETSAMPLER, 0, "Sampler"},
413 };
414
415 static inline void read_dword(const char **ptr, DWORD *d)
416 {
417 memcpy(d, *ptr, sizeof(*d));
418 *ptr += sizeof(*d);
419 }
420
421 static void skip_dword_unknown(const char **ptr, unsigned int count)
422 {
423 unsigned int i;
424 DWORD d;
425
426 WARN("Skipping %u unknown DWORDs:\n", count);
427 for (i = 0; i < count; ++i)
428 {
429 read_dword(ptr, &d);
430 WARN("\t0x%08x\n", d);
431 }
432 }
433
434 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
435 {
436 return (D3DXHANDLE)parameter;
437 }
438
439 static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
440 {
441 return (D3DXHANDLE)technique;
442 }
443
444 static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
445 {
446 return (D3DXHANDLE)pass;
447 }
448
449 static struct d3dx_technique *get_technique_by_name(struct d3dx9_base_effect *base, const char *name)
450 {
451 UINT i;
452
453 if (!name) return NULL;
454
455 for (i = 0; i < base->technique_count; ++i)
456 {
457 if (!strcmp(base->techniques[i].name, name))
458 return &base->techniques[i];
459 }
460
461 return NULL;
462 }
463
464 static struct d3dx_technique *get_valid_technique(struct d3dx9_base_effect *base, D3DXHANDLE technique)
465 {
466 unsigned int i;
467
468 for (i = 0; i < base->technique_count; ++i)
469 {
470 if (get_technique_handle(&base->techniques[i]) == technique)
471 return &base->techniques[i];
472 }
473
474 return get_technique_by_name(base, technique);
475 }
476
477 static struct d3dx_pass *get_valid_pass(struct d3dx9_base_effect *base, D3DXHANDLE pass)
478 {
479 unsigned int i, k;
480
481 for (i = 0; i < base->technique_count; ++i)
482 {
483 struct d3dx_technique *technique = &base->techniques[i];
484
485 for (k = 0; k < technique->pass_count; ++k)
486 {
487 if (get_pass_handle(&technique->passes[k]) == pass)
488 return &technique->passes[k];
489 }
490 }
491
492 return NULL;
493 }
494
495 static struct d3dx_parameter *get_valid_parameter(struct d3dx9_base_effect *base, D3DXHANDLE parameter)
496 {
497 struct d3dx_parameter *handle_param = (struct d3dx_parameter *)parameter;
498
499 if (handle_param && !strncmp(handle_param->magic_string, parameter_magic_string,
500 sizeof(parameter_magic_string)))
501 return handle_param;
502
503 return base->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(base, NULL, parameter);
504 }
505
506 static void free_state(struct d3dx_state *state)
507 {
508 free_parameter(&state->parameter, FALSE, FALSE);
509 }
510
511 static void free_object(struct d3dx_object *object)
512 {
513 HeapFree(GetProcessHeap(), 0, object->data);
514 }
515
516 static void free_sampler(struct d3dx_sampler *sampler)
517 {
518 UINT i;
519
520 for (i = 0; i < sampler->state_count; ++i)
521 {
522 free_state(&sampler->states[i]);
523 }
524 HeapFree(GetProcessHeap(), 0, sampler->states);
525 }
526
527 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param);
528
529 static void free_parameter_data(struct d3dx_parameter *param, BOOL child)
530 {
531 if (!param->data)
532 return;
533 if (param->class == D3DXPC_OBJECT && !param->element_count)
534 {
535 switch (param->type)
536 {
537 case D3DXPT_STRING:
538 HeapFree(GetProcessHeap(), 0, *(char **)param->data);
539 break;
540
541 case D3DXPT_TEXTURE:
542 case D3DXPT_TEXTURE1D:
543 case D3DXPT_TEXTURE2D:
544 case D3DXPT_TEXTURE3D:
545 case D3DXPT_TEXTURECUBE:
546 case D3DXPT_PIXELSHADER:
547 case D3DXPT_VERTEXSHADER:
548 if (*(IUnknown **)param->data) IUnknown_Release(*(IUnknown **)param->data);
549 break;
550
551 case D3DXPT_SAMPLER:
552 case D3DXPT_SAMPLER1D:
553 case D3DXPT_SAMPLER2D:
554 case D3DXPT_SAMPLER3D:
555 case D3DXPT_SAMPLERCUBE:
556 free_sampler((struct d3dx_sampler *)param->data);
557 break;
558
559 default:
560 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
561 break;
562 }
563 }
564 if (!child)
565 HeapFree(GetProcessHeap(), 0, param->data);
566 }
567
568 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child)
569 {
570 unsigned int i;
571
572 TRACE("Free parameter %p, name %s, type %s, element %#x, child %#x.\n", param, param->name,
573 debug_d3dxparameter_type(param->type), element, child);
574
575 if (param->param_eval)
576 d3dx_free_param_eval(param->param_eval);
577
578 if (param->members)
579 {
580 unsigned int count = param->element_count ? param->element_count : param->member_count;
581
582 for (i = 0; i < count; ++i)
583 free_parameter(&param->members[i], param->element_count != 0, TRUE);
584 HeapFree(GetProcessHeap(), 0, param->members);
585 }
586
587 free_parameter_data(param, child);
588
589 /* only the parent has to release name and semantic */
590 if (!element)
591 {
592 HeapFree(GetProcessHeap(), 0, param->name);
593 HeapFree(GetProcessHeap(), 0, param->semantic);
594 }
595 }
596
597 static void free_top_level_parameter(struct d3dx_top_level_parameter *param)
598 {
599 if (param->annotations)
600 {
601 unsigned int i;
602
603 for (i = 0; i < param->annotation_count; ++i)
604 free_parameter(&param->annotations[i], FALSE, FALSE);
605 HeapFree(GetProcessHeap(), 0, param->annotations);
606 }
607 d3dx_pool_release_shared_parameter(param);
608 free_parameter(&param->param, FALSE, FALSE);
609 }
610
611 static void free_pass(struct d3dx_pass *pass)
612 {
613 unsigned int i;
614
615 TRACE("Free pass %p\n", pass);
616
617 if (!pass)
618 return;
619
620 if (pass->annotations)
621 {
622 for (i = 0; i < pass->annotation_count; ++i)
623 free_parameter(&pass->annotations[i], FALSE, FALSE);
624 HeapFree(GetProcessHeap(), 0, pass->annotations);
625 pass->annotations = NULL;
626 }
627
628 if (pass->states)
629 {
630 for (i = 0; i < pass->state_count; ++i)
631 free_state(&pass->states[i]);
632 HeapFree(GetProcessHeap(), 0, pass->states);
633 pass->states = NULL;
634 }
635
636 HeapFree(GetProcessHeap(), 0, pass->name);
637 pass->name = NULL;
638 }
639
640 static void free_technique(struct d3dx_technique *technique)
641 {
642 unsigned int i;
643
644 TRACE("Free technique %p\n", technique);
645
646 if (!technique)
647 return;
648
649 if (technique->saved_state)
650 {
651 IDirect3DStateBlock9_Release(technique->saved_state);
652 technique->saved_state = NULL;
653 }
654
655 if (technique->annotations)
656 {
657 for (i = 0; i < technique->annotation_count; ++i)
658 free_parameter(&technique->annotations[i], FALSE, FALSE);
659 HeapFree(GetProcessHeap(), 0, technique->annotations);
660 technique->annotations = NULL;
661 }
662
663 if (technique->passes)
664 {
665 for (i = 0; i < technique->pass_count; ++i)
666 free_pass(&technique->passes[i]);
667 HeapFree(GetProcessHeap(), 0, technique->passes);
668 technique->passes = NULL;
669 }
670
671 HeapFree(GetProcessHeap(), 0, technique->name);
672 technique->name = NULL;
673 }
674
675 static void d3dx9_base_effect_cleanup(struct d3dx9_base_effect *base)
676 {
677 unsigned int i;
678
679 TRACE("base %p.\n", base);
680
681 if (base->parameters)
682 {
683 for (i = 0; i < base->parameter_count; ++i)
684 free_top_level_parameter(&base->parameters[i]);
685 HeapFree(GetProcessHeap(), 0, base->parameters);
686 base->parameters = NULL;
687 }
688
689 if (base->techniques)
690 {
691 for (i = 0; i < base->technique_count; ++i)
692 free_technique(&base->techniques[i]);
693 HeapFree(GetProcessHeap(), 0, base->techniques);
694 base->techniques = NULL;
695 }
696
697 if (base->objects)
698 {
699 for (i = 0; i < base->object_count; ++i)
700 {
701 free_object(&base->objects[i]);
702 }
703 HeapFree(GetProcessHeap(), 0, base->objects);
704 base->objects = NULL;
705 }
706 }
707
708 static void free_effect(struct ID3DXEffectImpl *effect)
709 {
710 TRACE("Free effect %p\n", effect);
711
712 d3dx9_base_effect_cleanup(&effect->base_effect);
713
714 if (effect->pool)
715 {
716 effect->pool->lpVtbl->Release(effect->pool);
717 }
718
719 if (effect->manager)
720 {
721 IUnknown_Release(effect->manager);
722 }
723
724 IDirect3DDevice9_Release(effect->device);
725 }
726
727 static void free_effect_compiler(struct ID3DXEffectCompilerImpl *compiler)
728 {
729 TRACE("Free effect compiler %p\n", compiler);
730
731 d3dx9_base_effect_cleanup(&compiler->base_effect);
732 }
733
734 static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector)
735 {
736 UINT i;
737
738 for (i = 0; i < 4; ++i)
739 {
740 if (i < param->columns)
741 set_number((FLOAT *)vector + i, D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
742 else
743 ((FLOAT *)vector)[i] = 0.0f;
744 }
745 }
746
747 static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector)
748 {
749 UINT i;
750
751 for (i = 0; i < param->columns; ++i)
752 {
753 set_number((FLOAT *)param->data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
754 }
755 }
756
757 static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose)
758 {
759 UINT i, k;
760
761 for (i = 0; i < 4; ++i)
762 {
763 for (k = 0; k < 4; ++k)
764 {
765 FLOAT *tmp = transpose ? (FLOAT *)&matrix->u.m[k][i] : (FLOAT *)&matrix->u.m[i][k];
766
767 if ((i < param->rows) && (k < param->columns))
768 set_number(tmp, D3DXPT_FLOAT, (DWORD *)param->data + i * param->columns + k, param->type);
769 else
770 *tmp = 0.0f;
771 }
772 }
773 }
774
775 static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
776 {
777 UINT i, k;
778
779 if (param->type == D3DXPT_FLOAT)
780 {
781 if (param->columns == 4)
782 memcpy(param->data, matrix->u.m, param->rows * 4 * sizeof(float));
783 else
784 for (i = 0; i < param->rows; ++i)
785 memcpy((float *)param->data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
786 return;
787 }
788
789 for (i = 0; i < param->rows; ++i)
790 {
791 for (k = 0; k < param->columns; ++k)
792 {
793 set_number((FLOAT *)param->data + i * param->columns + k, param->type,
794 &matrix->u.m[i][k], D3DXPT_FLOAT);
795 }
796 }
797 }
798
799 static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
800 {
801 UINT i, k;
802
803 for (i = 0; i < param->rows; ++i)
804 {
805 for (k = 0; k < param->columns; ++k)
806 {
807 set_number((FLOAT *)param->data + i * param->columns + k, param->type,
808 &matrix->u.m[k][i], D3DXPT_FLOAT);
809 }
810 }
811 }
812
813 static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_parameter *parameter, const char *name)
814 {
815 UINT element;
816 struct d3dx_parameter *temp_parameter;
817 const char *part;
818
819 TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
820
821 if (!name || !*name) return NULL;
822
823 element = atoi(name);
824 part = strchr(name, ']') + 1;
825
826 /* check for empty [] && element range */
827 if ((part - name) > 1 && parameter->element_count > element)
828 {
829 temp_parameter = &parameter->members[element];
830
831 switch (*part++)
832 {
833 case '.':
834 return get_parameter_by_name(NULL, temp_parameter, part);
835
836 case '\0':
837 TRACE("Returning parameter %p\n", temp_parameter);
838 return temp_parameter;
839
840 default:
841 FIXME("Unhandled case \"%c\"\n", *--part);
842 break;
843 }
844 }
845
846 TRACE("Parameter not found\n");
847 return NULL;
848 }
849
850 static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *annotations,
851 const char *name)
852 {
853 UINT i, length;
854 struct d3dx_parameter *temp_parameter;
855 const char *part;
856
857 TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
858
859 if (!name || !*name) return NULL;
860
861 length = strcspn( name, "[.@" );
862 part = name + length;
863
864 for (i = 0; i < count; ++i)
865 {
866 temp_parameter = &annotations[i];
867
868 if (!strcmp(temp_parameter->name, name))
869 {
870 TRACE("Returning annotation %p\n", temp_parameter);
871 return temp_parameter;
872 }
873 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
874 {
875 switch (*part++)
876 {
877 case '.':
878 return get_parameter_by_name(NULL, temp_parameter, part);
879
880 case '[':
881 return get_parameter_element_by_name(temp_parameter, part);
882
883 default:
884 FIXME("Unhandled case \"%c\"\n", *--part);
885 break;
886 }
887 }
888 }
889
890 TRACE("Annotation not found\n");
891 return NULL;
892 }
893
894 struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base,
895 struct d3dx_parameter *parameter, const char *name)
896 {
897 UINT i, count, length;
898 struct d3dx_parameter *temp_parameter;
899 const char *part;
900
901 TRACE("base %p, parameter %p, name %s\n", base, parameter, debugstr_a(name));
902
903 if (!name || !*name) return NULL;
904
905 count = parameter ? parameter->member_count : base->parameter_count;
906 length = strcspn( name, "[.@" );
907 part = name + length;
908
909 for (i = 0; i < count; i++)
910 {
911 temp_parameter = !parameter ? &base->parameters[i].param
912 : &parameter->members[i];
913
914 if (!strcmp(temp_parameter->name, name))
915 {
916 TRACE("Returning parameter %p\n", temp_parameter);
917 return temp_parameter;
918 }
919 else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
920 {
921 switch (*part++)
922 {
923 case '.':
924 return get_parameter_by_name(NULL, temp_parameter, part);
925
926 case '@':
927 {
928 struct d3dx_top_level_parameter *top_param
929 = top_level_parameter_from_parameter(temp_parameter);
930
931 return parameter ? NULL : get_annotation_by_name(top_param->annotation_count,
932 top_param->annotations, part);
933 }
934 case '[':
935 return get_parameter_element_by_name(temp_parameter, part);
936
937 default:
938 FIXME("Unhandled case \"%c\"\n", *--part);
939 break;
940 }
941 }
942 }
943
944 TRACE("Parameter not found\n");
945 return NULL;
946 }
947
948 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
949 {
950 return (0xfeff0000 | ((major) << 8) | (minor));
951 }
952
953 static HRESULT d3dx9_base_effect_get_desc(struct d3dx9_base_effect *base, D3DXEFFECT_DESC *desc)
954 {
955 if (!desc)
956 {
957 WARN("Invalid argument specified.\n");
958 return D3DERR_INVALIDCALL;
959 }
960
961 FIXME("partial stub!\n");
962
963 /* TODO: add creator and function count. */
964 desc->Creator = NULL;
965 desc->Functions = 0;
966 desc->Parameters = base->parameter_count;
967 desc->Techniques = base->technique_count;
968
969 return D3D_OK;
970 }
971
972 static HRESULT d3dx9_base_effect_get_parameter_desc(struct d3dx9_base_effect *base,
973 D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
974 {
975 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
976
977 if (!desc || !param)
978 {
979 WARN("Invalid argument specified.\n");
980 return D3DERR_INVALIDCALL;
981 }
982
983 desc->Name = param->name;
984 desc->Semantic = param->semantic;
985 desc->Class = param->class;
986 desc->Type = param->type;
987 desc->Rows = param->rows;
988 desc->Columns = param->columns;
989 desc->Elements = param->element_count;
990 desc->Annotations = is_top_level_parameter(param)
991 ? top_level_parameter_from_parameter(param)->annotation_count : 0;
992 desc->StructMembers = param->member_count;
993 desc->Flags = param->flags;
994 desc->Bytes = param->bytes;
995
996 return D3D_OK;
997 }
998
999 static HRESULT d3dx9_base_effect_get_technique_desc(struct d3dx9_base_effect *base,
1000 D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
1001 {
1002 struct d3dx_technique *tech = technique ? get_valid_technique(base, technique) : &base->techniques[0];
1003
1004 if (!desc || !tech)
1005 {
1006 WARN("Invalid argument specified.\n");
1007 return D3DERR_INVALIDCALL;
1008 }
1009
1010 desc->Name = tech->name;
1011 desc->Passes = tech->pass_count;
1012 desc->Annotations = tech->annotation_count;
1013
1014 return D3D_OK;
1015 }
1016
1017 static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_state *state,
1018 void **param_value, struct d3dx_parameter **out_param,
1019 BOOL update_all, BOOL *param_dirty)
1020 {
1021 struct d3dx_parameter *param = &state->parameter;
1022
1023 *param_value = NULL;
1024 *out_param = NULL;
1025 *param_dirty = FALSE;
1026
1027 switch (state->type)
1028 {
1029 case ST_PARAMETER:
1030 param = state->referenced_param;
1031 *param_dirty = is_param_dirty(param, pass->update_version);
1032 /* fallthrough */
1033 case ST_CONSTANT:
1034 *out_param = param;
1035 *param_value = param->data;
1036 return D3D_OK;
1037 case ST_ARRAY_SELECTOR:
1038 {
1039 unsigned int array_idx;
1040 static const struct d3dx_parameter array_idx_param =
1041 {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1042 HRESULT hr;
1043 struct d3dx_parameter *ref_param, *selected_param;
1044
1045 if (!param->param_eval)
1046 {
1047 FIXME("Preshader structure is null.\n");
1048 return D3DERR_INVALIDCALL;
1049 }
1050 /* We override with the update_version of the pass because we want
1051 * to force index recomputation and check for out of bounds. */
1052 if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1053 {
1054 if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1055 return hr;
1056 }
1057 else
1058 {
1059 array_idx = state->index;
1060 }
1061 ref_param = state->referenced_param;
1062 TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1063 ref_param->element_count);
1064 /* According to the tests, native d3dx handles the case of array index evaluated to -1
1065 * in a specific way, always selecting first array element and not returning error. */
1066 if (array_idx == ~0u)
1067 {
1068 WARN("Array index is -1, setting to 0.\n");
1069 array_idx = 0;
1070 }
1071
1072 if (array_idx >= ref_param->element_count)
1073 {
1074 WARN("Computed array index %u is larger than array size %u.\n",
1075 array_idx, ref_param->element_count);
1076 return E_FAIL;
1077 }
1078 selected_param = &ref_param->members[array_idx];
1079 *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1080 state->index = array_idx;
1081
1082 *param_value = selected_param->data;
1083 *out_param = selected_param;
1084 return D3D_OK;
1085 }
1086 case ST_FXLC:
1087 if (param->param_eval)
1088 {
1089 *out_param = param;
1090 *param_value = param->data;
1091 /* We check with the update_version of the pass because the
1092 * same preshader might be used by both the vertex and the
1093 * pixel shader (that can happen e.g. for sampler states). */
1094 if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1095 {
1096 *param_dirty = TRUE;
1097 return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1098 }
1099 else
1100 return D3D_OK;
1101 }
1102 else
1103 {
1104 FIXME("No preshader for FXLC parameter.\n");
1105 return D3DERR_INVALIDCALL;
1106 }
1107 }
1108 return E_NOTIMPL;
1109 }
1110
1111 static HRESULT d3dx9_base_effect_get_pass_desc(struct d3dx9_base_effect *base,
1112 D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
1113 {
1114 struct d3dx_pass *pass = get_valid_pass(base, pass_handle);
1115 unsigned int i;
1116
1117 if (!desc || !pass)
1118 {
1119 WARN("Invalid argument specified.\n");
1120 return D3DERR_INVALIDCALL;
1121 }
1122
1123 desc->Name = pass->name;
1124 desc->Annotations = pass->annotation_count;
1125
1126 desc->pVertexShaderFunction = NULL;
1127 desc->pPixelShaderFunction = NULL;
1128
1129 if (base->flags & D3DXFX_NOT_CLONEABLE)
1130 return D3D_OK;
1131
1132 for (i = 0; i < pass->state_count; ++i)
1133 {
1134 struct d3dx_state *state = &pass->states[i];
1135
1136 if (state_table[state->operation].class == SC_VERTEXSHADER
1137 || state_table[state->operation].class == SC_PIXELSHADER)
1138 {
1139 struct d3dx_parameter *param;
1140 void *param_value;
1141 BOOL param_dirty;
1142 HRESULT hr;
1143
1144 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
1145 FALSE, &param_dirty)))
1146 return hr;
1147
1148 if (!param->object_id)
1149 {
1150 FIXME("Zero object ID in shader parameter.\n");
1151 return E_FAIL;
1152 }
1153
1154 if (state_table[state->operation].class == SC_VERTEXSHADER)
1155 desc->pVertexShaderFunction = base->objects[param->object_id].data;
1156 else
1157 desc->pPixelShaderFunction = base->objects[param->object_id].data;
1158 }
1159 }
1160
1161 return D3D_OK;
1162 }
1163
1164 static HRESULT d3dx9_base_effect_get_function_desc(struct d3dx9_base_effect *base,
1165 D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
1166 {
1167 FIXME("stub!\n");
1168
1169 return E_NOTIMPL;
1170 }
1171
1172 static D3DXHANDLE d3dx9_base_effect_get_parameter(struct d3dx9_base_effect *base,
1173 D3DXHANDLE parameter, UINT index)
1174 {
1175 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1176
1177 if (!parameter)
1178 {
1179 if (index < base->parameter_count)
1180 {
1181 TRACE("Returning parameter %p.\n", &base->parameters[index]);
1182 return get_parameter_handle(&base->parameters[index].param);
1183 }
1184 }
1185 else
1186 {
1187 if (param && !param->element_count && index < param->member_count)
1188 {
1189 TRACE("Returning parameter %p.\n", &param->members[index]);
1190 return get_parameter_handle(&param->members[index]);
1191 }
1192 }
1193
1194 WARN("Parameter not found.\n");
1195
1196 return NULL;
1197 }
1198
1199 static D3DXHANDLE d3dx9_base_effect_get_parameter_by_name(struct d3dx9_base_effect *base,
1200 D3DXHANDLE parameter, const char *name)
1201 {
1202 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1203 D3DXHANDLE handle;
1204
1205 if (!name)
1206 {
1207 handle = get_parameter_handle(param);
1208 TRACE("Returning parameter %p.\n", handle);
1209 return handle;
1210 }
1211
1212 handle = get_parameter_handle(get_parameter_by_name(base, param, name));
1213 TRACE("Returning parameter %p.\n", handle);
1214
1215 return handle;
1216 }
1217
1218 static D3DXHANDLE d3dx9_base_effect_get_parameter_by_semantic(struct d3dx9_base_effect *base,
1219 D3DXHANDLE parameter, const char *semantic)
1220 {
1221 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1222 struct d3dx_parameter *temp_param;
1223 UINT i;
1224
1225 if (!parameter)
1226 {
1227 for (i = 0; i < base->parameter_count; ++i)
1228 {
1229 temp_param = &base->parameters[i].param;
1230
1231 if (!temp_param->semantic)
1232 {
1233 if (!semantic)
1234 {
1235 TRACE("Returning parameter %p\n", temp_param);
1236 return get_parameter_handle(temp_param);
1237 }
1238 continue;
1239 }
1240
1241 if (!strcasecmp(temp_param->semantic, semantic))
1242 {
1243 TRACE("Returning parameter %p\n", temp_param);
1244 return get_parameter_handle(temp_param);
1245 }
1246 }
1247 }
1248 else if (param)
1249 {
1250 for (i = 0; i < param->member_count; ++i)
1251 {
1252 temp_param = &param->members[i];
1253
1254 if (!temp_param->semantic)
1255 {
1256 if (!semantic)
1257 {
1258 TRACE("Returning parameter %p\n", temp_param);
1259 return get_parameter_handle(temp_param);
1260 }
1261 continue;
1262 }
1263
1264 if (!strcasecmp(temp_param->semantic, semantic))
1265 {
1266 TRACE("Returning parameter %p\n", temp_param);
1267 return get_parameter_handle(temp_param);
1268 }
1269 }
1270 }
1271
1272 WARN("Parameter not found.\n");
1273
1274 return NULL;
1275 }
1276
1277 static D3DXHANDLE d3dx9_base_effect_get_parameter_element(struct d3dx9_base_effect *base,
1278 D3DXHANDLE parameter, UINT index)
1279 {
1280 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1281
1282 if (!param)
1283 {
1284 if (index < base->parameter_count)
1285 {
1286 TRACE("Returning parameter %p.\n", &base->parameters[index]);
1287 return get_parameter_handle(&base->parameters[index].param);
1288 }
1289 }
1290 else
1291 {
1292 if (index < param->element_count)
1293 {
1294 TRACE("Returning parameter %p.\n", &param->members[index]);
1295 return get_parameter_handle(&param->members[index]);
1296 }
1297 }
1298
1299 WARN("Parameter not found.\n");
1300
1301 return NULL;
1302 }
1303
1304 static D3DXHANDLE d3dx9_base_effect_get_technique(struct d3dx9_base_effect *base, UINT index)
1305 {
1306 if (index >= base->technique_count)
1307 {
1308 WARN("Invalid argument specified.\n");
1309 return NULL;
1310 }
1311
1312 TRACE("Returning technique %p.\n", &base->techniques[index]);
1313
1314 return get_technique_handle(&base->techniques[index]);
1315 }
1316
1317 static D3DXHANDLE d3dx9_base_effect_get_technique_by_name(struct d3dx9_base_effect *base, const char *name)
1318 {
1319 struct d3dx_technique *tech = get_technique_by_name(base, name);
1320
1321 if (tech)
1322 {
1323 D3DXHANDLE t = get_technique_handle(tech);
1324 TRACE("Returning technique %p\n", t);
1325 return t;
1326 }
1327
1328 WARN("Technique not found.\n");
1329
1330 return NULL;
1331 }
1332
1333 static D3DXHANDLE d3dx9_base_effect_get_pass(struct d3dx9_base_effect *base,
1334 D3DXHANDLE technique, UINT index)
1335 {
1336 struct d3dx_technique *tech = get_valid_technique(base, technique);
1337
1338 if (tech && index < tech->pass_count)
1339 {
1340 TRACE("Returning pass %p\n", &tech->passes[index]);
1341 return get_pass_handle(&tech->passes[index]);
1342 }
1343
1344 WARN("Pass not found.\n");
1345
1346 return NULL;
1347 }
1348
1349 static D3DXHANDLE d3dx9_base_effect_get_pass_by_name(struct d3dx9_base_effect *base,
1350 D3DXHANDLE technique, const char *name)
1351 {
1352 struct d3dx_technique *tech = get_valid_technique(base, technique);
1353
1354 if (tech && name)
1355 {
1356 unsigned int i;
1357
1358 for (i = 0; i < tech->pass_count; ++i)
1359 {
1360 struct d3dx_pass *pass = &tech->passes[i];
1361
1362 if (!strcmp(pass->name, name))
1363 {
1364 TRACE("Returning pass %p\n", pass);
1365 return get_pass_handle(pass);
1366 }
1367 }
1368 }
1369
1370 WARN("Pass not found.\n");
1371
1372 return NULL;
1373 }
1374
1375 static D3DXHANDLE d3dx9_base_effect_get_function(struct d3dx9_base_effect *base, UINT index)
1376 {
1377 FIXME("stub!\n");
1378
1379 return NULL;
1380 }
1381
1382 static D3DXHANDLE d3dx9_base_effect_get_function_by_name(struct d3dx9_base_effect *base, const char *name)
1383 {
1384 FIXME("stub!\n");
1385
1386 return NULL;
1387 }
1388
1389 static UINT get_annotation_from_object(struct d3dx9_base_effect *base,
1390 D3DXHANDLE object, struct d3dx_parameter **annotations)
1391 {
1392 struct d3dx_parameter *param = get_valid_parameter(base, object);
1393 struct d3dx_pass *pass = get_valid_pass(base, object);
1394 struct d3dx_technique *technique = get_valid_technique(base, object);
1395
1396 if (pass)
1397 {
1398 *annotations = pass->annotations;
1399 return pass->annotation_count;
1400 }
1401 else if (technique)
1402 {
1403 *annotations = technique->annotations;
1404 return technique->annotation_count;
1405 }
1406 else if (param)
1407 {
1408 if (is_top_level_parameter(param))
1409 {
1410 struct d3dx_top_level_parameter *top_param
1411 = top_level_parameter_from_parameter(param);
1412
1413 *annotations = top_param->annotations;
1414 return top_param->annotation_count;
1415 }
1416 else
1417 {
1418 *annotations = NULL;
1419 return 0;
1420 }
1421 }
1422 else
1423 {
1424 FIXME("Functions are not handled, yet!\n");
1425 return 0;
1426 }
1427 }
1428
1429 static D3DXHANDLE d3dx9_base_effect_get_annotation(struct d3dx9_base_effect *base,
1430 D3DXHANDLE object, UINT index)
1431 {
1432 struct d3dx_parameter *annotations = NULL;
1433 UINT annotation_count = 0;
1434
1435 annotation_count = get_annotation_from_object(base, object, &annotations);
1436
1437 if (index < annotation_count)
1438 {
1439 TRACE("Returning parameter %p\n", &annotations[index]);
1440 return get_parameter_handle(&annotations[index]);
1441 }
1442
1443 WARN("Annotation not found.\n");
1444
1445 return NULL;
1446 }
1447
1448 static D3DXHANDLE d3dx9_base_effect_get_annotation_by_name(struct d3dx9_base_effect *base,
1449 D3DXHANDLE object, const char *name)
1450 {
1451 struct d3dx_parameter *annotation = NULL;
1452 struct d3dx_parameter *annotations = NULL;
1453 UINT annotation_count = 0;
1454
1455 if (!name)
1456 {
1457 WARN("Invalid argument specified\n");
1458 return NULL;
1459 }
1460
1461 annotation_count = get_annotation_from_object(base, object, &annotations);
1462
1463 annotation = get_annotation_by_name(annotation_count, annotations, name);
1464 if (annotation)
1465 {
1466 TRACE("Returning parameter %p\n", annotation);
1467 return get_parameter_handle(annotation);
1468 }
1469
1470 WARN("Annotation not found.\n");
1471
1472 return NULL;
1473 }
1474
1475 static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
1476 void *data)
1477 {
1478 unsigned int i;
1479 unsigned int member_count;
1480
1481 if (param_func(data, param))
1482 return TRUE;
1483
1484 member_count = param->element_count ? param->element_count : param->member_count;
1485 for (i = 0; i < member_count; ++i)
1486 {
1487 if (walk_parameter_tree(&param->members[i], param_func, data))
1488 return TRUE;
1489 }
1490 return FALSE;
1491 }
1492
1493 static ULONG64 *get_version_counter_ptr(struct d3dx9_base_effect *base)
1494 {
1495 return base->pool ? &base->pool->version_counter : &base->version_counter;
1496 }
1497
1498 static ULONG64 next_effect_update_version(struct d3dx9_base_effect *base)
1499 {
1500 return next_update_version(get_version_counter_ptr(base));
1501 }
1502
1503 static void set_dirty(struct d3dx_parameter *param)
1504 {
1505 struct d3dx_shared_data *shared_data;
1506 struct d3dx_top_level_parameter *top_param = param->top_level_param;
1507 ULONG64 new_update_version = next_update_version(top_param->version_counter);
1508
1509 if ((shared_data = top_param->shared_data))
1510 shared_data->update_version = new_update_version;
1511 else
1512 top_param->update_version = new_update_version;
1513 }
1514
1515 static HRESULT set_string(char **param_data, const char *string)
1516 {
1517 HeapFree(GetProcessHeap(), 0, *param_data);
1518 *param_data = HeapAlloc(GetProcessHeap(), 0, strlen(string) + 1);
1519 if (!*param_data)
1520 {
1521 ERR("Out of memory.\n");
1522 return E_OUTOFMEMORY;
1523 }
1524 strcpy(*param_data, string);
1525 return D3D_OK;
1526 }
1527
1528 static HRESULT d3dx9_base_effect_set_value(struct d3dx9_base_effect *base,
1529 D3DXHANDLE parameter, const void *data, UINT bytes)
1530 {
1531 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1532 unsigned int i;
1533
1534 if (!param)
1535 {
1536 WARN("Invalid parameter %p specified\n", parameter);
1537 return D3DERR_INVALIDCALL;
1538 }
1539
1540 /* samplers don't touch data */
1541 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
1542 {
1543 TRACE("Sampler: returning E_FAIL\n");
1544 return E_FAIL;
1545 }
1546
1547 if (data && param->bytes <= bytes)
1548 {
1549 switch (param->type)
1550 {
1551 case D3DXPT_TEXTURE:
1552 case D3DXPT_TEXTURE1D:
1553 case D3DXPT_TEXTURE2D:
1554 case D3DXPT_TEXTURE3D:
1555 case D3DXPT_TEXTURECUBE:
1556 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
1557 {
1558 IUnknown *unk = ((IUnknown **)data)[i];
1559 if (unk)
1560 IUnknown_AddRef(unk);
1561
1562 unk = ((IUnknown **)param->data)[i];
1563 if (unk)
1564 IUnknown_Release(unk);
1565 }
1566 /* fallthrough */
1567 case D3DXPT_VOID:
1568 case D3DXPT_BOOL:
1569 case D3DXPT_INT:
1570 case D3DXPT_FLOAT:
1571 TRACE("Copy %u bytes.\n", param->bytes);
1572 memcpy(param->data, data, param->bytes);
1573 set_dirty(param);
1574 break;
1575
1576 case D3DXPT_STRING:
1577 {
1578 HRESULT hr;
1579
1580 set_dirty(param);
1581 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
1582 {
1583 if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i])))
1584 return hr;
1585 }
1586 break;
1587 }
1588
1589 default:
1590 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
1591 break;
1592 }
1593
1594 return D3D_OK;
1595 }
1596
1597 WARN("Invalid argument specified\n");
1598
1599 return D3DERR_INVALIDCALL;
1600 }
1601
1602 static HRESULT d3dx9_base_effect_get_value(struct d3dx9_base_effect *base,
1603 D3DXHANDLE parameter, void *data, UINT bytes)
1604 {
1605 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1606
1607 if (!param)
1608 {
1609 WARN("Invalid parameter %p specified\n", parameter);
1610 return D3DERR_INVALIDCALL;
1611 }
1612
1613 /* samplers don't touch data */
1614 if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
1615 {
1616 TRACE("Sampler: returning E_FAIL\n");
1617 return E_FAIL;
1618 }
1619
1620 if (data && param->bytes <= bytes)
1621 {
1622 TRACE("Type %s\n", debug_d3dxparameter_type(param->type));
1623
1624 switch (param->type)
1625 {
1626 case D3DXPT_VOID:
1627 case D3DXPT_BOOL:
1628 case D3DXPT_INT:
1629 case D3DXPT_FLOAT:
1630 case D3DXPT_STRING:
1631 break;
1632
1633 case D3DXPT_VERTEXSHADER:
1634 case D3DXPT_PIXELSHADER:
1635 case D3DXPT_TEXTURE:
1636 case D3DXPT_TEXTURE1D:
1637 case D3DXPT_TEXTURE2D:
1638 case D3DXPT_TEXTURE3D:
1639 case D3DXPT_TEXTURECUBE:
1640 {
1641 UINT i;
1642
1643 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
1644 {
1645 IUnknown *unk = ((IUnknown **)param->data)[i];
1646 if (unk) IUnknown_AddRef(unk);
1647 }
1648 break;
1649 }
1650
1651 default:
1652 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
1653 break;
1654 }
1655
1656 TRACE("Copy %u bytes\n", param->bytes);
1657 memcpy(data, param->data, param->bytes);
1658 return D3D_OK;
1659 }
1660
1661 WARN("Parameter not found.\n");
1662
1663 return D3DERR_INVALIDCALL;
1664 }
1665
1666 static HRESULT d3dx9_base_effect_set_bool(struct d3dx9_base_effect *base, D3DXHANDLE parameter, BOOL b)
1667 {
1668 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1669
1670 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
1671 {
1672 set_number(param->data, param->type, &b, D3DXPT_BOOL);
1673 set_dirty(param);
1674 return D3D_OK;
1675 }
1676
1677 WARN("Parameter not found.\n");
1678
1679 return D3DERR_INVALIDCALL;
1680 }
1681
1682 static HRESULT d3dx9_base_effect_get_bool(struct d3dx9_base_effect *base, D3DXHANDLE parameter, BOOL *b)
1683 {
1684 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1685
1686 if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
1687 {
1688 set_number(b, D3DXPT_BOOL, param->data, param->type);
1689 TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
1690 return D3D_OK;
1691 }
1692
1693 WARN("Parameter not found.\n");
1694
1695 return D3DERR_INVALIDCALL;
1696 }
1697
1698 static HRESULT d3dx9_base_effect_set_bool_array(struct d3dx9_base_effect *base,
1699 D3DXHANDLE parameter, const BOOL *b, UINT count)
1700 {
1701 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1702
1703 if (param)
1704 {
1705 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1706
1707 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
1708
1709 switch (param->class)
1710 {
1711 case D3DXPC_SCALAR:
1712 case D3DXPC_VECTOR:
1713 case D3DXPC_MATRIX_ROWS:
1714 for (i = 0; i < size; ++i)
1715 {
1716 /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
1717 set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT);
1718 }
1719 set_dirty(param);
1720 return D3D_OK;
1721
1722 case D3DXPC_OBJECT:
1723 case D3DXPC_STRUCT:
1724 break;
1725
1726 default:
1727 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
1728 break;
1729 }
1730 }
1731
1732 WARN("Parameter not found.\n");
1733
1734 return D3DERR_INVALIDCALL;
1735 }
1736
1737 static HRESULT d3dx9_base_effect_get_bool_array(struct d3dx9_base_effect *base,
1738 D3DXHANDLE parameter, BOOL *b, UINT count)
1739 {
1740 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1741
1742 if (b && param && (param->class == D3DXPC_SCALAR
1743 || param->class == D3DXPC_VECTOR
1744 || param->class == D3DXPC_MATRIX_ROWS
1745 || param->class == D3DXPC_MATRIX_COLUMNS))
1746 {
1747 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1748
1749 for (i = 0; i < size; ++i)
1750 {
1751 set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
1752 }
1753 return D3D_OK;
1754 }
1755
1756 WARN("Parameter not found.\n");
1757
1758 return D3DERR_INVALIDCALL;
1759 }
1760
1761 static HRESULT d3dx9_base_effect_set_int(struct d3dx9_base_effect *base, D3DXHANDLE parameter, INT n)
1762 {
1763 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1764
1765 if (param && !param->element_count)
1766 {
1767 if (param->rows == 1 && param->columns == 1)
1768 {
1769 DWORD value;
1770
1771 set_number(&value, param->type, &n, D3DXPT_INT);
1772 if (value != *(DWORD *)param->data)
1773 set_dirty(param);
1774 *(DWORD *)param->data = value;
1775 return D3D_OK;
1776 }
1777
1778 /*
1779 * Split the value, if parameter is a vector with dimension 3 or 4.
1780 */
1781 if (param->type == D3DXPT_FLOAT &&
1782 ((param->class == D3DXPC_VECTOR && param->columns != 2) ||
1783 (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
1784 {
1785 TRACE("Vector fixup\n");
1786
1787 *(FLOAT *)param->data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
1788 ((FLOAT *)param->data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
1789 ((FLOAT *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
1790 if (param->rows * param->columns > 3)
1791 {
1792 ((FLOAT *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
1793 }
1794 set_dirty(param);
1795 return D3D_OK;
1796 }
1797 }
1798
1799 WARN("Parameter not found.\n");
1800
1801 return D3DERR_INVALIDCALL;
1802 }
1803
1804 static HRESULT d3dx9_base_effect_get_int(struct d3dx9_base_effect *base, D3DXHANDLE parameter, INT *n)
1805 {
1806 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1807
1808 if (n && param && !param->element_count)
1809 {
1810 if (param->columns == 1 && param->rows == 1)
1811 {
1812 set_number(n, D3DXPT_INT, param->data, param->type);
1813 TRACE("Returning %i\n", *n);
1814 return D3D_OK;
1815 }
1816
1817 if (param->type == D3DXPT_FLOAT &&
1818 ((param->class == D3DXPC_VECTOR && param->columns != 2)
1819 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
1820 {
1821 TRACE("Vector fixup\n");
1822
1823 /* all components (3,4) are clamped (0,255) and put in the INT */
1824 *n = (INT)(min(max(0.0f, *((FLOAT *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI);
1825 *n += ((INT)(min(max(0.0f, *((FLOAT *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
1826 *n += ((INT)(min(max(0.0f, *((FLOAT *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
1827 if (param->columns * param->rows > 3)
1828 {
1829 *n += ((INT)(min(max(0.0f, *((FLOAT *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
1830 }
1831
1832 TRACE("Returning %i\n", *n);
1833 return D3D_OK;
1834 }
1835 }
1836
1837 WARN("Parameter not found.\n");
1838
1839 return D3DERR_INVALIDCALL;
1840 }
1841
1842 static HRESULT d3dx9_base_effect_set_int_array(struct d3dx9_base_effect *base,
1843 D3DXHANDLE parameter, const INT *n, UINT count)
1844 {
1845 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1846
1847 if (param)
1848 {
1849 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1850
1851 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
1852
1853 switch (param->class)
1854 {
1855 case D3DXPC_SCALAR:
1856 case D3DXPC_VECTOR:
1857 case D3DXPC_MATRIX_ROWS:
1858 for (i = 0; i < size; ++i)
1859 {
1860 set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT);
1861 }
1862 set_dirty(param);
1863 return D3D_OK;
1864
1865 case D3DXPC_OBJECT:
1866 case D3DXPC_STRUCT:
1867 break;
1868
1869 default:
1870 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
1871 break;
1872 }
1873 }
1874
1875 WARN("Parameter not found.\n");
1876
1877 return D3DERR_INVALIDCALL;
1878 }
1879
1880 static HRESULT d3dx9_base_effect_get_int_array(struct d3dx9_base_effect *base,
1881 D3DXHANDLE parameter, INT *n, UINT count)
1882 {
1883 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1884
1885 if (n && param && (param->class == D3DXPC_SCALAR
1886 || param->class == D3DXPC_VECTOR
1887 || param->class == D3DXPC_MATRIX_ROWS
1888 || param->class == D3DXPC_MATRIX_COLUMNS))
1889 {
1890 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1891
1892 for (i = 0; i < size; ++i)
1893 {
1894 set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
1895 }
1896 return D3D_OK;
1897 }
1898
1899 WARN("Parameter not found.\n");
1900
1901 return D3DERR_INVALIDCALL;
1902 }
1903
1904 static HRESULT d3dx9_base_effect_set_float(struct d3dx9_base_effect *base, D3DXHANDLE parameter, float f)
1905 {
1906 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1907
1908 if (param && !param->element_count && param->rows == 1 && param->columns == 1)
1909 {
1910 DWORD value;
1911
1912 set_number(&value, param->type, &f, D3DXPT_FLOAT);
1913 if (value != *(DWORD *)param->data)
1914 set_dirty(param);
1915 *(DWORD *)param->data = value;
1916 return D3D_OK;
1917 }
1918
1919 WARN("Parameter not found.\n");
1920
1921 return D3DERR_INVALIDCALL;
1922 }
1923
1924 static HRESULT d3dx9_base_effect_get_float(struct d3dx9_base_effect *base, D3DXHANDLE parameter, float *f)
1925 {
1926 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1927
1928 if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
1929 {
1930 set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
1931 TRACE("Returning %f\n", *f);
1932 return D3D_OK;
1933 }
1934
1935 WARN("Parameter not found.\n");
1936
1937 return D3DERR_INVALIDCALL;
1938 }
1939
1940 static HRESULT d3dx9_base_effect_set_float_array(struct d3dx9_base_effect *base,
1941 D3DXHANDLE parameter, const float *f, UINT count)
1942 {
1943 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1944
1945 if (param)
1946 {
1947 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1948
1949 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
1950
1951 switch (param->class)
1952 {
1953 case D3DXPC_SCALAR:
1954 case D3DXPC_VECTOR:
1955 case D3DXPC_MATRIX_ROWS:
1956 for (i = 0; i < size; ++i)
1957 {
1958 set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT);
1959 }
1960 set_dirty(param);
1961 return D3D_OK;
1962
1963 case D3DXPC_OBJECT:
1964 case D3DXPC_STRUCT:
1965 break;
1966
1967 default:
1968 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
1969 break;
1970 }
1971 }
1972
1973 WARN("Parameter not found.\n");
1974
1975 return D3DERR_INVALIDCALL;
1976 }
1977
1978 static HRESULT d3dx9_base_effect_get_float_array(struct d3dx9_base_effect *base,
1979 D3DXHANDLE parameter, float *f, UINT count)
1980 {
1981 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
1982
1983 if (f && param && (param->class == D3DXPC_SCALAR
1984 || param->class == D3DXPC_VECTOR
1985 || param->class == D3DXPC_MATRIX_ROWS
1986 || param->class == D3DXPC_MATRIX_COLUMNS))
1987 {
1988 UINT i, size = min(count, param->bytes / sizeof(DWORD));
1989
1990 for (i = 0; i < size; ++i)
1991 {
1992 set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
1993 }
1994 return D3D_OK;
1995 }
1996
1997 WARN("Parameter not found.\n");
1998
1999 return D3DERR_INVALIDCALL;
2000 }
2001
2002 static HRESULT d3dx9_base_effect_set_vector(struct d3dx9_base_effect *base,
2003 D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2004 {
2005 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2006
2007 if (param && !param->element_count)
2008 {
2009 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2010
2011 switch (param->class)
2012 {
2013 case D3DXPC_SCALAR:
2014 case D3DXPC_VECTOR:
2015 set_dirty(param);
2016 if (param->type == D3DXPT_INT && param->bytes == 4)
2017 {
2018 DWORD tmp;
2019
2020 TRACE("INT fixup\n");
2021 tmp = (DWORD)(max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI);
2022 tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2023 tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2024 tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2025
2026 *(INT *)param->data = tmp;
2027 return D3D_OK;
2028 }
2029 if (param->type == D3DXPT_FLOAT)
2030 {
2031 memcpy(param->data, vector, param->columns * sizeof(float));
2032 return D3D_OK;
2033 }
2034
2035 set_vector(param, vector);
2036 return D3D_OK;
2037
2038 case D3DXPC_MATRIX_ROWS:
2039 case D3DXPC_OBJECT:
2040 case D3DXPC_STRUCT:
2041 break;
2042
2043 default:
2044 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2045 break;
2046 }
2047 }
2048
2049 WARN("Parameter not found.\n");
2050
2051 return D3DERR_INVALIDCALL;
2052 }
2053
2054 static HRESULT d3dx9_base_effect_get_vector(struct d3dx9_base_effect *base,
2055 D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2056 {
2057 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2058
2059 if (vector && param && !param->element_count)
2060 {
2061 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2062
2063 switch (param->class)
2064 {
2065 case D3DXPC_SCALAR:
2066 case D3DXPC_VECTOR:
2067 if (param->type == D3DXPT_INT && param->bytes == 4)
2068 {
2069 TRACE("INT fixup\n");
2070 vector->x = (((*(INT *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2071 vector->y = (((*(INT *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2072 vector->z = ((*(INT *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2073 vector->w = (((*(INT *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2074 return D3D_OK;
2075 }
2076 get_vector(param, vector);
2077 return D3D_OK;
2078
2079 case D3DXPC_MATRIX_ROWS:
2080 case D3DXPC_OBJECT:
2081 case D3DXPC_STRUCT:
2082 break;
2083
2084 default:
2085 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2086 break;
2087 }
2088 }
2089
2090 WARN("Parameter not found.\n");
2091
2092 return D3DERR_INVALIDCALL;
2093 }
2094
2095 static HRESULT d3dx9_base_effect_set_vector_array(struct d3dx9_base_effect *base,
2096 D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count)
2097 {
2098 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2099
2100 if (param && param->element_count && param->element_count >= count)
2101 {
2102 UINT i;
2103
2104 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2105
2106 switch (param->class)
2107 {
2108 case D3DXPC_VECTOR:
2109 set_dirty(param);
2110 if (param->type == D3DXPT_FLOAT)
2111 {
2112 if (param->columns == 4)
2113 memcpy(param->data, vector, count * 4 * sizeof(float));
2114 else
2115 for (i = 0; i < count; ++i)
2116 memcpy((float *)param->data + param->columns * i, vector + i,
2117 param->columns * sizeof(float));
2118 return D3D_OK;
2119 }
2120
2121 for (i = 0; i < count; ++i)
2122 {
2123 set_vector(&param->members[i], &vector[i]);
2124 }
2125 return D3D_OK;
2126
2127 case D3DXPC_SCALAR:
2128 case D3DXPC_MATRIX_ROWS:
2129 case D3DXPC_OBJECT:
2130 case D3DXPC_STRUCT:
2131 break;
2132
2133 default:
2134 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2135 break;
2136 }
2137 }
2138
2139 WARN("Parameter not found.\n");
2140
2141 return D3DERR_INVALIDCALL;
2142 }
2143
2144 static HRESULT d3dx9_base_effect_get_vector_array(struct d3dx9_base_effect *base,
2145 D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
2146 {
2147 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2148
2149 if (!count) return D3D_OK;
2150
2151 if (vector && param && count <= param->element_count)
2152 {
2153 UINT i;
2154
2155 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2156
2157 switch (param->class)
2158 {
2159 case D3DXPC_VECTOR:
2160 for (i = 0; i < count; ++i)
2161 {
2162 get_vector(&param->members[i], &vector[i]);
2163 }
2164 return D3D_OK;
2165
2166 case D3DXPC_SCALAR:
2167 case D3DXPC_MATRIX_ROWS:
2168 case D3DXPC_OBJECT:
2169 case D3DXPC_STRUCT:
2170 break;
2171
2172 default:
2173 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2174 break;
2175 }
2176 }
2177
2178 WARN("Parameter not found.\n");
2179
2180 return D3DERR_INVALIDCALL;
2181 }
2182
2183 static HRESULT d3dx9_base_effect_set_matrix(struct d3dx9_base_effect *base,
2184 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
2185 {
2186 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2187
2188 if (param && !param->element_count)
2189 {
2190 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2191
2192 switch (param->class)
2193 {
2194 case D3DXPC_MATRIX_ROWS:
2195 set_matrix(param, matrix);
2196 set_dirty(param);
2197 return D3D_OK;
2198
2199 case D3DXPC_SCALAR:
2200 case D3DXPC_VECTOR:
2201 case D3DXPC_OBJECT:
2202 case D3DXPC_STRUCT:
2203 break;
2204
2205 default:
2206 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2207 break;
2208 }
2209 }
2210
2211 WARN("Parameter not found.\n");
2212
2213 return D3DERR_INVALIDCALL;
2214 }
2215
2216 static HRESULT d3dx9_base_effect_get_matrix(struct d3dx9_base_effect *base,
2217 D3DXHANDLE parameter, D3DXMATRIX *matrix)
2218 {
2219 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2220
2221 if (matrix && param && !param->element_count)
2222 {
2223 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2224
2225 switch (param->class)
2226 {
2227 case D3DXPC_MATRIX_ROWS:
2228 get_matrix(param, matrix, FALSE);
2229 return D3D_OK;
2230
2231 case D3DXPC_SCALAR:
2232 case D3DXPC_VECTOR:
2233 case D3DXPC_OBJECT:
2234 case D3DXPC_STRUCT:
2235 break;
2236
2237 default:
2238 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2239 break;
2240 }
2241 }
2242
2243 WARN("Parameter not found.\n");
2244
2245 return D3DERR_INVALIDCALL;
2246 }
2247
2248 static HRESULT d3dx9_base_effect_set_matrix_array(struct d3dx9_base_effect *base,
2249 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
2250 {
2251 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2252
2253 if (param && param->element_count >= count)
2254 {
2255 UINT i;
2256
2257 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2258
2259 switch (param->class)
2260 {
2261 case D3DXPC_MATRIX_ROWS:
2262 set_dirty(param);
2263 for (i = 0; i < count; ++i)
2264 {
2265 set_matrix(&param->members[i], &matrix[i]);
2266 }
2267 return D3D_OK;
2268
2269 case D3DXPC_SCALAR:
2270 case D3DXPC_VECTOR:
2271 case D3DXPC_OBJECT:
2272 case D3DXPC_STRUCT:
2273 break;
2274
2275 default:
2276 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2277 break;
2278 }
2279 }
2280
2281 WARN("Parameter not found.\n");
2282
2283 return D3DERR_INVALIDCALL;
2284 }
2285
2286 static HRESULT d3dx9_base_effect_get_matrix_array(struct d3dx9_base_effect *base,
2287 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
2288 {
2289 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2290
2291 if (!count) return D3D_OK;
2292
2293 if (matrix && param && count <= param->element_count)
2294 {
2295 UINT i;
2296
2297 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2298
2299 switch (param->class)
2300 {
2301 case D3DXPC_MATRIX_ROWS:
2302 for (i = 0; i < count; ++i)
2303 {
2304 get_matrix(&param->members[i], &matrix[i], FALSE);
2305 }
2306 return D3D_OK;
2307
2308 case D3DXPC_SCALAR:
2309 case D3DXPC_VECTOR:
2310 case D3DXPC_OBJECT:
2311 case D3DXPC_STRUCT:
2312 break;
2313
2314 default:
2315 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2316 break;
2317 }
2318 }
2319
2320 WARN("Parameter not found.\n");
2321
2322 return D3DERR_INVALIDCALL;
2323 }
2324
2325 static HRESULT d3dx9_base_effect_set_matrix_pointer_array(struct d3dx9_base_effect *base,
2326 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
2327 {
2328 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2329
2330 if (param && count <= param->element_count)
2331 {
2332 UINT i;
2333
2334 switch (param->class)
2335 {
2336 case D3DXPC_MATRIX_ROWS:
2337 set_dirty(param);
2338 for (i = 0; i < count; ++i)
2339 {
2340 set_matrix(&param->members[i], matrix[i]);
2341 }
2342 return D3D_OK;
2343
2344 case D3DXPC_SCALAR:
2345 case D3DXPC_VECTOR:
2346 case D3DXPC_OBJECT:
2347 break;
2348
2349 default:
2350 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2351 break;
2352 }
2353 }
2354
2355 WARN("Parameter not found.\n");
2356
2357 return D3DERR_INVALIDCALL;
2358 }
2359
2360 static HRESULT d3dx9_base_effect_get_matrix_pointer_array(struct d3dx9_base_effect *base,
2361 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
2362 {
2363 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2364
2365 if (!count) return D3D_OK;
2366
2367 if (param && matrix && count <= param->element_count)
2368 {
2369 UINT i;
2370
2371 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2372
2373 switch (param->class)
2374 {
2375 case D3DXPC_MATRIX_ROWS:
2376 for (i = 0; i < count; ++i)
2377 {
2378 get_matrix(&param->members[i], matrix[i], FALSE);
2379 }
2380 return D3D_OK;
2381
2382 case D3DXPC_SCALAR:
2383 case D3DXPC_VECTOR:
2384 case D3DXPC_OBJECT:
2385 break;
2386
2387 default:
2388 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2389 break;
2390 }
2391 }
2392
2393 WARN("Parameter not found.\n");
2394
2395 return D3DERR_INVALIDCALL;
2396 }
2397
2398 static HRESULT d3dx9_base_effect_set_matrix_transpose(struct d3dx9_base_effect *base,
2399 D3DXHANDLE parameter, const D3DXMATRIX *matrix)
2400 {
2401 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2402
2403 if (param && !param->element_count)
2404 {
2405 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2406
2407 switch (param->class)
2408 {
2409 case D3DXPC_MATRIX_ROWS:
2410 set_dirty(param);
2411 set_matrix_transpose(param, matrix);
2412 return D3D_OK;
2413
2414 case D3DXPC_SCALAR:
2415 case D3DXPC_VECTOR:
2416 case D3DXPC_OBJECT:
2417 case D3DXPC_STRUCT:
2418 break;
2419
2420 default:
2421 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2422 break;
2423 }
2424 }
2425
2426 WARN("Parameter not found.\n");
2427
2428 return D3DERR_INVALIDCALL;
2429 }
2430
2431 static HRESULT d3dx9_base_effect_get_matrix_transpose(struct d3dx9_base_effect *base,
2432 D3DXHANDLE parameter, D3DXMATRIX *matrix)
2433 {
2434 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2435
2436 if (matrix && param && !param->element_count)
2437 {
2438 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2439
2440 switch (param->class)
2441 {
2442 case D3DXPC_SCALAR:
2443 case D3DXPC_VECTOR:
2444 get_matrix(param, matrix, FALSE);
2445 return D3D_OK;
2446
2447 case D3DXPC_MATRIX_ROWS:
2448 get_matrix(param, matrix, TRUE);
2449 return D3D_OK;
2450
2451 case D3DXPC_OBJECT:
2452 case D3DXPC_STRUCT:
2453 break;
2454
2455 default:
2456 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2457 break;
2458 }
2459 }
2460
2461 WARN("Parameter not found.\n");
2462
2463 return D3DERR_INVALIDCALL;
2464 }
2465
2466 static HRESULT d3dx9_base_effect_set_matrix_transpose_array(struct d3dx9_base_effect *base,
2467 D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
2468 {
2469 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2470
2471 if (param && param->element_count >= count)
2472 {
2473 UINT i;
2474
2475 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2476
2477 switch (param->class)
2478 {
2479 case D3DXPC_MATRIX_ROWS:
2480 set_dirty(param);
2481 for (i = 0; i < count; ++i)
2482 {
2483 set_matrix_transpose(&param->members[i], &matrix[i]);
2484 }
2485 return D3D_OK;
2486
2487 case D3DXPC_SCALAR:
2488 case D3DXPC_VECTOR:
2489 case D3DXPC_OBJECT:
2490 case D3DXPC_STRUCT:
2491 break;
2492
2493 default:
2494 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2495 break;
2496 }
2497 }
2498
2499 WARN("Parameter not found.\n");
2500
2501 return D3DERR_INVALIDCALL;
2502 }
2503
2504 static HRESULT d3dx9_base_effect_get_matrix_transpose_array(struct d3dx9_base_effect *base,
2505 D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
2506 {
2507 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2508
2509 if (!count) return D3D_OK;
2510
2511 if (matrix && param && count <= param->element_count)
2512 {
2513 UINT i;
2514
2515 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2516
2517 switch (param->class)
2518 {
2519 case D3DXPC_MATRIX_ROWS:
2520 for (i = 0; i < count; ++i)
2521 {
2522 get_matrix(&param->members[i], &matrix[i], TRUE);
2523 }
2524 return D3D_OK;
2525
2526 case D3DXPC_SCALAR:
2527 case D3DXPC_VECTOR:
2528 case D3DXPC_OBJECT:
2529 case D3DXPC_STRUCT:
2530 break;
2531
2532 default:
2533 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2534 break;
2535 }
2536 }
2537
2538 WARN("Parameter not found.\n");
2539
2540 return D3DERR_INVALIDCALL;
2541 }
2542
2543 static HRESULT d3dx9_base_effect_set_matrix_transpose_pointer_array(struct d3dx9_base_effect *base,
2544 D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
2545 {
2546 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2547
2548 if (param && count <= param->element_count)
2549 {
2550 UINT i;
2551
2552 switch (param->class)
2553 {
2554 case D3DXPC_MATRIX_ROWS:
2555 set_dirty(param);
2556 for (i = 0; i < count; ++i)
2557 {
2558 set_matrix_transpose(&param->members[i], matrix[i]);
2559 }
2560 return D3D_OK;
2561
2562 case D3DXPC_SCALAR:
2563 case D3DXPC_VECTOR:
2564 case D3DXPC_OBJECT:
2565 break;
2566
2567 default:
2568 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2569 break;
2570 }
2571 }
2572
2573 WARN("Parameter not found.\n");
2574
2575 return D3DERR_INVALIDCALL;
2576 }
2577
2578 static HRESULT d3dx9_base_effect_get_matrix_transpose_pointer_array(struct d3dx9_base_effect *base,
2579 D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
2580 {
2581 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2582
2583 if (!count) return D3D_OK;
2584
2585 if (matrix && param && count <= param->element_count)
2586 {
2587 UINT i;
2588
2589 TRACE("Class %s\n", debug_d3dxparameter_class(param->class));
2590
2591 switch (param->class)
2592 {
2593 case D3DXPC_MATRIX_ROWS:
2594 for (i = 0; i < count; ++i)
2595 {
2596 get_matrix(&param->members[i], matrix[i], TRUE);
2597 }
2598 return D3D_OK;
2599
2600 case D3DXPC_SCALAR:
2601 case D3DXPC_VECTOR:
2602 case D3DXPC_OBJECT:
2603 break;
2604
2605 default:
2606 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
2607 break;
2608 }
2609 }
2610
2611 WARN("Parameter not found.\n");
2612
2613 return D3DERR_INVALIDCALL;
2614 }
2615
2616 static HRESULT d3dx9_base_effect_set_string(struct d3dx9_base_effect *base,
2617 D3DXHANDLE parameter, const char *string)
2618 {
2619 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2620
2621 if (param && param->type == D3DXPT_STRING)
2622 {
2623 set_dirty(param);
2624 return set_string(param->data, string);
2625 }
2626
2627 WARN("Parameter not found.\n");
2628
2629 return D3DERR_INVALIDCALL;
2630 }
2631
2632 static HRESULT d3dx9_base_effect_get_string(struct d3dx9_base_effect *base,
2633 D3DXHANDLE parameter, const char **string)
2634 {
2635 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2636
2637 if (string && param && !param->element_count && param->type == D3DXPT_STRING)
2638 {
2639 *string = *(const char **)param->data;
2640 TRACE("Returning %s.\n", debugstr_a(*string));
2641 return D3D_OK;
2642 }
2643
2644 WARN("Parameter not found.\n");
2645
2646 return D3DERR_INVALIDCALL;
2647 }
2648
2649 static HRESULT d3dx9_base_effect_set_texture(struct d3dx9_base_effect *base,
2650 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture)
2651 {
2652 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2653
2654 if (param && !param->element_count &&
2655 (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
2656 || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
2657 || param->type == D3DXPT_TEXTURECUBE))
2658 {
2659 struct IDirect3DBaseTexture9 *oltexture = *(struct IDirect3DBaseTexture9 **)param->data;
2660
2661 if (texture == oltexture)
2662 return D3D_OK;
2663
2664 if (texture) IDirect3DBaseTexture9_AddRef(texture);
2665 if (oltexture) IDirect3DBaseTexture9_Release(oltexture);
2666
2667 *(struct IDirect3DBaseTexture9 **)param->data = texture;
2668 set_dirty(param);
2669
2670 return D3D_OK;
2671 }
2672
2673 WARN("Parameter not found.\n");
2674
2675 return D3DERR_INVALIDCALL;
2676 }
2677
2678 static HRESULT d3dx9_base_effect_get_texture(struct d3dx9_base_effect *base,
2679 D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture)
2680 {
2681 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2682
2683 if (texture && param && !param->element_count &&
2684 (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
2685 || param->type == D3DXPT_TEXTURE2D || param->type == D3DXPT_TEXTURE3D
2686 || param->type == D3DXPT_TEXTURECUBE))
2687 {
2688 *texture = *(struct IDirect3DBaseTexture9 **)param->data;
2689 if (*texture) IDirect3DBaseTexture9_AddRef(*texture);
2690 TRACE("Returning %p\n", *texture);
2691 return D3D_OK;
2692 }
2693
2694 WARN("Parameter not found.\n");
2695
2696 return D3DERR_INVALIDCALL;
2697 }
2698
2699 static HRESULT d3dx9_base_effect_get_pixel_shader(struct d3dx9_base_effect *base,
2700 D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader)
2701 {
2702 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2703
2704 if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
2705 {
2706 if ((*shader = *(struct IDirect3DPixelShader9 **)param->data))
2707 IDirect3DPixelShader9_AddRef(*shader);
2708 TRACE("Returning %p.\n", *shader);
2709 return D3D_OK;
2710 }
2711
2712 WARN("Parameter not found.\n");
2713
2714 return D3DERR_INVALIDCALL;
2715 }
2716
2717 static HRESULT d3dx9_base_effect_get_vertex_shader(struct d3dx9_base_effect *base,
2718 D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader)
2719 {
2720 struct d3dx_parameter *param = get_valid_parameter(base, parameter);
2721
2722 if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
2723 {
2724 if ((*shader = *(struct IDirect3DVertexShader9 **)param->data))
2725 IDirect3DVertexShader9_AddRef(*shader);
2726 TRACE("Returning %p.\n", *shader);
2727 return D3D_OK;
2728 }
2729
2730 WARN("Parameter not found.\n");
2731
2732 return D3DERR_INVALIDCALL;
2733 }
2734
2735 static HRESULT d3dx9_base_effect_set_array_range(struct d3dx9_base_effect *base,
2736 D3DXHANDLE parameter, UINT start, UINT end)
2737 {
2738 FIXME("stub!\n");
2739
2740 return E_NOTIMPL;
2741 }
2742
2743 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
2744 {
2745 static const struct
2746 {
2747 unsigned int offset;
2748 const char *name;
2749 }
2750 light_tbl[] =
2751 {
2752 {FIELD_OFFSET(D3DLIGHT9, Type), "LC_TYPE"},
2753 {FIELD_OFFSET(D3DLIGHT9, Diffuse), "LT_DIFFUSE"},
2754 {FIELD_OFFSET(D3DLIGHT9, Specular), "LT_SPECULAR"},
2755 {FIELD_OFFSET(D3DLIGHT9, Ambient), "LT_AMBIENT"},
2756 {FIELD_OFFSET(D3DLIGHT9, Position), "LT_POSITION"},
2757 {FIELD_OFFSET(D3DLIGHT9, Direction), "LT_DIRECTION"},
2758 {FIELD_OFFSET(D3DLIGHT9, Range), "LT_RANGE"},
2759 {FIELD_OFFSET(D3DLIGHT9, Falloff), "LT_FALLOFF"},
2760 {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
2761 {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
2762 {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
2763 {FIELD_OFFSET(D3DLIGHT9, Theta), "LT_THETA"},
2764 {FIELD_OFFSET(D3DLIGHT9, Phi), "LT_PHI"}
2765 };
2766 switch (op)
2767 {
2768 case LT_TYPE:
2769 TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
2770 light->Type = *(D3DLIGHTTYPE *)value;
2771 break;
2772 case LT_DIFFUSE:
2773 case LT_SPECULAR:
2774 case LT_AMBIENT:
2775 {
2776 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
2777
2778 TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
2779 *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
2780 break;
2781 }
2782 case LT_POSITION:
2783 case LT_DIRECTION:
2784 {
2785 D3DVECTOR v = *(D3DVECTOR *)value;
2786
2787 TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
2788 *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
2789 break;
2790 }
2791 case LT_RANGE:
2792 case LT_FALLOFF:
2793 case LT_ATTENUATION0:
2794 case LT_ATTENUATION1:
2795 case LT_ATTENUATION2:
2796 case LT_THETA:
2797 case LT_PHI:
2798 {
2799 float v = *(float *)value;
2800 TRACE("%s %.8e.\n", light_tbl[op].name, v);
2801 *(float *)((BYTE *)light + light_tbl[op].offset) = v;
2802 break;
2803 }
2804 default:
2805 WARN("Unknown light parameter %u.\n", op);
2806 break;
2807 }
2808 }
2809
2810 static void d3dx9_set_material_parameter(enum MATERIAL_TYPE op, D3DMATERIAL9 *material, void *value)
2811 {
2812 static const struct
2813 {
2814 unsigned int offset;
2815 const char *name;
2816 }
2817 material_tbl[] =
2818 {
2819 {FIELD_OFFSET(D3DMATERIAL9, Diffuse), "MT_DIFFUSE"},
2820 {FIELD_OFFSET(D3DMATERIAL9, Ambient), "MT_AMBIENT"},
2821 {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
2822 {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
2823 {FIELD_OFFSET(D3DMATERIAL9, Power), "MT_POWER"}
2824 };
2825
2826 switch (op)
2827 {
2828 case MT_POWER:
2829 {
2830 float v = *(float *)value;
2831
2832 TRACE("%s %.8e.\n", material_tbl[op].name, v);
2833 material->Power = v;
2834 break;
2835 }
2836 case MT_DIFFUSE:
2837 case MT_AMBIENT:
2838 case MT_SPECULAR:
2839 case MT_EMISSIVE:
2840 {
2841 D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
2842
2843 TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
2844 *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
2845 break;
2846 }
2847 default:
2848 WARN("Unknown material parameter %u.\n", op);
2849 break;
2850 }
2851 }
2852
2853 static HRESULT d3dx_set_shader_const_state(struct ID3DXEffectImpl *effect, enum SHADER_CONSTANT_TYPE op, UINT index,
2854 struct d3dx_parameter *param, void *value_ptr)
2855 {
2856 static const struct
2857 {
2858 D3DXPARAMETER_TYPE type;
2859 UINT elem_size;
2860 const char *name;
2861 }
2862 const_tbl[] =
2863 {
2864 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
2865 {D3DXPT_BOOL, sizeof(BOOL), "SCT_VSBOOL"},
2866 {D3DXPT_INT, sizeof(int) * 4, "SCT_VSINT"},
2867 {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
2868 {D3DXPT_BOOL, sizeof(BOOL), "SCT_PSBOOL"},
2869 {D3DXPT_INT, sizeof(int) * 4, "SCT_PSINT"},
2870 };
2871 unsigned int element_count;
2872
2873 if (op < 0 || op > SCT_PSINT)
2874 {
2875 FIXME("Unknown op %u.\n", op);
2876 return D3DERR_INVALIDCALL;
2877 }
2878 element_count = param->bytes / const_tbl[op].elem_size;
2879 TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
2880 if (param->type != const_tbl[op].type)
2881 {
2882 FIXME("Unexpected param type %u.\n", param->type);
2883 return D3DERR_INVALIDCALL;
2884 }
2885 if (param->bytes % const_tbl[op].elem_size != 0)
2886 {
2887 FIXME("Unexpected param size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
2888 return D3DERR_INVALIDCALL;
2889 }
2890
2891 switch (op)
2892 {
2893 case SCT_VSFLOAT:
2894 return SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)value_ptr, element_count);
2895 case SCT_VSBOOL:
2896 return SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)value_ptr, element_count);
2897 case SCT_VSINT:
2898 return SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)value_ptr, element_count);
2899 case SCT_PSFLOAT:
2900 return SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)value_ptr, element_count);
2901 case SCT_PSBOOL:
2902 return SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)value_ptr, element_count);
2903 case SCT_PSINT:
2904 return SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)value_ptr, element_count);
2905 }
2906 return D3D_OK;
2907 }
2908
2909 static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
2910 struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
2911
2912 static HRESULT d3dx_set_shader_constants(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
2913 struct d3dx_parameter *param, BOOL vs, BOOL update_all)
2914 {
2915 HRESULT hr, ret;
2916 struct d3dx_parameter **params;
2917 D3DXCONSTANT_DESC *cdesc;
2918 unsigned int parameters_count;
2919 unsigned int i, j;
2920
2921 if (!param->param_eval)
2922 {
2923 FIXME("param_eval structure is null.\n");
2924 return D3DERR_INVALIDCALL;
2925 }
2926 if (FAILED(hr = d3dx_param_eval_set_shader_constants(effect->manager, effect->device,
2927 param->param_eval, update_all)))
2928 return hr;
2929 params = param->param_eval->shader_inputs.inputs_param;
2930 cdesc = param->param_eval->shader_inputs.inputs;
2931 parameters_count = param->param_eval->shader_inputs.input_count;
2932 ret = D3D_OK;
2933 for (i = 0; i < parameters_count; ++i)
2934 {
2935 if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
2936 {
2937 struct d3dx_sampler *sampler;
2938 unsigned int sampler_idx;
2939
2940 for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
2941 {
2942 sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
2943 TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
2944 cdesc[i].RegisterIndex, sampler->state_count);
2945 for (j = 0; j < sampler->state_count; ++j)
2946 {
2947 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
2948 cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
2949 update_all)))
2950 ret = hr;
2951 }
2952 }
2953 }
2954 }
2955 return ret;
2956 }
2957
2958 static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
2959 struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
2960 {
2961 struct d3dx_parameter *param;
2962 void *param_value;
2963 BOOL param_dirty;
2964 HRESULT hr;
2965
2966 TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
2967
2968 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
2969 update_all, &param_dirty)))
2970 {
2971 if (!update_all && hr == E_FAIL)
2972 {
2973 /* Native d3dx9 returns D3D_OK from CommitChanges() involving
2974 * out of bounds array access and does not touch the affected
2975 * states. */
2976 WARN("Returning D3D_OK on out of bounds array access.\n");
2977 return D3D_OK;
2978 }
2979 return hr;
2980 }
2981
2982 if (!(update_all || param_dirty
2983 || state_table[state->operation].class == SC_VERTEXSHADER
2984 || state_table[state->operation].class == SC_PIXELSHADER
2985 || state_table[state->operation].class == SC_SETSAMPLER))
2986 return D3D_OK;
2987
2988 switch (state_table[state->operation].class)
2989 {
2990 case SC_RENDERSTATE:
2991 TRACE("%s, operation %u, value %u.\n", state_table[state->operation].name,
2992 state_table[state->operation].op, *(DWORD *)param_value);
2993 return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
2994 case SC_FVF:
2995 TRACE("%s, value %#x.\n", state_table[state->operation].name, *(DWORD *)param_value);
2996 return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
2997 case SC_TEXTURE:
2998 {
2999 UINT unit;
3000
3001 unit = parent_index == ~0u ? state->index : parent_index;
3002 TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
3003 *(IDirect3DBaseTexture9 **)param_value);
3004 return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
3005 }
3006 case SC_TEXTURESTAGE:
3007 TRACE("%s, stage %u, value %u.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
3008 return SET_D3D_STATE(effect, SetTextureStageState, state->index,
3009 state_table[state->operation].op, *(DWORD *)param_value);
3010 case SC_SETSAMPLER:
3011 {
3012 struct d3dx_sampler *sampler;
3013 HRESULT ret, hr;
3014 unsigned int i;
3015
3016 sampler = (struct d3dx_sampler *)param_value;
3017 TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
3018 sampler->state_count);
3019 ret = D3D_OK;
3020 for (i = 0; i < sampler->state_count; i++)
3021 {
3022 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
3023 ret = hr;
3024 }
3025 return ret;
3026 }
3027 case SC_SAMPLERSTATE:
3028 {
3029 UINT sampler;
3030
3031 sampler = parent_index == ~0u ? state->index : parent_index;
3032 TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
3033 return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
3034 *(DWORD *)param_value);
3035 }
3036 case SC_VERTEXSHADER:
3037 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
3038 if ((update_all || param_dirty)
3039 && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
3040 *(IDirect3DVertexShader9 **)param_value)))
3041 ERR("Could not set vertex shader, hr %#x.\n", hr);
3042 else if (*(IDirect3DVertexShader9 **)param_value)
3043 hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
3044 return hr;
3045 case SC_PIXELSHADER:
3046 TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
3047 if ((update_all || param_dirty)
3048 && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
3049 *(IDirect3DPixelShader9 **)param_value)))
3050 ERR("Could not set pixel shader, hr %#x.\n", hr);
3051 else if (*(IDirect3DPixelShader9 **)param_value)
3052 hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
3053 return hr;