xref: /reactos/dll/directx/wine/d3dx9_36/effect.c (revision 51b2c71b)
1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5  * Copyright 2010 Christian Costa
6  * Copyright 2011 Rico Schüller
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 
24 #include <stdio.h>
25 #include <assert.h>
26 
27 #include "d3dx9_private.h"
28 #include "d3dcompiler.h"
29 #include "winternl.h"
30 #include "wine/list.h"
31 #endif /* __REACTOS__ */
32 
33 /* Constants for special INT/FLOAT conversation */
34 #define INT_FLOAT_MULTI 255.0f
35 #define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI)
36 
37 static const char parameter_magic_string[4] = {'@', '!', '#', '\xFF'};
38 static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
39 
40 #define PARAMETER_FLAG_SHARED 1
41 
42 #define INITIAL_POOL_SIZE 16
43 #define INITIAL_PARAM_BLOCK_SIZE 1024
44 
45 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
46 
47 enum STATE_CLASS
48 {
49     SC_LIGHTENABLE,
50     SC_FVF,
51     SC_LIGHT,
52     SC_MATERIAL,
53     SC_NPATCHMODE,
54     SC_PIXELSHADER,
55     SC_RENDERSTATE,
56     SC_SETSAMPLER,
57     SC_SAMPLERSTATE,
58     SC_TEXTURE,
59     SC_TEXTURESTAGE,
60     SC_TRANSFORM,
61     SC_VERTEXSHADER,
62     SC_SHADERCONST,
63     SC_UNKNOWN,
64 };
65 
66 enum MATERIAL_TYPE
67 {
68     MT_DIFFUSE,
69     MT_AMBIENT,
70     MT_SPECULAR,
71     MT_EMISSIVE,
72     MT_POWER,
73 };
74 
75 enum LIGHT_TYPE
76 {
77     LT_TYPE,
78     LT_DIFFUSE,
79     LT_SPECULAR,
80     LT_AMBIENT,
81     LT_POSITION,
82     LT_DIRECTION,
83     LT_RANGE,
84     LT_FALLOFF,
85     LT_ATTENUATION0,
86     LT_ATTENUATION1,
87     LT_ATTENUATION2,
88     LT_THETA,
89     LT_PHI,
90 };
91 
92 enum SHADER_CONSTANT_TYPE
93 {
94     SCT_VSFLOAT,
95     SCT_VSBOOL,
96     SCT_VSINT,
97     SCT_PSFLOAT,
98     SCT_PSBOOL,
99     SCT_PSINT,
100 };
101 
102 enum STATE_TYPE
103 {
104     ST_CONSTANT,
105     ST_PARAMETER,
106     ST_FXLC,
107     ST_ARRAY_SELECTOR,
108 };
109 
110 struct d3dx_object
111 {
112     UINT size;
113     void *data;
114     struct d3dx_parameter *param;
115     BOOL creation_failed;
116 };
117 
118 struct d3dx_state
119 {
120     UINT operation;
121     UINT index;
122     enum STATE_TYPE type;
123     struct d3dx_parameter parameter;
124     struct d3dx_parameter *referenced_param;
125 };
126 
127 struct d3dx_sampler
128 {
129     UINT state_count;
130     struct d3dx_state *states;
131 };
132 
133 struct d3dx_pass
134 {
135     char *name;
136     UINT state_count;
137     UINT annotation_count;
138 
139     struct d3dx_state *states;
140     struct d3dx_parameter *annotations;
141 
142     ULONG64 update_version;
143 };
144 
145 struct d3dx_technique
146 {
147     char *name;
148     UINT pass_count;
149     UINT annotation_count;
150 
151     struct d3dx_parameter *annotations;
152     struct d3dx_pass *passes;
153 
154     struct IDirect3DStateBlock9 *saved_state;
155 };
156 
157 struct d3dx_parameter_block
158 {
159     char magic_string[ARRAY_SIZE(parameter_block_magic_string)];
160     struct d3dx_effect *effect;
161     struct list entry;
162     size_t size;
163     size_t offset;
164     BYTE *buffer;
165 };
166 
167 struct d3dx_recorded_parameter
168 {
169     struct d3dx_parameter *param;
170     unsigned int bytes;
171 };
172 
173 struct d3dx_effect
174 {
175     ID3DXEffect ID3DXEffect_iface;
176     LONG ref;
177 
178     unsigned int parameter_count;
179     unsigned int technique_count;
180     unsigned int object_count;
181     struct d3dx_top_level_parameter *parameters;
182     struct d3dx_technique *techniques;
183     struct d3dx_object *objects;
184     DWORD flags;
185 
186     struct wine_rb_tree param_tree;
187     char *full_name_tmp;
188     unsigned int full_name_tmp_size;
189 
190     struct ID3DXEffectStateManager *manager;
191     struct IDirect3DDevice9 *device;
192     struct d3dx_effect_pool *pool;
193     struct d3dx_technique *active_technique;
194     struct d3dx_pass *active_pass;
195     BOOL started;
196     DWORD begin_flags;
197     ULONG64 version_counter;
198 
199     D3DLIGHT9 current_light[8];
200     unsigned int light_updated;
201     D3DMATERIAL9 current_material;
202     BOOL material_updated;
203 
204     struct list parameter_block_list;
205     struct d3dx_parameter_block *current_parameter_block;
206 };
207 
208 #define INITIAL_SHARED_DATA_SIZE 4
209 
210 struct d3dx_effect_pool
211 {
212     ID3DXEffectPool ID3DXEffectPool_iface;
213     LONG refcount;
214 
215     struct d3dx_shared_data *shared_data;
216     unsigned int size;
217 
218     ULONG64 version_counter;
219 };
220 
221 struct ID3DXEffectCompilerImpl
222 {
223     ID3DXEffectCompiler ID3DXEffectCompiler_iface;
224     LONG ref;
225 };
226 
227 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
228         const char *data, const char **ptr, struct d3dx_object *objects);
229 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
230 
231 typedef BOOL (*walk_parameter_dep_func)(void *data, struct d3dx_parameter *param);
232 
233 static const struct
234 {
235     enum STATE_CLASS class;
236     UINT op;
237     const char *name;
238 }
239 state_table[] =
240 {
241     /* Render states */
242     {SC_RENDERSTATE, D3DRS_ZENABLE, "D3DRS_ZENABLE"}, /* 0x0 */
243     {SC_RENDERSTATE, D3DRS_FILLMODE, "D3DRS_FILLMODE"},
244     {SC_RENDERSTATE, D3DRS_SHADEMODE, "D3DRS_SHADEMODE"},
245     {SC_RENDERSTATE, D3DRS_ZWRITEENABLE, "D3DRS_ZWRITEENABLE"},
246     {SC_RENDERSTATE, D3DRS_ALPHATESTENABLE, "D3DRS_ALPHATESTENABLE"},
247     {SC_RENDERSTATE, D3DRS_LASTPIXEL, "D3DRS_LASTPIXEL"},
248     {SC_RENDERSTATE, D3DRS_SRCBLEND, "D3DRS_SRCBLEND"},
249     {SC_RENDERSTATE, D3DRS_DESTBLEND, "D3DRS_DESTBLEND"},
250     {SC_RENDERSTATE, D3DRS_CULLMODE, "D3DRS_CULLMODE"},
251     {SC_RENDERSTATE, D3DRS_ZFUNC, "D3DRS_ZFUNC"},
252     {SC_RENDERSTATE, D3DRS_ALPHAREF, "D3DRS_ALPHAREF"},
253     {SC_RENDERSTATE, D3DRS_ALPHAFUNC, "D3DRS_ALPHAFUNC"},
254     {SC_RENDERSTATE, D3DRS_DITHERENABLE, "D3DRS_DITHERENABLE"},
255     {SC_RENDERSTATE, D3DRS_ALPHABLENDENABLE, "D3DRS_ALPHABLENDENABLE"},
256     {SC_RENDERSTATE, D3DRS_FOGENABLE, "D3DRS_FOGENABLE"},
257     {SC_RENDERSTATE, D3DRS_SPECULARENABLE, "D3DRS_SPECULARENABLE"},
258     {SC_RENDERSTATE, D3DRS_FOGCOLOR, "D3DRS_FOGCOLOR"}, /* 0x10 */
259     {SC_RENDERSTATE, D3DRS_FOGTABLEMODE, "D3DRS_FOGTABLEMODE"},
260     {SC_RENDERSTATE, D3DRS_FOGSTART, "D3DRS_FOGSTART"},
261     {SC_RENDERSTATE, D3DRS_FOGEND, "D3DRS_FOGEND"},
262     {SC_RENDERSTATE, D3DRS_FOGDENSITY, "D3DRS_FOGDENSITY"},
263     {SC_RENDERSTATE, D3DRS_RANGEFOGENABLE, "D3DRS_RANGEFOGENABLE"},
264     {SC_RENDERSTATE, D3DRS_STENCILENABLE, "D3DRS_STENCILENABLE"},
265     {SC_RENDERSTATE, D3DRS_STENCILFAIL, "D3DRS_STENCILFAIL"},
266     {SC_RENDERSTATE, D3DRS_STENCILZFAIL, "D3DRS_STENCILZFAIL"},
267     {SC_RENDERSTATE, D3DRS_STENCILPASS, "D3DRS_STENCILPASS"},
268     {SC_RENDERSTATE, D3DRS_STENCILFUNC, "D3DRS_STENCILFUNC"},
269     {SC_RENDERSTATE, D3DRS_STENCILREF, "D3DRS_STENCILREF"},
270     {SC_RENDERSTATE, D3DRS_STENCILMASK, "D3DRS_STENCILMASK"},
271     {SC_RENDERSTATE, D3DRS_STENCILWRITEMASK, "D3DRS_STENCILWRITEMASK"},
272     {SC_RENDERSTATE, D3DRS_TEXTUREFACTOR, "D3DRS_TEXTUREFACTOR"},
273     {SC_RENDERSTATE, D3DRS_WRAP0, "D3DRS_WRAP0"},
274     {SC_RENDERSTATE, D3DRS_WRAP1, "D3DRS_WRAP1"}, /* 0x20 */
275     {SC_RENDERSTATE, D3DRS_WRAP2, "D3DRS_WRAP2"},
276     {SC_RENDERSTATE, D3DRS_WRAP3, "D3DRS_WRAP3"},
277     {SC_RENDERSTATE, D3DRS_WRAP4, "D3DRS_WRAP4"},
278     {SC_RENDERSTATE, D3DRS_WRAP5, "D3DRS_WRAP5"},
279     {SC_RENDERSTATE, D3DRS_WRAP6, "D3DRS_WRAP6"},
280     {SC_RENDERSTATE, D3DRS_WRAP7, "D3DRS_WRAP7"},
281     {SC_RENDERSTATE, D3DRS_WRAP8, "D3DRS_WRAP8"},
282     {SC_RENDERSTATE, D3DRS_WRAP9, "D3DRS_WRAP9"},
283     {SC_RENDERSTATE, D3DRS_WRAP10, "D3DRS_WRAP10"},
284     {SC_RENDERSTATE, D3DRS_WRAP11, "D3DRS_WRAP11"},
285     {SC_RENDERSTATE, D3DRS_WRAP12, "D3DRS_WRAP12"},
286     {SC_RENDERSTATE, D3DRS_WRAP13, "D3DRS_WRAP13"},
287     {SC_RENDERSTATE, D3DRS_WRAP14, "D3DRS_WRAP14"},
288     {SC_RENDERSTATE, D3DRS_WRAP15, "D3DRS_WRAP15"},
289     {SC_RENDERSTATE, D3DRS_CLIPPING, "D3DRS_CLIPPING"},
290     {SC_RENDERSTATE, D3DRS_LIGHTING, "D3DRS_LIGHTING"}, /* 0x30 */
291     {SC_RENDERSTATE, D3DRS_AMBIENT, "D3DRS_AMBIENT"},
292     {SC_RENDERSTATE, D3DRS_FOGVERTEXMODE, "D3DRS_FOGVERTEXMODE"},
293     {SC_RENDERSTATE, D3DRS_COLORVERTEX, "D3DRS_COLORVERTEX"},
294     {SC_RENDERSTATE, D3DRS_LOCALVIEWER, "D3DRS_LOCALVIEWER"},
295     {SC_RENDERSTATE, D3DRS_NORMALIZENORMALS, "D3DRS_NORMALIZENORMALS"},
296     {SC_RENDERSTATE, D3DRS_DIFFUSEMATERIALSOURCE, "D3DRS_DIFFUSEMATERIALSOURCE"},
297     {SC_RENDERSTATE, D3DRS_SPECULARMATERIALSOURCE, "D3DRS_SPECULARMATERIALSOURCE"},
298     {SC_RENDERSTATE, D3DRS_AMBIENTMATERIALSOURCE, "D3DRS_AMBIENTMATERIALSOURCE"},
299     {SC_RENDERSTATE, D3DRS_EMISSIVEMATERIALSOURCE, "D3DRS_EMISSIVEMATERIALSOURCE"},
300     {SC_RENDERSTATE, D3DRS_VERTEXBLEND, "D3DRS_VERTEXBLEND"},
301     {SC_RENDERSTATE, D3DRS_CLIPPLANEENABLE, "D3DRS_CLIPPLANEENABLE"},
302     {SC_RENDERSTATE, D3DRS_POINTSIZE, "D3DRS_POINTSIZE"},
303     {SC_RENDERSTATE, D3DRS_POINTSIZE_MIN, "D3DRS_POINTSIZE_MIN"},
304     {SC_RENDERSTATE, D3DRS_POINTSIZE_MAX, "D3DRS_POINTSIZE_MAX"},
305     {SC_RENDERSTATE, D3DRS_POINTSPRITEENABLE, "D3DRS_POINTSPRITEENABLE"},
306     {SC_RENDERSTATE, D3DRS_POINTSCALEENABLE, "D3DRS_POINTSCALEENABLE"}, /* 0x40 */
307     {SC_RENDERSTATE, D3DRS_POINTSCALE_A, "D3DRS_POINTSCALE_A"},
308     {SC_RENDERSTATE, D3DRS_POINTSCALE_B, "D3DRS_POINTSCALE_B"},
309     {SC_RENDERSTATE, D3DRS_POINTSCALE_C, "D3DRS_POINTSCALE_C"},
310     {SC_RENDERSTATE, D3DRS_MULTISAMPLEANTIALIAS, "D3DRS_MULTISAMPLEANTIALIAS"},
311     {SC_RENDERSTATE, D3DRS_MULTISAMPLEMASK, "D3DRS_MULTISAMPLEMASK"},
312     {SC_RENDERSTATE, D3DRS_PATCHEDGESTYLE, "D3DRS_PATCHEDGESTYLE"},
313     {SC_RENDERSTATE, D3DRS_DEBUGMONITORTOKEN, "D3DRS_DEBUGMONITORTOKEN"},
314     {SC_RENDERSTATE, D3DRS_INDEXEDVERTEXBLENDENABLE, "D3DRS_INDEXEDVERTEXBLENDENABLE"},
315     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE, "D3DRS_COLORWRITEENABLE"},
316     {SC_RENDERSTATE, D3DRS_TWEENFACTOR, "D3DRS_TWEENFACTOR"},
317     {SC_RENDERSTATE, D3DRS_BLENDOP, "D3DRS_BLENDOP"},
318     {SC_RENDERSTATE, D3DRS_POSITIONDEGREE, "D3DRS_POSITIONDEGREE"},
319     {SC_RENDERSTATE, D3DRS_NORMALDEGREE, "D3DRS_NORMALDEGREE"},
320     {SC_RENDERSTATE, D3DRS_SCISSORTESTENABLE, "D3DRS_SCISSORTESTENABLE"},
321     {SC_RENDERSTATE, D3DRS_SLOPESCALEDEPTHBIAS, "D3DRS_SLOPESCALEDEPTHBIAS"},
322     {SC_RENDERSTATE, D3DRS_ANTIALIASEDLINEENABLE, "D3DRS_ANTIALIASEDLINEENABLE"}, /* 0x50 */
323     {SC_RENDERSTATE, D3DRS_MINTESSELLATIONLEVEL, "D3DRS_MINTESSELLATIONLEVEL"},
324     {SC_RENDERSTATE, D3DRS_MAXTESSELLATIONLEVEL, "D3DRS_MAXTESSELLATIONLEVEL"},
325     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_X, "D3DRS_ADAPTIVETESS_X"},
326     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Y, "D3DRS_ADAPTIVETESS_Y"},
327     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_Z, "D3DRS_ADAPTIVETESS_Z"},
328     {SC_RENDERSTATE, D3DRS_ADAPTIVETESS_W, "D3DRS_ADAPTIVETESS_W"},
329     {SC_RENDERSTATE, D3DRS_ENABLEADAPTIVETESSELLATION, "D3DRS_ENABLEADAPTIVETESSELLATION"},
330     {SC_RENDERSTATE, D3DRS_TWOSIDEDSTENCILMODE, "D3DRS_TWOSIDEDSTENCILMODE"},
331     {SC_RENDERSTATE, D3DRS_CCW_STENCILFAIL, "D3DRS_CCW_STENCILFAIL"},
332     {SC_RENDERSTATE, D3DRS_CCW_STENCILZFAIL, "D3DRS_CCW_STENCILZFAIL"},
333     {SC_RENDERSTATE, D3DRS_CCW_STENCILPASS, "D3DRS_CCW_STENCILPASS"},
334     {SC_RENDERSTATE, D3DRS_CCW_STENCILFUNC, "D3DRS_CCW_STENCILFUNC"},
335     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE1, "D3DRS_COLORWRITEENABLE1"},
336     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE2, "D3DRS_COLORWRITEENABLE2"},
337     {SC_RENDERSTATE, D3DRS_COLORWRITEENABLE3, "D3DRS_COLORWRITEENABLE3"},
338     {SC_RENDERSTATE, D3DRS_BLENDFACTOR, "D3DRS_BLENDFACTOR"}, /* 0x60 */
339     {SC_RENDERSTATE, D3DRS_SRGBWRITEENABLE, "D3DRS_SRGBWRITEENABLE"},
340     {SC_RENDERSTATE, D3DRS_DEPTHBIAS, "D3DRS_DEPTHBIAS"},
341     {SC_RENDERSTATE, D3DRS_SEPARATEALPHABLENDENABLE, "D3DRS_SEPARATEALPHABLENDENABLE"},
342     {SC_RENDERSTATE, D3DRS_SRCBLENDALPHA, "D3DRS_SRCBLENDALPHA"},
343     {SC_RENDERSTATE, D3DRS_DESTBLENDALPHA, "D3DRS_DESTBLENDALPHA"},
344     {SC_RENDERSTATE, D3DRS_BLENDOPALPHA, "D3DRS_BLENDOPALPHA"},
345     /* Texture stages */
346     {SC_TEXTURESTAGE, D3DTSS_COLOROP, "D3DTSS_COLOROP"},
347     {SC_TEXTURESTAGE, D3DTSS_COLORARG0, "D3DTSS_COLORARG0"},
348     {SC_TEXTURESTAGE, D3DTSS_COLORARG1, "D3DTSS_COLORARG1"},
349     {SC_TEXTURESTAGE, D3DTSS_COLORARG2, "D3DTSS_COLORARG2"},
350     {SC_TEXTURESTAGE, D3DTSS_ALPHAOP, "D3DTSS_ALPHAOP"},
351     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG0, "D3DTSS_ALPHAARG0"},
352     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG1, "D3DTSS_ALPHAARG1"},
353     {SC_TEXTURESTAGE, D3DTSS_ALPHAARG2, "D3DTSS_ALPHAARG2"},
354     {SC_TEXTURESTAGE, D3DTSS_RESULTARG, "D3DTSS_RESULTARG"},
355     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT00, "D3DTSS_BUMPENVMAT00"}, /* 0x70 */
356     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT01, "D3DTSS_BUMPENVMAT01"},
357     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT10, "D3DTSS_BUMPENVMAT10"},
358     {SC_TEXTURESTAGE, D3DTSS_BUMPENVMAT11, "D3DTSS_BUMPENVMAT11"},
359     {SC_TEXTURESTAGE, D3DTSS_TEXCOORDINDEX, "D3DTSS_TEXCOORDINDEX"},
360     {SC_TEXTURESTAGE, D3DTSS_BUMPENVLSCALE, "D3DTSS_BUMPENVLSCALE"},
361     {SC_TEXTURESTAGE, D3DTSS_BUMPENVLOFFSET, "D3DTSS_BUMPENVLOFFSET"},
362     {SC_TEXTURESTAGE, D3DTSS_TEXTURETRANSFORMFLAGS, "D3DTSS_TEXTURETRANSFORMFLAGS"},
363     {SC_TEXTURESTAGE, D3DTSS_CONSTANT, "D3DTSS_CONSTANT"},
364     /* NPatchMode */
365     {SC_NPATCHMODE, 0, "NPatchMode"},
366     /* FVF */
367     {SC_FVF, 0, "FVF"},
368     /* Transform */
369     {SC_TRANSFORM, D3DTS_PROJECTION, "D3DTS_PROJECTION"},
370     {SC_TRANSFORM, D3DTS_VIEW, "D3DTS_VIEW"},
371     {SC_TRANSFORM, D3DTS_WORLD, "D3DTS_WORLD"},
372     {SC_TRANSFORM, D3DTS_TEXTURE0, "D3DTS_TEXTURE0"},
373     /* Material */
374     {SC_MATERIAL, MT_DIFFUSE, "MaterialDiffuse"},
375     {SC_MATERIAL, MT_AMBIENT, "MaterialAmbient"}, /* 0x80 */
376     {SC_MATERIAL, MT_SPECULAR, "MaterialSpecular"},
377     {SC_MATERIAL, MT_EMISSIVE, "MaterialEmissive"},
378     {SC_MATERIAL, MT_POWER, "MaterialPower"},
379     /* Light */
380     {SC_LIGHT, LT_TYPE, "LightType"},
381     {SC_LIGHT, LT_DIFFUSE, "LightDiffuse"},
382     {SC_LIGHT, LT_SPECULAR, "LightSpecular"},
383     {SC_LIGHT, LT_AMBIENT, "LightAmbient"},
384     {SC_LIGHT, LT_POSITION, "LightPosition"},
385     {SC_LIGHT, LT_DIRECTION, "LightDirection"},
386     {SC_LIGHT, LT_RANGE, "LightRange"},
387     {SC_LIGHT, LT_FALLOFF, "LightFallOff"},
388     {SC_LIGHT, LT_ATTENUATION0, "LightAttenuation0"},
389     {SC_LIGHT, LT_ATTENUATION1, "LightAttenuation1"},
390     {SC_LIGHT, LT_ATTENUATION2, "LightAttenuation2"},
391     {SC_LIGHT, LT_THETA, "LightTheta"},
392     {SC_LIGHT, LT_PHI, "LightPhi"}, /* 0x90 */
393     /* Lightenable */
394     {SC_LIGHTENABLE, 0, "LightEnable"},
395     /* Vertexshader */
396     {SC_VERTEXSHADER, 0, "Vertexshader"},
397     /* Pixelshader */
398     {SC_PIXELSHADER, 0, "Pixelshader"},
399     /* Shader constants */
400     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstantF"},
401     {SC_SHADERCONST, SCT_VSBOOL, "VertexShaderConstantB"},
402     {SC_SHADERCONST, SCT_VSINT, "VertexShaderConstantI"},
403     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant"},
404     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant1"},
405     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant2"},
406     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant3"},
407     {SC_SHADERCONST, SCT_VSFLOAT, "VertexShaderConstant4"},
408     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstantF"},
409     {SC_SHADERCONST, SCT_PSBOOL, "PixelShaderConstantB"},
410     {SC_SHADERCONST, SCT_PSINT, "PixelShaderConstantI"},
411     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant"},
412     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant1"}, /* 0xa0 */
413     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant2"},
414     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant3"},
415     {SC_SHADERCONST, SCT_PSFLOAT, "PixelShaderConstant4"},
416     /* Texture */
417     {SC_TEXTURE, 0, "Texture"},
418     /* Sampler states */
419     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSU, "AddressU"},
420     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSV, "AddressV"},
421     {SC_SAMPLERSTATE, D3DSAMP_ADDRESSW, "AddressW"},
422     {SC_SAMPLERSTATE, D3DSAMP_BORDERCOLOR, "BorderColor"},
423     {SC_SAMPLERSTATE, D3DSAMP_MAGFILTER, "MagFilter"},
424     {SC_SAMPLERSTATE, D3DSAMP_MINFILTER, "MinFilter"},
425     {SC_SAMPLERSTATE, D3DSAMP_MIPFILTER, "MipFilter"},
426     {SC_SAMPLERSTATE, D3DSAMP_MIPMAPLODBIAS, "MipMapLodBias"},
427     {SC_SAMPLERSTATE, D3DSAMP_MAXMIPLEVEL, "MaxMipLevel"},
428     {SC_SAMPLERSTATE, D3DSAMP_MAXANISOTROPY, "MaxAnisotropy"},
429     {SC_SAMPLERSTATE, D3DSAMP_SRGBTEXTURE, "SRGBTexture"},
430     {SC_SAMPLERSTATE, D3DSAMP_ELEMENTINDEX, "ElementIndex"}, /* 0xb0 */
431     {SC_SAMPLERSTATE, D3DSAMP_DMAPOFFSET, "DMAPOffset"},
432     /* Set sampler */
433     {SC_SETSAMPLER, 0, "Sampler"},
434 };
435 
436 static inline void read_dword(const char **ptr, DWORD *d)
437 {
438     memcpy(d, *ptr, sizeof(*d));
439     *ptr += sizeof(*d);
440 }
441 
442 static void skip_dword_unknown(const char **ptr, unsigned int count)
443 {
444     unsigned int i;
445     DWORD d;
446 
447     WARN("Skipping %u unknown DWORDs:\n", count);
448     for (i = 0; i < count; ++i)
449     {
450         read_dword(ptr, &d);
451         WARN("\t0x%08x\n", d);
452     }
453 }
454 
455 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
456 {
457     return (D3DXHANDLE)parameter;
458 }
459 
460 static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
461 {
462     return (D3DXHANDLE)technique;
463 }
464 
465 static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
466 {
467     return (D3DXHANDLE)pass;
468 }
469 
470 static struct d3dx_technique *get_technique_by_name(struct d3dx_effect *effect, const char *name)
471 {
472     unsigned int i;
473 
474     if (!name) return NULL;
475 
476     for (i = 0; i < effect->technique_count; ++i)
477     {
478         if (!strcmp(effect->techniques[i].name, name))
479             return &effect->techniques[i];
480     }
481 
482     return NULL;
483 }
484 
485 static struct d3dx_technique *get_valid_technique(struct d3dx_effect *effect, D3DXHANDLE technique)
486 {
487     unsigned int i;
488 
489     for (i = 0; i < effect->technique_count; ++i)
490     {
491         if (get_technique_handle(&effect->techniques[i]) == technique)
492             return &effect->techniques[i];
493     }
494 
495     return get_technique_by_name(effect, technique);
496 }
497 
498 static struct d3dx_pass *get_valid_pass(struct d3dx_effect *effect, D3DXHANDLE pass)
499 {
500     unsigned int i, k;
501 
502     for (i = 0; i < effect->technique_count; ++i)
503     {
504         struct d3dx_technique *technique = &effect->techniques[i];
505 
506         for (k = 0; k < technique->pass_count; ++k)
507         {
508             if (get_pass_handle(&technique->passes[k]) == pass)
509                 return &technique->passes[k];
510         }
511     }
512 
513     return NULL;
514 }
515 
516 static struct d3dx_parameter *get_valid_parameter(struct d3dx_effect *effect, D3DXHANDLE parameter)
517 {
518     struct d3dx_parameter *handle_param = (struct d3dx_parameter *)parameter;
519 
520     if (handle_param && !strncmp(handle_param->magic_string, parameter_magic_string,
521             sizeof(parameter_magic_string)))
522         return handle_param;
523 
524     return effect->flags & D3DXFX_LARGEADDRESSAWARE ? NULL : get_parameter_by_name(effect, NULL, parameter);
525 }
526 
527 static struct d3dx_parameter_block *get_valid_parameter_block(D3DXHANDLE handle)
528 {
529     struct d3dx_parameter_block *block = (struct d3dx_parameter_block *)handle;
530 
531     return block && !strncmp(block->magic_string, parameter_block_magic_string,
532             sizeof(parameter_block_magic_string)) ? block : NULL;
533 }
534 
535 static void free_state(struct d3dx_state *state)
536 {
537     free_parameter(&state->parameter, FALSE, FALSE);
538 }
539 
540 static void free_object(struct d3dx_object *object)
541 {
542     HeapFree(GetProcessHeap(), 0, object->data);
543 }
544 
545 static void free_sampler(struct d3dx_sampler *sampler)
546 {
547     UINT i;
548 
549     for (i = 0; i < sampler->state_count; ++i)
550     {
551         free_state(&sampler->states[i]);
552     }
553     heap_free(sampler->states);
554 }
555 
556 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param);
557 
558 static void free_parameter_object_data(struct d3dx_parameter *param, const void *data, unsigned int bytes)
559 {
560     unsigned int i, count;
561 
562     if (param->class != D3DXPC_OBJECT)
563         return;
564 
565     count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
566 
567     for (i = 0; i < count; ++i)
568     {
569         switch (param->type)
570         {
571             case D3DXPT_STRING:
572                 heap_free(((char **)data)[i]);
573                 break;
574 
575             case D3DXPT_TEXTURE:
576             case D3DXPT_TEXTURE1D:
577             case D3DXPT_TEXTURE2D:
578             case D3DXPT_TEXTURE3D:
579             case D3DXPT_TEXTURECUBE:
580             case D3DXPT_PIXELSHADER:
581             case D3DXPT_VERTEXSHADER:
582                 if (*(IUnknown **)data)
583                     IUnknown_Release(((IUnknown **)data)[i]);
584                 break;
585 
586             case D3DXPT_SAMPLER:
587             case D3DXPT_SAMPLER1D:
588             case D3DXPT_SAMPLER2D:
589             case D3DXPT_SAMPLER3D:
590             case D3DXPT_SAMPLERCUBE:
591                 assert(count == 1);
592                 free_sampler((struct d3dx_sampler *)data);
593                 return;
594 
595             default:
596                 FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
597                 break;
598         }
599     }
600 }
601 
602 static void free_parameter_data(struct d3dx_parameter *param, BOOL child)
603 {
604     if (!param->data)
605         return;
606 
607     if (!param->element_count)
608         free_parameter_object_data(param, param->data, param->bytes);
609 
610     if (!child || is_param_type_sampler(param->type))
611         heap_free(param->data);
612 }
613 
614 static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child)
615 {
616     unsigned int i;
617 
618     TRACE("Free parameter %p, name %s, type %s, element %#x, child %#x.\n", param, param->name,
619             debug_d3dxparameter_type(param->type), element, child);
620 
621     if (param->param_eval)
622         d3dx_free_param_eval(param->param_eval);
623 
624     if (param->members)
625     {
626         unsigned int count = param->element_count ? param->element_count : param->member_count;
627 
628         for (i = 0; i < count; ++i)
629             free_parameter(&param->members[i], param->element_count != 0, TRUE);
630         HeapFree(GetProcessHeap(), 0, param->members);
631     }
632 
633     heap_free(param->full_name);
634     free_parameter_data(param, child);
635 
636     /* only the parent has to release name and semantic */
637     if (!element)
638     {
639         HeapFree(GetProcessHeap(), 0, param->name);
640         HeapFree(GetProcessHeap(), 0, param->semantic);
641     }
642 }
643 
644 static void free_top_level_parameter(struct d3dx_top_level_parameter *param)
645 {
646     if (param->annotations)
647     {
648         unsigned int i;
649 
650         for (i = 0; i < param->annotation_count; ++i)
651             free_parameter(&param->annotations[i], FALSE, FALSE);
652         HeapFree(GetProcessHeap(), 0, param->annotations);
653     }
654     d3dx_pool_release_shared_parameter(param);
655     free_parameter(&param->param, FALSE, FALSE);
656 }
657 
658 static void free_pass(struct d3dx_pass *pass)
659 {
660     unsigned int i;
661 
662     TRACE("Free pass %p\n", pass);
663 
664     if (!pass)
665         return;
666 
667     if (pass->annotations)
668     {
669         for (i = 0; i < pass->annotation_count; ++i)
670             free_parameter(&pass->annotations[i], FALSE, FALSE);
671         HeapFree(GetProcessHeap(), 0, pass->annotations);
672         pass->annotations = NULL;
673     }
674 
675     if (pass->states)
676     {
677         for (i = 0; i < pass->state_count; ++i)
678             free_state(&pass->states[i]);
679         HeapFree(GetProcessHeap(), 0, pass->states);
680         pass->states = NULL;
681     }
682 
683     HeapFree(GetProcessHeap(), 0, pass->name);
684     pass->name = NULL;
685 }
686 
687 static void free_technique(struct d3dx_technique *technique)
688 {
689     unsigned int i;
690 
691     TRACE("Free technique %p\n", technique);
692 
693     if (!technique)
694         return;
695 
696     if (technique->saved_state)
697     {
698         IDirect3DStateBlock9_Release(technique->saved_state);
699         technique->saved_state = NULL;
700     }
701 
702     if (technique->annotations)
703     {
704         for (i = 0; i < technique->annotation_count; ++i)
705             free_parameter(&technique->annotations[i], FALSE, FALSE);
706         HeapFree(GetProcessHeap(), 0, technique->annotations);
707         technique->annotations = NULL;
708     }
709 
710     if (technique->passes)
711     {
712         for (i = 0; i < technique->pass_count; ++i)
713             free_pass(&technique->passes[i]);
714         HeapFree(GetProcessHeap(), 0, technique->passes);
715         technique->passes = NULL;
716     }
717 
718     HeapFree(GetProcessHeap(), 0, technique->name);
719     technique->name = NULL;
720 }
721 
722 static unsigned int get_recorded_parameter_size(const struct d3dx_recorded_parameter *record)
723 {
724     return sizeof(*record) + record->bytes;
725 }
726 
727 static void free_parameter_block(struct d3dx_parameter_block *block)
728 {
729     struct d3dx_recorded_parameter *record;
730 
731     if (!block)
732         return;
733 
734     record = (struct d3dx_recorded_parameter *)block->buffer;
735     while ((BYTE *)record < block->buffer + block->offset)
736     {
737         free_parameter_object_data(record->param, record + 1, record->bytes);
738         record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
739     }
740     assert((BYTE *)record == block->buffer + block->offset);
741 
742     heap_free(block->buffer);
743     heap_free(block);
744 }
745 
746 static void d3dx_effect_cleanup(struct d3dx_effect *effect)
747 {
748     struct d3dx_parameter_block *block, *cursor;
749     ID3DXEffectPool *pool;
750     unsigned int i;
751 
752     TRACE("effect %p.\n", effect);
753 
754     free_parameter_block(effect->current_parameter_block);
755     LIST_FOR_EACH_ENTRY_SAFE(block, cursor, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
756     {
757         list_remove(&block->entry);
758         free_parameter_block(block);
759     }
760 
761     heap_free(effect->full_name_tmp);
762 
763     if (effect->parameters)
764     {
765         for (i = 0; i < effect->parameter_count; ++i)
766             free_top_level_parameter(&effect->parameters[i]);
767         heap_free(effect->parameters);
768     }
769 
770     if (effect->techniques)
771     {
772         for (i = 0; i < effect->technique_count; ++i)
773             free_technique(&effect->techniques[i]);
774         heap_free(effect->techniques);
775     }
776 
777     if (effect->objects)
778     {
779         for (i = 0; i < effect->object_count; ++i)
780             free_object(&effect->objects[i]);
781         heap_free(effect->objects);
782     }
783 
784     if (effect->pool)
785     {
786         pool = &effect->pool->ID3DXEffectPool_iface;
787         pool->lpVtbl->Release(pool);
788     }
789 
790     if (effect->manager)
791         IUnknown_Release(effect->manager);
792 
793     IDirect3DDevice9_Release(effect->device);
794     heap_free(effect);
795 }
796 
797 static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector)
798 {
799     UINT i;
800 
801     for (i = 0; i < 4; ++i)
802     {
803         if (i < param->columns)
804             set_number((FLOAT *)vector + i, D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
805         else
806             ((FLOAT *)vector)[i] = 0.0f;
807     }
808 }
809 
810 static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector, void *dst_data)
811 {
812     UINT i;
813 
814     for (i = 0; i < param->columns; ++i)
815         set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
816 }
817 
818 static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose)
819 {
820     UINT i, k;
821 
822     for (i = 0; i < 4; ++i)
823     {
824         for (k = 0; k < 4; ++k)
825         {
826             FLOAT *tmp = transpose ? (FLOAT *)&matrix->u.m[k][i] : (FLOAT *)&matrix->u.m[i][k];
827 
828             if ((i < param->rows) && (k < param->columns))
829                 set_number(tmp, D3DXPT_FLOAT, (DWORD *)param->data + i * param->columns + k, param->type);
830             else
831                 *tmp = 0.0f;
832         }
833     }
834 }
835 
836 static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
837 {
838     UINT i, k;
839 
840     if (param->type == D3DXPT_FLOAT)
841     {
842         if (param->columns == 4)
843         {
844             memcpy(dst_data, matrix->u.m, param->rows * 4 * sizeof(float));
845         }
846         else
847         {
848             for (i = 0; i < param->rows; ++i)
849                 memcpy((float *)dst_data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
850         }
851         return;
852     }
853 
854     for (i = 0; i < param->rows; ++i)
855     {
856         for (k = 0; k < param->columns; ++k)
857             set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
858                     &matrix->u.m[i][k], D3DXPT_FLOAT);
859     }
860 }
861 
862 static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
863 {
864     UINT i, k;
865 
866     for (i = 0; i < param->rows; ++i)
867     {
868         for (k = 0; k < param->columns; ++k)
869         {
870             set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
871                     &matrix->u.m[k][i], D3DXPT_FLOAT);
872         }
873     }
874 }
875 
876 static HRESULT set_string(char **param_data, const char *string)
877 {
878     heap_free(*param_data);
879     *param_data = heap_alloc(strlen(string) + 1);
880     if (!*param_data)
881     {
882         ERR("Out of memory.\n");
883         return E_OUTOFMEMORY;
884     }
885     strcpy(*param_data, string);
886     return D3D_OK;
887 }
888 
889 static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes,
890         void *dst_data)
891 {
892     unsigned int i, count;
893 
894     bytes = min(bytes, param->bytes);
895     count = min(param->element_count ? param->element_count : 1, bytes / sizeof(void *));
896 
897     switch (param->type)
898     {
899         case D3DXPT_TEXTURE:
900         case D3DXPT_TEXTURE1D:
901         case D3DXPT_TEXTURE2D:
902         case D3DXPT_TEXTURE3D:
903         case D3DXPT_TEXTURECUBE:
904             for (i = 0; i < count; ++i)
905             {
906                 IUnknown *old_texture = ((IUnknown **)dst_data)[i];
907                 IUnknown *new_texture = ((IUnknown **)data)[i];
908 
909                 if (new_texture == old_texture)
910                     continue;
911 
912                 if (new_texture)
913                     IUnknown_AddRef(new_texture);
914                 if (old_texture)
915                     IUnknown_Release(old_texture);
916             }
917         /* fallthrough */
918         case D3DXPT_VOID:
919         case D3DXPT_BOOL:
920         case D3DXPT_INT:
921         case D3DXPT_FLOAT:
922             TRACE("Copy %u bytes.\n", bytes);
923             memcpy(dst_data, data, bytes);
924             break;
925 
926         case D3DXPT_STRING:
927         {
928             HRESULT hr;
929 
930             for (i = 0; i < count; ++i)
931                 if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i])))
932                     return hr;
933             break;
934         }
935 
936         default:
937             FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
938             break;
939     }
940 
941     return D3D_OK;
942 }
943 
944 static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_effect *effect,
945         struct d3dx_parameter *parameter, const char *name)
946 {
947     UINT element;
948     struct d3dx_parameter *temp_parameter;
949     const char *part;
950 
951     TRACE("parameter %p, name %s\n", parameter, debugstr_a(name));
952 
953     if (!name || !*name) return NULL;
954 
955     element = atoi(name);
956     part = strchr(name, ']') + 1;
957 
958     /* check for empty [] && element range */
959     if ((part - name) > 1 && parameter->element_count > element)
960     {
961         temp_parameter = &parameter->members[element];
962 
963         switch (*part++)
964         {
965             case '.':
966                 return get_parameter_by_name(effect, temp_parameter, part);
967 
968             case '\0':
969                 TRACE("Returning parameter %p\n", temp_parameter);
970                 return temp_parameter;
971 
972             default:
973                 FIXME("Unhandled case \"%c\"\n", *--part);
974                 break;
975         }
976     }
977 
978     TRACE("Parameter not found\n");
979     return NULL;
980 }
981 
982 static struct d3dx_parameter *get_annotation_by_name(struct d3dx_effect *effect, unsigned int count,
983         struct d3dx_parameter *annotations, const char *name)
984 {
985     UINT i, length;
986     struct d3dx_parameter *temp_parameter;
987     const char *part;
988 
989     TRACE("count %u, annotations %p, name %s\n", count, annotations, debugstr_a(name));
990 
991     if (!name || !*name) return NULL;
992 
993     length = strcspn( name, "[.@" );
994     part = name + length;
995 
996     for (i = 0; i < count; ++i)
997     {
998         temp_parameter = &annotations[i];
999 
1000         if (!strcmp(temp_parameter->name, name))
1001         {
1002             TRACE("Returning annotation %p\n", temp_parameter);
1003             return temp_parameter;
1004         }
1005         else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1006         {
1007             switch (*part++)
1008             {
1009                 case '.':
1010                     return get_parameter_by_name(effect, temp_parameter, part);
1011 
1012                 case '[':
1013                     return get_parameter_element_by_name(effect, temp_parameter, part);
1014 
1015                 default:
1016                     FIXME("Unhandled case \"%c\"\n", *--part);
1017                     break;
1018             }
1019         }
1020     }
1021 
1022     TRACE("Annotation not found\n");
1023     return NULL;
1024 }
1025 
1026 struct d3dx_parameter *get_parameter_by_name(struct d3dx_effect* effect,
1027         struct d3dx_parameter *parameter, const char *name)
1028 {
1029     struct d3dx_parameter *temp_parameter;
1030     unsigned int name_len, param_name_len;
1031     unsigned int i, count, length;
1032     struct wine_rb_entry *entry;
1033     unsigned int full_name_size;
1034     const char *part;
1035     char *full_name;
1036 
1037     TRACE("effect %p, parameter %p, name %s.\n", effect, parameter, debugstr_a(name));
1038 
1039     if (!name || !*name) return NULL;
1040 
1041     if (!parameter)
1042     {
1043         if ((entry = wine_rb_get(&effect->param_tree, name)))
1044             return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1045         return NULL;
1046     }
1047 
1048     if (parameter->full_name)
1049     {
1050         name_len = strlen(name);
1051         param_name_len = strlen(parameter->full_name);
1052         full_name_size = name_len + param_name_len + 2;
1053         if (effect->full_name_tmp_size < full_name_size)
1054         {
1055             if (!(full_name = heap_realloc(effect->full_name_tmp, full_name_size)))
1056             {
1057                 ERR("Out of memory.\n");
1058                 return NULL;
1059             }
1060             effect->full_name_tmp = full_name;
1061             effect->full_name_tmp_size = full_name_size;
1062         }
1063         else
1064         {
1065             full_name = effect->full_name_tmp;
1066         }
1067         memcpy(full_name, parameter->full_name, param_name_len);
1068         full_name[param_name_len] = '.';
1069         memcpy(full_name + param_name_len + 1, name, name_len);
1070         full_name[param_name_len + 1 + name_len] = 0;
1071 
1072         if ((entry = wine_rb_get(&effect->param_tree, full_name)))
1073             return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
1074         return NULL;
1075     }
1076 
1077     /* Pass / technique annotations are not stored in the parameters tree,
1078      * do a linear search. */
1079     count = parameter->member_count;
1080 
1081     length = strcspn( name, "[." );
1082     part = name + length;
1083 
1084     for (i = 0; i < count; i++)
1085     {
1086         temp_parameter = &parameter->members[i];
1087 
1088         if (!strcmp(temp_parameter->name, name))
1089         {
1090             TRACE("Returning parameter %p\n", temp_parameter);
1091             return temp_parameter;
1092         }
1093         else if (strlen(temp_parameter->name) == length && !strncmp(temp_parameter->name, name, length))
1094         {
1095             switch (*part++)
1096             {
1097                 case '.':
1098                     return get_parameter_by_name(effect, temp_parameter, part);
1099 
1100                 case '[':
1101                     return get_parameter_element_by_name(effect, temp_parameter, part);
1102 
1103                 default:
1104                     FIXME("Unhandled case \"%c\"\n", *--part);
1105                     break;
1106             }
1107         }
1108     }
1109 
1110     TRACE("Parameter not found\n");
1111     return NULL;
1112 }
1113 
1114 static inline DWORD d3dx9_effect_version(DWORD major, DWORD minor)
1115 {
1116     return (0xfeff0000 | ((major) << 8) | (minor));
1117 }
1118 
1119 static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_state *state,
1120         void **param_value, struct d3dx_parameter **out_param,
1121         BOOL update_all, BOOL *param_dirty)
1122 {
1123     struct d3dx_parameter *param = &state->parameter;
1124 
1125     *param_value = NULL;
1126     *out_param = NULL;
1127     *param_dirty = FALSE;
1128 
1129     switch (state->type)
1130     {
1131         case ST_PARAMETER:
1132             param = state->referenced_param;
1133             *param_dirty = is_param_dirty(param, pass->update_version);
1134             /* fallthrough */
1135         case ST_CONSTANT:
1136             *out_param = param;
1137             *param_value = param->data;
1138             return D3D_OK;
1139         case ST_ARRAY_SELECTOR:
1140         {
1141             unsigned int array_idx;
1142             static const struct d3dx_parameter array_idx_param =
1143                 {"", NULL, NULL, NULL, NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, sizeof(array_idx)};
1144             HRESULT hr;
1145             struct d3dx_parameter *ref_param, *selected_param;
1146 
1147             if (!param->param_eval)
1148             {
1149                 FIXME("Preshader structure is null.\n");
1150                 return D3DERR_INVALIDCALL;
1151             }
1152             /* We override with the update_version of the pass because we want
1153              * to force index recomputation and check for out of bounds. */
1154             if (is_param_eval_input_dirty(param->param_eval, pass->update_version))
1155             {
1156                 if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
1157                     return hr;
1158             }
1159             else
1160             {
1161                 array_idx = state->index;
1162             }
1163             ref_param = state->referenced_param;
1164             TRACE("Array index %u, stored array index %u, element_count %u.\n", array_idx, state->index,
1165                     ref_param->element_count);
1166             /* According to the tests, native d3dx handles the case of array index evaluated to -1
1167              * in a specific way, always selecting first array element and not returning error. */
1168             if (array_idx == ~0u)
1169             {
1170                 WARN("Array index is -1, setting to 0.\n");
1171                 array_idx = 0;
1172             }
1173 
1174             if (array_idx >= ref_param->element_count)
1175             {
1176                 WARN("Computed array index %u is larger than array size %u.\n",
1177                         array_idx, ref_param->element_count);
1178                 return E_FAIL;
1179             }
1180             selected_param = &ref_param->members[array_idx];
1181             *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
1182             state->index = array_idx;
1183 
1184             *param_value = selected_param->data;
1185             *out_param = selected_param;
1186             return D3D_OK;
1187         }
1188         case ST_FXLC:
1189             if (param->param_eval)
1190             {
1191                 *out_param = param;
1192                 *param_value = param->data;
1193                 /* We check with the update_version of the pass because the
1194                  * same preshader might be used by both the vertex and the
1195                  * pixel shader (that can happen e.g. for sampler states). */
1196                 if (update_all || is_param_eval_input_dirty(param->param_eval, pass->update_version))
1197                 {
1198                     *param_dirty = TRUE;
1199                     return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
1200                 }
1201                 else
1202                     return D3D_OK;
1203             }
1204             else
1205             {
1206                 FIXME("No preshader for FXLC parameter.\n");
1207                 return D3DERR_INVALIDCALL;
1208             }
1209     }
1210     return E_NOTIMPL;
1211 }
1212 
1213 static unsigned int get_annotation_from_object(struct d3dx_effect *effect, D3DXHANDLE object,
1214         struct d3dx_parameter **annotations)
1215 {
1216     struct d3dx_parameter *param = get_valid_parameter(effect, object);
1217     struct d3dx_pass *pass = get_valid_pass(effect, object);
1218     struct d3dx_technique *technique = get_valid_technique(effect, object);
1219 
1220     if (pass)
1221     {
1222         *annotations = pass->annotations;
1223         return pass->annotation_count;
1224     }
1225     else if (technique)
1226     {
1227         *annotations = technique->annotations;
1228         return technique->annotation_count;
1229     }
1230     else if (param)
1231     {
1232         if (is_top_level_parameter(param))
1233         {
1234             struct d3dx_top_level_parameter *top_param
1235                     = top_level_parameter_from_parameter(param);
1236 
1237             *annotations = top_param->annotations;
1238             return top_param->annotation_count;
1239         }
1240         else
1241         {
1242             *annotations = NULL;
1243             return 0;
1244         }
1245     }
1246     else
1247     {
1248         FIXME("Functions are not handled, yet!\n");
1249         return 0;
1250     }
1251 }
1252 
1253 static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
1254         void *data)
1255 {
1256     unsigned int i;
1257     unsigned int member_count;
1258 
1259     if (param_func(data, param))
1260         return TRUE;
1261 
1262     member_count = param->element_count ? param->element_count : param->member_count;
1263     for (i = 0; i < member_count; ++i)
1264     {
1265         if (walk_parameter_tree(&param->members[i], param_func, data))
1266             return TRUE;
1267     }
1268     return FALSE;
1269 }
1270 
1271 static ULONG64 *get_version_counter_ptr(struct d3dx_effect *effect)
1272 {
1273     return effect->pool ? &effect->pool->version_counter : &effect->version_counter;
1274 }
1275 
1276 static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
1277 {
1278     return next_update_version(get_version_counter_ptr(effect));
1279 }
1280 
1281 static void *record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, unsigned int bytes)
1282 {
1283     struct d3dx_parameter_block *block = effect->current_parameter_block;
1284     struct d3dx_recorded_parameter new_record, *record;
1285     unsigned int new_size, alloc_size;
1286 
1287     new_record.param = param;
1288     new_record.bytes = bytes;
1289     new_size = block->offset + get_recorded_parameter_size(&new_record);
1290 
1291     if (new_size > block->size)
1292     {
1293         BYTE *new_alloc;
1294 
1295         alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
1296         if (block->size)
1297             new_alloc = heap_realloc(block->buffer, alloc_size);
1298         else
1299             new_alloc = heap_alloc(alloc_size);
1300 
1301         if (!new_alloc)
1302         {
1303             ERR("Out of memory.\n");
1304             return param->data;
1305         }
1306         /* Data update functions may want to free some references upon setting value. */
1307         memset(new_alloc + block->size, 0, alloc_size - block->size);
1308 
1309         block->size = alloc_size;
1310         block->buffer = new_alloc;
1311     }
1312     record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
1313     *record = new_record;
1314     block->offset = new_size;
1315     return record + 1;
1316 }
1317 
1318 static void set_dirty(struct d3dx_parameter *param)
1319 {
1320     struct d3dx_shared_data *shared_data;
1321     struct d3dx_top_level_parameter *top_param = param->top_level_param;
1322     ULONG64 new_update_version = next_update_version(top_param->version_counter);
1323 
1324     if ((shared_data = top_param->shared_data))
1325         shared_data->update_version = new_update_version;
1326     else
1327         top_param->update_version = new_update_version;
1328 }
1329 
1330 static void *param_get_data_and_dirtify(struct d3dx_effect *effect, struct d3dx_parameter *param,
1331         unsigned int bytes, BOOL value_changed)
1332 {
1333     assert(bytes <= param->bytes);
1334 
1335     if (value_changed && !effect->current_parameter_block)
1336         set_dirty(param);
1337 
1338     return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data;
1339 }
1340 
1341 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
1342 {
1343     static const struct
1344     {
1345         unsigned int offset;
1346         const char *name;
1347     }
1348     light_tbl[] =
1349     {
1350         {FIELD_OFFSET(D3DLIGHT9, Type),         "LC_TYPE"},
1351         {FIELD_OFFSET(D3DLIGHT9, Diffuse),      "LT_DIFFUSE"},
1352         {FIELD_OFFSET(D3DLIGHT9, Specular),     "LT_SPECULAR"},
1353         {FIELD_OFFSET(D3DLIGHT9, Ambient),      "LT_AMBIENT"},
1354         {FIELD_OFFSET(D3DLIGHT9, Position),     "LT_POSITION"},
1355         {FIELD_OFFSET(D3DLIGHT9, Direction),    "LT_DIRECTION"},
1356         {FIELD_OFFSET(D3DLIGHT9, Range),        "LT_RANGE"},
1357         {FIELD_OFFSET(D3DLIGHT9, Falloff),      "LT_FALLOFF"},
1358         {FIELD_OFFSET(D3DLIGHT9, Attenuation0), "LT_ATTENUATION0"},
1359         {FIELD_OFFSET(D3DLIGHT9, Attenuation1), "LT_ATTENUATION1"},
1360         {FIELD_OFFSET(D3DLIGHT9, Attenuation2), "LT_ATTENUATION2"},
1361         {FIELD_OFFSET(D3DLIGHT9, Theta),        "LT_THETA"},
1362         {FIELD_OFFSET(D3DLIGHT9, Phi),          "LT_PHI"}
1363     };
1364     switch (op)
1365     {
1366         case LT_TYPE:
1367             TRACE("LT_TYPE %u.\n", *(D3DLIGHTTYPE *)value);
1368             light->Type = *(D3DLIGHTTYPE *)value;
1369             break;
1370         case LT_DIFFUSE:
1371         case LT_SPECULAR:
1372         case LT_AMBIENT:
1373         {
1374             D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1375 
1376             TRACE("%s (%.8e %.8e %.8e %.8e).\n", light_tbl[op].name, c.r, c.g, c.b, c.a);
1377             *(D3DCOLORVALUE *)((BYTE *)light + light_tbl[op].offset) = c;
1378             break;
1379         }
1380         case LT_POSITION:
1381         case LT_DIRECTION:
1382         {
1383             D3DVECTOR v = *(D3DVECTOR *)value;
1384 
1385             TRACE("%s (%.8e %.8e %.8e).\n", light_tbl[op].name, v.x, v.y, v.z);
1386             *(D3DVECTOR *)((BYTE *)light + light_tbl[op].offset) = v;
1387             break;
1388         }
1389         case LT_RANGE:
1390         case LT_FALLOFF:
1391         case LT_ATTENUATION0:
1392         case LT_ATTENUATION1:
1393         case LT_ATTENUATION2:
1394         case LT_THETA:
1395         case LT_PHI:
1396         {
1397             float v = *(float *)value;
1398             TRACE("%s %.8e.\n", light_tbl[op].name, v);
1399             *(float *)((BYTE *)light + light_tbl[op].offset) = v;
1400             break;
1401         }
1402         default:
1403             WARN("Unknown light parameter %u.\n", op);
1404             break;
1405     }
1406 }
1407 
1408 static void d3dx9_set_material_parameter(enum MATERIAL_TYPE op, D3DMATERIAL9 *material, void *value)
1409 {
1410     static const struct
1411     {
1412         unsigned int offset;
1413         const char *name;
1414     }
1415     material_tbl[] =
1416     {
1417         {FIELD_OFFSET(D3DMATERIAL9, Diffuse),  "MT_DIFFUSE"},
1418         {FIELD_OFFSET(D3DMATERIAL9, Ambient),  "MT_AMBIENT"},
1419         {FIELD_OFFSET(D3DMATERIAL9, Specular), "MT_SPECULAR"},
1420         {FIELD_OFFSET(D3DMATERIAL9, Emissive), "MT_EMISSIVE"},
1421         {FIELD_OFFSET(D3DMATERIAL9, Power),    "MT_POWER"}
1422     };
1423 
1424     switch (op)
1425     {
1426         case MT_POWER:
1427         {
1428             float v = *(float *)value;
1429 
1430             TRACE("%s %.8e.\n", material_tbl[op].name, v);
1431             material->Power = v;
1432             break;
1433         }
1434         case MT_DIFFUSE:
1435         case MT_AMBIENT:
1436         case MT_SPECULAR:
1437         case MT_EMISSIVE:
1438         {
1439             D3DCOLORVALUE c = *(D3DCOLORVALUE *)value;
1440 
1441             TRACE("%s, value (%.8e %.8e %.8e %.8e).\n", material_tbl[op].name, c.r, c.g, c.b, c.a);
1442             *(D3DCOLORVALUE *)((BYTE *)material + material_tbl[op].offset) = c;
1443             break;
1444         }
1445         default:
1446             WARN("Unknown material parameter %u.\n", op);
1447             break;
1448     }
1449 }
1450 
1451 static HRESULT d3dx_set_shader_const_state(struct d3dx_effect *effect, enum SHADER_CONSTANT_TYPE op, UINT index,
1452         struct d3dx_parameter *param, void *value_ptr)
1453 {
1454     static const struct
1455     {
1456         D3DXPARAMETER_TYPE type;
1457         UINT elem_size;
1458         const char *name;
1459     }
1460     const_tbl[] =
1461     {
1462         {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_VSFLOAT"},
1463         {D3DXPT_BOOL,  sizeof(BOOL),      "SCT_VSBOOL"},
1464         {D3DXPT_INT,   sizeof(int) * 4,   "SCT_VSINT"},
1465         {D3DXPT_FLOAT, sizeof(float) * 4, "SCT_PSFLOAT"},
1466         {D3DXPT_BOOL,  sizeof(BOOL),      "SCT_PSBOOL"},
1467         {D3DXPT_INT,   sizeof(int) * 4,   "SCT_PSINT"},
1468     };
1469 
1470     BOOL is_heap_buffer = FALSE;
1471     unsigned int element_count;
1472     void *buffer = value_ptr;
1473     D3DXVECTOR4 value;
1474     HRESULT ret;
1475 
1476     assert(op < ARRAY_SIZE(const_tbl));
1477     element_count = param->bytes / const_tbl[op].elem_size;
1478     TRACE("%s, index %u, element_count %u.\n", const_tbl[op].name, index, element_count);
1479     if (param->type != const_tbl[op].type)
1480     {
1481         FIXME("Unexpected param type %u.\n", param->type);
1482         return D3DERR_INVALIDCALL;
1483     }
1484 
1485     if (param->bytes % const_tbl[op].elem_size || element_count > 1)
1486     {
1487         unsigned int param_data_size;
1488 
1489         TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
1490 
1491         if (param->bytes % const_tbl[op].elem_size)
1492             ++element_count;
1493         if (element_count > 1)
1494         {
1495             WARN("Setting %u elements.\n", element_count);
1496             buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count);
1497             if (!buffer)
1498             {
1499                 ERR("Out of memory.\n");
1500                 return E_OUTOFMEMORY;
1501             }
1502             is_heap_buffer = TRUE;
1503         }
1504         else
1505         {
1506             assert(const_tbl[op].elem_size <= sizeof(value));
1507             buffer = &value;
1508         }
1509         param_data_size = min(param->bytes, const_tbl[op].elem_size);
1510         memcpy(buffer, value_ptr, param_data_size);
1511         memset((unsigned char *)buffer + param_data_size, 0,
1512                 const_tbl[op].elem_size * element_count - param_data_size);
1513     }
1514 
1515     switch (op)
1516     {
1517         case SCT_VSFLOAT:
1518             ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
1519             break;
1520         case SCT_VSBOOL:
1521             ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
1522             break;
1523         case SCT_VSINT:
1524             ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
1525             break;
1526         case SCT_PSFLOAT:
1527             ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
1528             break;
1529         case SCT_PSBOOL:
1530             ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
1531             break;
1532         case SCT_PSINT:
1533             ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
1534             break;
1535         default:
1536             ret = D3DERR_INVALIDCALL;
1537             break;
1538     }
1539 
1540     if (is_heap_buffer)
1541         HeapFree(GetProcessHeap(), 0, buffer);
1542 
1543     return ret;
1544 }
1545 
1546 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1547         struct d3dx_state *state, unsigned int parent_index, BOOL update_all);
1548 
1549 static HRESULT d3dx_set_shader_constants(struct d3dx_effect *effect, struct d3dx_pass *pass,
1550         struct d3dx_parameter *param, BOOL vs, BOOL update_all)
1551 {
1552     HRESULT hr, ret;
1553     struct d3dx_parameter **params;
1554     D3DXCONSTANT_DESC *cdesc;
1555     unsigned int parameters_count;
1556     unsigned int i, j;
1557 
1558     if (!param->param_eval)
1559     {
1560         FIXME("param_eval structure is null.\n");
1561         return D3DERR_INVALIDCALL;
1562     }
1563     if (FAILED(hr = d3dx_param_eval_set_shader_constants(effect->manager, effect->device,
1564             param->param_eval, update_all)))
1565         return hr;
1566     params = param->param_eval->shader_inputs.inputs_param;
1567     cdesc = param->param_eval->shader_inputs.inputs;
1568     parameters_count = param->param_eval->shader_inputs.input_count;
1569     ret = D3D_OK;
1570     for (i = 0; i < parameters_count; ++i)
1571     {
1572         if (params[i] && params[i]->class == D3DXPC_OBJECT && is_param_type_sampler(params[i]->type))
1573         {
1574             struct d3dx_sampler *sampler;
1575             unsigned int sampler_idx;
1576 
1577             for (sampler_idx = 0; sampler_idx < cdesc[i].RegisterCount; ++sampler_idx)
1578             {
1579                 sampler = params[i]->element_count ? params[i]->members[sampler_idx].data : params[i]->data;
1580                 TRACE("sampler %s, register index %u, state count %u.\n", debugstr_a(params[i]->name),
1581                         cdesc[i].RegisterIndex, sampler->state_count);
1582                 for (j = 0; j < sampler->state_count; ++j)
1583                 {
1584                     if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
1585                             cdesc[i].RegisterIndex + sampler_idx + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0),
1586                             update_all)))
1587                         ret = hr;
1588                 }
1589             }
1590         }
1591     }
1592     return ret;
1593 }
1594 
1595 static HRESULT d3dx9_apply_state(struct d3dx_effect *effect, struct d3dx_pass *pass,
1596         struct d3dx_state *state, unsigned int parent_index, BOOL update_all)
1597 {
1598     struct d3dx_parameter *param;
1599     void *param_value;
1600     BOOL param_dirty;
1601     HRESULT hr;
1602 
1603     TRACE("operation %u, index %u, type %u.\n", state->operation, state->index, state->type);
1604 
1605     if (FAILED(hr = d3dx9_get_param_value_ptr(pass, state, &param_value, &param,
1606             update_all, &param_dirty)))
1607     {
1608         if (!update_all && hr == E_FAIL)
1609         {
1610             /* Native d3dx9 returns D3D_OK from CommitChanges() involving
1611              * out of bounds array access and does not touch the affected
1612              * states. */
1613             WARN("Returning D3D_OK on out of bounds array access.\n");
1614             return D3D_OK;
1615         }
1616         return hr;
1617     }
1618 
1619     if (!(update_all || param_dirty
1620             || state_table[state->operation].class == SC_VERTEXSHADER
1621             || state_table[state->operation].class == SC_PIXELSHADER
1622             || state_table[state->operation].class == SC_SETSAMPLER))
1623         return D3D_OK;
1624 
1625     switch (state_table[state->operation].class)
1626     {
1627         case SC_RENDERSTATE:
1628             TRACE("%s, operation %u, value %u.\n", state_table[state->operation].name,
1629                     state_table[state->operation].op, *(DWORD *)param_value);
1630             return SET_D3D_STATE(effect, SetRenderState, state_table[state->operation].op, *(DWORD *)param_value);
1631         case SC_FVF:
1632             TRACE("%s, value %#x.\n", state_table[state->operation].name, *(DWORD *)param_value);
1633             return SET_D3D_STATE(effect, SetFVF, *(DWORD *)param_value);
1634         case SC_TEXTURE:
1635         {
1636             UINT unit;
1637 
1638             unit = parent_index == ~0u ? state->index : parent_index;
1639             TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
1640                     *(IDirect3DBaseTexture9 **)param_value);
1641             return SET_D3D_STATE(effect, SetTexture, unit, *(IDirect3DBaseTexture9 **)param_value);
1642         }
1643         case SC_TEXTURESTAGE:
1644             TRACE("%s, stage %u, value %u.\n", state_table[state->operation].name, state->index, *(DWORD *)param_value);
1645             return SET_D3D_STATE(effect, SetTextureStageState, state->index,
1646                         state_table[state->operation].op, *(DWORD *)param_value);
1647         case SC_SETSAMPLER:
1648         {
1649             struct d3dx_sampler *sampler;
1650             HRESULT ret, hr;
1651             unsigned int i;
1652 
1653             sampler = (struct d3dx_sampler *)param_value;
1654             TRACE("%s, sampler %u, applying %u states.\n", state_table[state->operation].name, state->index,
1655                     sampler->state_count);
1656             ret = D3D_OK;
1657             for (i = 0; i < sampler->state_count; i++)
1658             {
1659                 if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[i], state->index, update_all)))
1660                     ret = hr;
1661             }
1662             return ret;
1663         }
1664         case SC_SAMPLERSTATE:
1665         {
1666             UINT sampler;
1667 
1668             sampler = parent_index == ~0u ? state->index : parent_index;
1669             TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
1670             return SET_D3D_STATE(effect, SetSamplerState, sampler, state_table[state->operation].op,
1671                     *(DWORD *)param_value);
1672         }
1673         case SC_VERTEXSHADER:
1674             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
1675             if ((update_all || param_dirty)
1676                     && FAILED(hr = SET_D3D_STATE(effect, SetVertexShader,
1677                     *(IDirect3DVertexShader9 **)param_value)))
1678                 ERR("Could not set vertex shader, hr %#x.\n", hr);
1679             else if (*(IDirect3DVertexShader9 **)param_value)
1680                 hr = d3dx_set_shader_constants(effect, pass, param, TRUE, update_all || param_dirty);
1681             return hr;
1682         case SC_PIXELSHADER:
1683             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
1684             if ((update_all || param_dirty)
1685                     && FAILED(hr = SET_D3D_STATE(effect, SetPixelShader,
1686                     *(IDirect3DPixelShader9 **)param_value)))
1687                 ERR("Could not set pixel shader, hr %#x.\n", hr);
1688             else if (*(IDirect3DPixelShader9 **)param_value)
1689                 hr = d3dx_set_shader_constants(effect, pass, param, FALSE, update_all || param_dirty);
1690             return hr;
1691         case SC_TRANSFORM:
1692             TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
1693             return SET_D3D_STATE(effect, SetTransform, state_table[state->operation].op + state->index,
1694                     (D3DMATRIX *)param_value);
1695         case SC_LIGHTENABLE:
1696             TRACE("%s, index %u, value %u.\n", state_table[state->operation].name, state->index, *(BOOL *)param_value);
1697             return SET_D3D_STATE(effect, LightEnable, state->index, *(BOOL *)param_value);
1698         case SC_LIGHT:
1699         {
1700             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1701                     state_table[state->operation].op);
1702             d3dx9_set_light_parameter(state_table[state->operation].op,
1703                     &effect->current_light[state->index], param_value);
1704             effect->light_updated |= 1u << state->index;
1705             return D3D_OK;
1706         }
1707         case SC_MATERIAL:
1708         {
1709             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1710                     state_table[state->operation].op);
1711             d3dx9_set_material_parameter(state_table[state->operation].op,
1712                     &effect->current_material, param_value);
1713             effect->material_updated = TRUE;
1714             return D3D_OK;
1715         }
1716         case SC_NPATCHMODE:
1717             TRACE("%s, nsegments %f.\n", state_table[state->operation].name, *(float *)param_value);
1718             return SET_D3D_STATE(effect, SetNPatchMode, *(float *)param_value);
1719         case SC_SHADERCONST:
1720             TRACE("%s, index %u, op %u.\n", state_table[state->operation].name, state->index,
1721                 state_table[state->operation].op);
1722             return d3dx_set_shader_const_state(effect, state_table[state->operation].op, state->index,
1723                 param, param_value);
1724         default:
1725             FIXME("%s not handled.\n", state_table[state->operation].name);
1726             break;
1727     }
1728     return D3D_OK;
1729 }
1730 
1731 static HRESULT d3dx9_apply_pass_states(struct d3dx_effect *effect, struct d3dx_pass *pass, BOOL update_all)
1732 {
1733     unsigned int i;
1734     HRESULT ret;
1735     HRESULT hr;
1736     ULONG64 new_update_version = next_effect_update_version(effect);
1737 
1738     TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
1739 
1740     ret = D3D_OK;
1741     for (i = 0; i < pass->state_count; ++i)
1742     {
1743         if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u, update_all)))
1744         {
1745             WARN("Error applying state, hr %#x.\n", hr);
1746             ret = hr;
1747         }
1748     }
1749 
1750     if (effect->light_updated)
1751     {
1752         for (i = 0; i < ARRAY_SIZE(effect->current_light); ++i)
1753         {
1754             if ((effect->light_updated & (1u << i))
1755                     && FAILED(hr = SET_D3D_STATE(effect, SetLight, i, &effect->current_light[i])))
1756             {
1757                 WARN("Error setting light, hr %#x.\n", hr);
1758                 ret = hr;
1759             }
1760         }
1761         effect->light_updated = 0;
1762     }
1763 
1764     if (effect->material_updated
1765             && FAILED(hr = SET_D3D_STATE(effect, SetMaterial, &effect->current_material)))
1766     {
1767         WARN("Error setting material, hr %#x.\n", hr);
1768         ret = hr;
1769     }
1770     effect->material_updated = FALSE;
1771 
1772     pass->update_version = new_update_version;
1773     return ret;
1774 }
1775 
1776 static void param_set_data_pointer(struct d3dx_parameter *param, unsigned char *data, BOOL child, BOOL free_data)
1777 {
1778     unsigned char *member_data = data;
1779     unsigned int i, count;
1780 
1781     count = param->element_count ? param->element_count : param->member_count;
1782     for (i = 0; i < count; ++i)
1783     {
1784         param_set_data_pointer(&param->members[i], member_data, TRUE, free_data);
1785         if (data)
1786             member_data += param->members[i].bytes;
1787     }
1788     if (free_data)
1789         free_parameter_data(param, child);
1790     param->data = data;
1791 }
1792 
1793 static BOOL is_same_parameter(void *param1_, struct d3dx_parameter *param2)
1794 {
1795     struct d3dx_parameter *param1 = (struct d3dx_parameter *)param1_;
1796     BOOL matches;
1797     unsigned int i, member_count;
1798 
1799     matches = !strcmp(param1->name, param2->name) && param1->class == param2->class
1800             && param1->type == param2->type && param1->rows == param2->rows
1801             && param1->columns == param2->columns && param1->element_count == param2->element_count
1802             && param1->member_count == param2->member_count;
1803 
1804     member_count = param1->element_count ? param1->element_count : param1->member_count;
1805 
1806     if (!matches || !member_count)
1807         return matches;
1808 
1809     for (i = 0; i < member_count; ++i)
1810     {
1811         if (!is_same_parameter(&param1->members[i], &param2->members[i]))
1812             return FALSE;
1813     }
1814     return TRUE;
1815 }
1816 
1817 static HRESULT d3dx_pool_sync_shared_parameter(struct d3dx_effect_pool *pool, struct d3dx_top_level_parameter *param)
1818 {
1819     unsigned int i, free_entry_index;
1820     unsigned int new_size, new_count;
1821 
1822     if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !pool || is_param_type_sampler(param->param.type))
1823         return D3D_OK;
1824 
1825     free_entry_index = pool->size;
1826     for (i = 0; i < pool->size; ++i)
1827     {
1828         if (!pool->shared_data[i].count)
1829             free_entry_index = i;
1830         else if (is_same_parameter(&param->param, &pool->shared_data[i].parameters[0]->param))
1831             break;
1832     }
1833     if (i == pool->size)
1834     {
1835         i = free_entry_index;
1836         if (i == pool->size)
1837         {
1838             struct d3dx_shared_data *new_alloc;
1839 
1840             if (!pool->size)
1841             {
1842                 new_size = INITIAL_POOL_SIZE;
1843                 new_alloc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1844                         sizeof(*pool->shared_data) * new_size);
1845                 if (!new_alloc)
1846                 {
1847                     ERR("Out of memory.\n");
1848                     return E_OUTOFMEMORY;
1849                 }
1850             }
1851             else
1852             {
1853                 new_size = pool->size * 2;
1854                 new_alloc = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pool->shared_data,
1855                         sizeof(*pool->shared_data) * new_size);
1856                 if (!new_alloc)
1857                 {
1858                     ERR("Out of memory.\n");
1859                     return E_OUTOFMEMORY;
1860                 }
1861                 if (new_alloc != pool->shared_data)
1862                 {
1863                     unsigned int j, k;
1864 
1865                     for (j = 0; j < pool->size; ++j)
1866                         for (k = 0; k < new_alloc[j].count; ++k)
1867                             new_alloc[j].parameters[k]->shared_data = &new_alloc[j];
1868                 }
1869             }
1870             pool->shared_data = new_alloc;
1871             pool->size = new_size;
1872         }
1873         pool->shared_data[i].data = param->param.data;
1874     }
1875     else
1876     {
1877         param_set_data_pointer(&param->param, pool->shared_data[i].data, FALSE, TRUE);
1878     }
1879     new_count = ++pool->shared_data[i].count;
1880     if (new_count >= pool->shared_data[i].size)
1881     {
1882         if (!pool->shared_data[i].size)
1883         {
1884             new_size = INITIAL_SHARED_DATA_SIZE;
1885             pool->shared_data[i].parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1886                     sizeof(*pool->shared_data[i].parameters) * INITIAL_SHARED_DATA_SIZE);
1887         }
1888         else
1889         {
1890             new_size = pool->shared_data[i].size * 2;
1891             pool->shared_data[i].parameters = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1892                     pool->shared_data[i].parameters,
1893                     sizeof(*pool->shared_data[i].parameters) * new_size);
1894         }
1895         pool->shared_data[i].size = new_size;
1896     }
1897 
1898     param->shared_data = &pool->shared_data[i];
1899     pool->shared_data[i].parameters[new_count - 1] = param;
1900 
1901     TRACE("name %s, parameter idx %u, new refcount %u.\n", debugstr_a(param->param.name), i,
1902             new_count);
1903 
1904     return D3D_OK;
1905 }
1906 
1907 static BOOL param_zero_data_func(void *dummy, struct d3dx_parameter *param)
1908 {
1909     param->data = NULL;
1910     return FALSE;
1911 }
1912 
1913 static void d3dx_pool_release_shared_parameter(struct d3dx_top_level_parameter *param)
1914 {
1915     unsigned int new_count;
1916 
1917     if (!(param->param.flags & PARAMETER_FLAG_SHARED) || !param->shared_data)
1918         return;
1919     new_count = --param->shared_data->count;
1920 
1921     TRACE("param %p, param->shared_data %p, new_count %d.\n", param, param->shared_data, new_count);
1922 
1923     if (new_count)
1924     {
1925         unsigned int i;
1926 
1927         for (i = 0; i < new_count; ++i)
1928         {
1929             if (param->shared_data->parameters[i] == param)
1930             {
1931                 memmove(&param->shared_data->parameters[i],
1932                         &param->shared_data->parameters[i + 1],
1933                         sizeof(param->shared_data->parameters[i]) * (new_count - i));
1934                 break;
1935             }
1936         }
1937         walk_parameter_tree(&param->param, param_zero_data_func, NULL);
1938     }
1939     else
1940     {
1941         HeapFree(GetProcessHeap(), 0, param->shared_data->parameters);
1942         /* Zeroing table size is required as the entry in pool parameters table can be reused. */
1943         param->shared_data->size = 0;
1944         param->shared_data = NULL;
1945     }
1946 }
1947 
1948 static inline struct d3dx_effect_pool *impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
1949 {
1950     return CONTAINING_RECORD(iface, struct d3dx_effect_pool, ID3DXEffectPool_iface);
1951 }
1952 
1953 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface);
1954 
1955 static inline struct d3dx_effect *impl_from_ID3DXEffect(ID3DXEffect *iface)
1956 {
1957     return CONTAINING_RECORD(iface, struct d3dx_effect, ID3DXEffect_iface);
1958 }
1959 
1960 /*** IUnknown methods ***/
1961 static HRESULT WINAPI d3dx_effect_QueryInterface(ID3DXEffect *iface, REFIID riid, void **object)
1962 {
1963     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), object);
1964 
1965     if (IsEqualGUID(riid, &IID_IUnknown) ||
1966         IsEqualGUID(riid, &IID_ID3DXEffect))
1967     {
1968         iface->lpVtbl->AddRef(iface);
1969         *object = iface;
1970         return S_OK;
1971     }
1972 
1973     ERR("Interface %s not found\n", debugstr_guid(riid));
1974 
1975     return E_NOINTERFACE;
1976 }
1977 
1978 static ULONG WINAPI d3dx_effect_AddRef(ID3DXEffect *iface)
1979 {
1980     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
1981 
1982     TRACE("(%p)->(): AddRef from %u\n", This, This->ref);
1983 
1984     return InterlockedIncrement(&This->ref);
1985 }
1986 
1987 static ULONG WINAPI d3dx_effect_Release(ID3DXEffect *iface)
1988 {
1989     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
1990     ULONG refcount = InterlockedDecrement(&effect->ref);
1991 
1992     TRACE("%p decreasing refcount to %u.\n", effect, refcount);
1993 
1994     if (!refcount)
1995         d3dx_effect_cleanup(effect);
1996 
1997     return refcount;
1998 }
1999 
2000 /*** ID3DXBaseEffect methods ***/
2001 static HRESULT WINAPI d3dx_effect_GetDesc(ID3DXEffect *iface, D3DXEFFECT_DESC *desc)
2002 {
2003     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2004 
2005     FIXME("iface %p, desc %p partial stub.\n", iface, desc);
2006 
2007     if (!desc)
2008     {
2009         WARN("Invalid argument specified.\n");
2010         return D3DERR_INVALIDCALL;
2011     }
2012 
2013     /* TODO: add creator and function count. */
2014     desc->Creator = NULL;
2015     desc->Functions = 0;
2016     desc->Parameters = effect->parameter_count;
2017     desc->Techniques = effect->technique_count;
2018 
2019     return D3D_OK;
2020 }
2021 
2022 static HRESULT WINAPI d3dx_effect_GetParameterDesc(ID3DXEffect *iface, D3DXHANDLE parameter,
2023         D3DXPARAMETER_DESC *desc)
2024 {
2025     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2026     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2027 
2028     TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc);
2029 
2030     if (!desc || !param)
2031     {
2032         WARN("Invalid argument specified.\n");
2033         return D3DERR_INVALIDCALL;
2034     }
2035 
2036     desc->Name = param->name;
2037     desc->Semantic = param->semantic;
2038     desc->Class = param->class;
2039     desc->Type = param->type;
2040     desc->Rows = param->rows;
2041     desc->Columns = param->columns;
2042     desc->Elements = param->element_count;
2043     desc->Annotations = is_top_level_parameter(param)
2044             ? top_level_parameter_from_parameter(param)->annotation_count : 0;
2045     desc->StructMembers = param->member_count;
2046     desc->Flags = param->flags;
2047     desc->Bytes = param->bytes;
2048 
2049     return D3D_OK;
2050 }
2051 
2052 static HRESULT WINAPI d3dx_effect_GetTechniqueDesc(ID3DXEffect *iface, D3DXHANDLE technique,
2053         D3DXTECHNIQUE_DESC *desc)
2054 {
2055     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2056     struct d3dx_technique *tech = technique ? get_valid_technique(effect, technique) : &effect->techniques[0];
2057 
2058     TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc);
2059 
2060     if (!desc || !tech)
2061     {
2062         WARN("Invalid argument specified.\n");
2063         return D3DERR_INVALIDCALL;
2064     }
2065 
2066     desc->Name = tech->name;
2067     desc->Passes = tech->pass_count;
2068     desc->Annotations = tech->annotation_count;
2069 
2070     return D3D_OK;
2071 }
2072 
2073 static HRESULT WINAPI d3dx_effect_GetPassDesc(ID3DXEffect *iface, D3DXHANDLE pass_handle, D3DXPASS_DESC *desc)
2074 {
2075     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2076     struct d3dx_pass *pass = get_valid_pass(effect, pass_handle);
2077     unsigned int i;
2078 
2079     TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc);
2080 
2081     if (!desc || !pass)
2082     {
2083         WARN("Invalid argument specified.\n");
2084         return D3DERR_INVALIDCALL;
2085     }
2086 
2087     desc->Name = pass->name;
2088     desc->Annotations = pass->annotation_count;
2089 
2090     desc->pVertexShaderFunction = NULL;
2091     desc->pPixelShaderFunction = NULL;
2092 
2093     if (effect->flags & D3DXFX_NOT_CLONEABLE)
2094         return D3D_OK;
2095 
2096     for (i = 0; i < pass->state_count; ++i)
2097     {
2098         struct d3dx_state *state = &pass->states[i];
2099 
2100         if (state_table[state->operation].class == SC_VERTEXSHADER
2101                 || state_table[state->operation].class == SC_PIXELSHADER)
2102         {
2103             struct d3dx_parameter *param;
2104             void *param_value;
2105             BOOL param_dirty;
2106             HRESULT hr;
2107             void *data;
2108 
2109             if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[i], &param_value, &param,
2110                     FALSE, &param_dirty)))
2111                 return hr;
2112 
2113             data = param->object_id ? effect->objects[param->object_id].data : NULL;
2114             if (state_table[state->operation].class == SC_VERTEXSHADER)
2115                 desc->pVertexShaderFunction = data;
2116             else
2117                 desc->pPixelShaderFunction = data;
2118         }
2119     }
2120 
2121     return D3D_OK;
2122 }
2123 
2124 static HRESULT WINAPI d3dx_effect_GetFunctionDesc(ID3DXEffect *iface, D3DXHANDLE shader,
2125         D3DXFUNCTION_DESC *desc)
2126 {
2127     FIXME("iface %p, shader %p, desc %p stub.\n", iface, shader, desc);
2128 
2129     return E_NOTIMPL;
2130 }
2131 
2132 static D3DXHANDLE WINAPI d3dx_effect_GetParameter(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2133 {
2134     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2135     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2136 
2137     TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2138 
2139     if (!parameter)
2140     {
2141         if (index < effect->parameter_count)
2142         {
2143             TRACE("Returning parameter %p.\n", &effect->parameters[index]);
2144             return get_parameter_handle(&effect->parameters[index].param);
2145         }
2146     }
2147     else
2148     {
2149         if (param && !param->element_count && index < param->member_count)
2150         {
2151             TRACE("Returning parameter %p.\n", &param->members[index]);
2152             return get_parameter_handle(&param->members[index]);
2153         }
2154     }
2155 
2156     WARN("Parameter not found.\n");
2157 
2158     return NULL;
2159 }
2160 
2161 static D3DXHANDLE WINAPI d3dx_effect_GetParameterByName(ID3DXEffect *iface, D3DXHANDLE parameter,
2162         const char *name)
2163 {
2164     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2165     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2166     D3DXHANDLE handle;
2167 
2168     TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name));
2169 
2170     if (!name)
2171     {
2172         handle = get_parameter_handle(param);
2173         TRACE("Returning parameter %p.\n", handle);
2174         return handle;
2175     }
2176 
2177     handle = get_parameter_handle(get_parameter_by_name(effect, param, name));
2178     TRACE("Returning parameter %p.\n", handle);
2179 
2180     return handle;
2181 }
2182 
2183 static D3DXHANDLE WINAPI d3dx_effect_GetParameterBySemantic(ID3DXEffect *iface, D3DXHANDLE parameter,
2184         const char *semantic)
2185 {
2186     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2187     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2188     struct d3dx_parameter *temp_param;
2189     unsigned int i;
2190 
2191     TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic));
2192 
2193     if (!parameter)
2194     {
2195         for (i = 0; i < effect->parameter_count; ++i)
2196         {
2197             temp_param = &effect->parameters[i].param;
2198 
2199             if (!temp_param->semantic)
2200             {
2201                 if (!semantic)
2202                 {
2203                     TRACE("Returning parameter %p\n", temp_param);
2204                     return get_parameter_handle(temp_param);
2205                 }
2206                 continue;
2207             }
2208 
2209             if (!_strnicmp(temp_param->semantic, semantic, -1))
2210             {
2211                 TRACE("Returning parameter %p\n", temp_param);
2212                 return get_parameter_handle(temp_param);
2213             }
2214         }
2215     }
2216     else if (param)
2217     {
2218         for (i = 0; i < param->member_count; ++i)
2219         {
2220             temp_param = &param->members[i];
2221 
2222             if (!temp_param->semantic)
2223             {
2224                 if (!semantic)
2225                 {
2226                     TRACE("Returning parameter %p\n", temp_param);
2227                     return get_parameter_handle(temp_param);
2228                 }
2229                 continue;
2230             }
2231 
2232             if (!_strnicmp(temp_param->semantic, semantic, -1))
2233             {
2234                 TRACE("Returning parameter %p\n", temp_param);
2235                 return get_parameter_handle(temp_param);
2236             }
2237         }
2238     }
2239 
2240     WARN("Parameter not found.\n");
2241 
2242     return NULL;
2243 }
2244 
2245 static D3DXHANDLE WINAPI d3dx_effect_GetParameterElement(ID3DXEffect *iface, D3DXHANDLE parameter, UINT index)
2246 {
2247     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2248     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2249 
2250     TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index);
2251 
2252     if (!param)
2253     {
2254         if (index < effect->parameter_count)
2255         {
2256             TRACE("Returning parameter %p.\n", &effect->parameters[index]);
2257             return get_parameter_handle(&effect->parameters[index].param);
2258         }
2259     }
2260     else
2261     {
2262         if (index < param->element_count)
2263         {
2264             TRACE("Returning parameter %p.\n", &param->members[index]);
2265             return get_parameter_handle(&param->members[index]);
2266         }
2267     }
2268 
2269     WARN("Parameter not found.\n");
2270 
2271     return NULL;
2272 }
2273 
2274 static D3DXHANDLE WINAPI d3dx_effect_GetTechnique(ID3DXEffect *iface, UINT index)
2275 {
2276     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2277 
2278     TRACE("iface %p, index %u.\n", iface, index);
2279 
2280     if (index >= effect->technique_count)
2281     {
2282         WARN("Invalid argument specified.\n");
2283         return NULL;
2284     }
2285 
2286     TRACE("Returning technique %p.\n", &effect->techniques[index]);
2287 
2288     return get_technique_handle(&effect->techniques[index]);
2289 }
2290 
2291 static D3DXHANDLE WINAPI d3dx_effect_GetTechniqueByName(ID3DXEffect *iface, const char *name)
2292 {
2293     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2294     struct d3dx_technique *tech = get_technique_by_name(effect, name);
2295 
2296     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
2297 
2298     if (tech)
2299     {
2300         D3DXHANDLE t = get_technique_handle(tech);
2301         TRACE("Returning technique %p\n", t);
2302         return t;
2303     }
2304 
2305     WARN("Technique not found.\n");
2306 
2307     return NULL;
2308 }
2309 
2310 static D3DXHANDLE WINAPI d3dx_effect_GetPass(ID3DXEffect *iface, D3DXHANDLE technique, UINT index)
2311 {
2312     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2313     struct d3dx_technique *tech = get_valid_technique(effect, technique);
2314 
2315     TRACE("iface %p, technique %p, index %u.\n", iface, technique, index);
2316 
2317     if (tech && index < tech->pass_count)
2318     {
2319         TRACE("Returning pass %p\n", &tech->passes[index]);
2320         return get_pass_handle(&tech->passes[index]);
2321     }
2322 
2323     WARN("Pass not found.\n");
2324 
2325     return NULL;
2326 }
2327 
2328 static D3DXHANDLE WINAPI d3dx_effect_GetPassByName(ID3DXEffect *iface, D3DXHANDLE technique, const char *name)
2329 {
2330     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2331     struct d3dx_technique *tech = get_valid_technique(effect, technique);
2332 
2333     TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name));
2334 
2335     if (tech && name)
2336     {
2337         unsigned int i;
2338 
2339         for (i = 0; i < tech->pass_count; ++i)
2340         {
2341             struct d3dx_pass *pass = &tech->passes[i];
2342 
2343             if (!strcmp(pass->name, name))
2344             {
2345                 TRACE("Returning pass %p\n", pass);
2346                 return get_pass_handle(pass);
2347             }
2348         }
2349     }
2350 
2351     WARN("Pass not found.\n");
2352 
2353     return NULL;
2354 }
2355 
2356 static D3DXHANDLE WINAPI d3dx_effect_GetFunction(ID3DXEffect *iface, UINT index)
2357 {
2358     FIXME("iface %p, index %u stub.\n", iface, index);
2359 
2360     return NULL;
2361 }
2362 
2363 static D3DXHANDLE WINAPI d3dx_effect_GetFunctionByName(ID3DXEffect *iface, const char *name)
2364 {
2365     FIXME("iface %p, name %s stub.\n", iface, debugstr_a(name));
2366 
2367     return NULL;
2368 }
2369 
2370 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotation(ID3DXEffect *iface, D3DXHANDLE object, UINT index)
2371 {
2372     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2373     struct d3dx_parameter *annotations = NULL;
2374     unsigned int annotation_count;
2375 
2376     TRACE("iface %p, object %p, index %u.\n", iface, object, index);
2377 
2378     annotation_count = get_annotation_from_object(effect, object, &annotations);
2379 
2380     if (index < annotation_count)
2381     {
2382         TRACE("Returning parameter %p\n", &annotations[index]);
2383         return get_parameter_handle(&annotations[index]);
2384     }
2385 
2386     WARN("Annotation not found.\n");
2387 
2388     return NULL;
2389 }
2390 
2391 static D3DXHANDLE WINAPI d3dx_effect_GetAnnotationByName(ID3DXEffect *iface, D3DXHANDLE object,
2392         const char *name)
2393 {
2394     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2395     struct d3dx_parameter *annotation = NULL;
2396     struct d3dx_parameter *annotations = NULL;
2397     unsigned int annotation_count;
2398 
2399     TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name));
2400 
2401     if (!name)
2402     {
2403         WARN("Invalid argument specified\n");
2404         return NULL;
2405     }
2406 
2407     annotation_count = get_annotation_from_object(effect, object, &annotations);
2408 
2409     annotation = get_annotation_by_name(effect, annotation_count, annotations, name);
2410     if (annotation)
2411     {
2412         TRACE("Returning parameter %p\n", annotation);
2413         return get_parameter_handle(annotation);
2414     }
2415 
2416     WARN("Annotation not found.\n");
2417 
2418     return NULL;
2419 }
2420 
2421 static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parameter,
2422         const void *data, UINT bytes)
2423 {
2424     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2425     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2426 
2427     TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2428 
2429     if (!param)
2430     {
2431         WARN("Invalid parameter %p specified.\n", parameter);
2432         return D3DERR_INVALIDCALL;
2433     }
2434     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2435     {
2436         WARN("Parameter is a sampler, returning E_FAIL.\n");
2437         return E_FAIL;
2438     }
2439 
2440     if (data && param->bytes <= bytes)
2441         return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
2442 
2443     WARN("Invalid argument specified.\n");
2444 
2445     return D3DERR_INVALIDCALL;
2446 }
2447 
2448 static HRESULT WINAPI d3dx_effect_GetValue(ID3DXEffect *iface, D3DXHANDLE parameter, void *data, UINT bytes)
2449 {
2450     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2451     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2452 
2453     TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes);
2454 
2455     if (!param)
2456     {
2457         WARN("Invalid parameter %p specified.\n", parameter);
2458         return D3DERR_INVALIDCALL;
2459     }
2460     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
2461     {
2462         WARN("Parameter is a sampler, returning E_FAIL.\n");
2463         return E_FAIL;
2464     }
2465 
2466     if (data && param->bytes <= bytes)
2467     {
2468         TRACE("Type %s.\n", debug_d3dxparameter_type(param->type));
2469 
2470         switch (param->type)
2471         {
2472             case D3DXPT_VOID:
2473             case D3DXPT_BOOL:
2474             case D3DXPT_INT:
2475             case D3DXPT_FLOAT:
2476             case D3DXPT_STRING:
2477                 break;
2478 
2479             case D3DXPT_VERTEXSHADER:
2480             case D3DXPT_PIXELSHADER:
2481             case D3DXPT_TEXTURE:
2482             case D3DXPT_TEXTURE1D:
2483             case D3DXPT_TEXTURE2D:
2484             case D3DXPT_TEXTURE3D:
2485             case D3DXPT_TEXTURECUBE:
2486             {
2487                 unsigned int i;
2488 
2489                 for (i = 0; i < (param->element_count ? param->element_count : 1); ++i)
2490                 {
2491                     IUnknown *unk = ((IUnknown **)param->data)[i];
2492                     if (unk)
2493                         IUnknown_AddRef(unk);
2494                 }
2495                 break;
2496             }
2497 
2498             default:
2499                 FIXME("Unhandled type %s.\n", debug_d3dxparameter_type(param->type));
2500                 break;
2501         }
2502 
2503         TRACE("Copy %u bytes.\n", param->bytes);
2504         memcpy(data, param->data, param->bytes);
2505         return D3D_OK;
2506     }
2507 
2508     WARN("Parameter not found.\n");
2509 
2510     return D3DERR_INVALIDCALL;
2511 }
2512 
2513 static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL b)
2514 {
2515     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2516     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2517 
2518     TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b);
2519 
2520     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2521     {
2522         set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
2523                 param->type, &b, D3DXPT_BOOL);
2524         return D3D_OK;
2525     }
2526 
2527     WARN("Parameter not found.\n");
2528 
2529     return D3DERR_INVALIDCALL;
2530 }
2531 
2532 static HRESULT WINAPI d3dx_effect_GetBool(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b)
2533 {
2534     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2535     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2536 
2537     TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b);
2538 
2539     if (b && param && !param->element_count && param->rows == 1 && param->columns == 1)
2540     {
2541         set_number(b, D3DXPT_BOOL, param->data, param->type);
2542         TRACE("Returning %s\n", *b ? "TRUE" : "FALSE");
2543         return D3D_OK;
2544     }
2545 
2546     WARN("Parameter not found.\n");
2547 
2548     return D3DERR_INVALIDCALL;
2549 }
2550 
2551 static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, const BOOL *b, UINT count)
2552 {
2553     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2554     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2555     DWORD *data;
2556 
2557     TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2558 
2559     if (param)
2560     {
2561         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2562 
2563         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2564 
2565         switch (param->class)
2566         {
2567             case D3DXPC_SCALAR:
2568             case D3DXPC_VECTOR:
2569             case D3DXPC_MATRIX_ROWS:
2570                 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2571                 for (i = 0; i < size; ++i)
2572                 {
2573                     /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
2574                     set_number(data + i, param->type, &b[i], D3DXPT_INT);
2575                 }
2576                 return D3D_OK;
2577 
2578             case D3DXPC_OBJECT:
2579             case D3DXPC_STRUCT:
2580                 break;
2581 
2582             default:
2583                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2584                 break;
2585         }
2586     }
2587 
2588     WARN("Parameter not found.\n");
2589 
2590     return D3DERR_INVALIDCALL;
2591 }
2592 
2593 static HRESULT WINAPI d3dx_effect_GetBoolArray(ID3DXEffect *iface, D3DXHANDLE parameter, BOOL *b, UINT count)
2594 {
2595     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2596     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2597 
2598     TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
2599 
2600     if (b && param && (param->class == D3DXPC_SCALAR
2601             || param->class == D3DXPC_VECTOR
2602             || param->class == D3DXPC_MATRIX_ROWS
2603             || param->class == D3DXPC_MATRIX_COLUMNS))
2604     {
2605         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2606 
2607         for (i = 0; i < size; ++i)
2608         {
2609             set_number(&b[i], D3DXPT_BOOL, (DWORD *)param->data + i, param->type);
2610         }
2611         return D3D_OK;
2612     }
2613 
2614     WARN("Parameter not found.\n");
2615 
2616     return D3DERR_INVALIDCALL;
2617 }
2618 
2619 static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT n)
2620 {
2621     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2622     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2623 
2624     TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n);
2625 
2626     if (param && !param->element_count)
2627     {
2628         if (param->rows == 1 && param->columns == 1)
2629         {
2630             DWORD value;
2631 
2632             set_number(&value, param->type, &n, D3DXPT_INT);
2633             *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
2634                     value != *(DWORD *)param->data) = value;
2635             return D3D_OK;
2636         }
2637 
2638         /* Split the value if parameter is a vector with dimension 3 or 4. */
2639         if (param->type == D3DXPT_FLOAT
2640                 && ((param->class == D3DXPC_VECTOR && param->columns != 2)
2641                 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2642         {
2643             float *data;
2644 
2645             TRACE("Vector fixup.\n");
2646 
2647             data = param_get_data_and_dirtify(effect, param,
2648                     min(4, param->rows * param->columns) * sizeof(float), TRUE);
2649 
2650             data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2651             data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2652             data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
2653             if (param->rows * param->columns > 3)
2654                 data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2655 
2656             return D3D_OK;
2657         }
2658     }
2659 
2660     WARN("Parameter not found.\n");
2661 
2662     return D3DERR_INVALIDCALL;
2663 }
2664 
2665 static HRESULT WINAPI d3dx_effect_GetInt(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n)
2666 {
2667     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2668     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2669 
2670     TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n);
2671 
2672     if (n && param && !param->element_count)
2673     {
2674         if (param->columns == 1 && param->rows == 1)
2675         {
2676             set_number(n, D3DXPT_INT, param->data, param->type);
2677             TRACE("Returning %d.\n", *n);
2678             return D3D_OK;
2679         }
2680 
2681         if (param->type == D3DXPT_FLOAT &&
2682                 ((param->class == D3DXPC_VECTOR && param->columns != 2)
2683                 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
2684         {
2685             TRACE("Vector fixup.\n");
2686 
2687             *n = min(max(0.0f, *((float *)param->data + 2)), 1.0f) * INT_FLOAT_MULTI;
2688             *n += ((int)(min(max(0.0f, *((float *)param->data + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8;
2689             *n += ((int)(min(max(0.0f, *((float *)param->data + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16;
2690             if (param->columns * param->rows > 3)
2691                 *n += ((int)(min(max(0.0f, *((float *)param->data + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24;
2692 
2693             TRACE("Returning %d.\n", *n);
2694             return D3D_OK;
2695         }
2696     }
2697 
2698     WARN("Parameter not found.\n");
2699 
2700     return D3DERR_INVALIDCALL;
2701 }
2702 
2703 static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, const INT *n, UINT count)
2704 {
2705     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2706     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2707     DWORD *data;
2708 
2709     TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2710 
2711     if (param)
2712     {
2713         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2714 
2715         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2716 
2717         switch (param->class)
2718         {
2719             case D3DXPC_SCALAR:
2720             case D3DXPC_VECTOR:
2721             case D3DXPC_MATRIX_ROWS:
2722                 data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
2723                 for (i = 0; i < size; ++i)
2724                     set_number(data + i, param->type, &n[i], D3DXPT_INT);
2725                 return D3D_OK;
2726 
2727             case D3DXPC_OBJECT:
2728             case D3DXPC_STRUCT:
2729                 break;
2730 
2731             default:
2732                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2733                 break;
2734         }
2735     }
2736 
2737     WARN("Parameter not found.\n");
2738 
2739     return D3DERR_INVALIDCALL;
2740 }
2741 
2742 static HRESULT WINAPI d3dx_effect_GetIntArray(ID3DXEffect *iface, D3DXHANDLE parameter, INT *n, UINT count)
2743 {
2744     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2745     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2746 
2747     TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
2748 
2749     if (n && param && (param->class == D3DXPC_SCALAR
2750             || param->class == D3DXPC_VECTOR
2751             || param->class == D3DXPC_MATRIX_ROWS
2752             || param->class == D3DXPC_MATRIX_COLUMNS))
2753     {
2754         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2755 
2756         for (i = 0; i < size; ++i)
2757             set_number(&n[i], D3DXPT_INT, (DWORD *)param->data + i, param->type);
2758         return D3D_OK;
2759     }
2760 
2761     WARN("Parameter not found.\n");
2762 
2763     return D3DERR_INVALIDCALL;
2764 }
2765 
2766 static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float f)
2767 {
2768     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2769     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2770 
2771     TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f);
2772 
2773     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
2774     {
2775         DWORD value;
2776 
2777         set_number(&value, param->type, &f, D3DXPT_FLOAT);
2778         *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
2779                 value != *(DWORD *)param->data) = value;
2780         return D3D_OK;
2781     }
2782 
2783     WARN("Parameter not found.\n");
2784 
2785     return D3DERR_INVALIDCALL;
2786 }
2787 
2788 static HRESULT WINAPI d3dx_effect_GetFloat(ID3DXEffect *iface, D3DXHANDLE parameter, float *f)
2789 {
2790     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2791     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2792 
2793     TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f);
2794 
2795     if (f && param && !param->element_count && param->columns == 1 && param->rows == 1)
2796     {
2797         set_number(f, D3DXPT_FLOAT, (DWORD *)param->data, param->type);
2798         TRACE("Returning %f.\n", *f);
2799         return D3D_OK;
2800     }
2801 
2802     WARN("Parameter not found.\n");
2803 
2804     return D3DERR_INVALIDCALL;
2805 }
2806 
2807 static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2808         const float *f, UINT count)
2809 {
2810     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2811     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2812     DWORD *data;
2813 
2814     TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2815 
2816     if (param)
2817     {
2818         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2819 
2820         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2821 
2822         switch (param->class)
2823         {
2824             case D3DXPC_SCALAR:
2825             case D3DXPC_VECTOR:
2826             case D3DXPC_MATRIX_ROWS:
2827                 data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
2828                 for (i = 0; i < size; ++i)
2829                     set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
2830                 return D3D_OK;
2831 
2832             case D3DXPC_OBJECT:
2833             case D3DXPC_STRUCT:
2834                 break;
2835 
2836             default:
2837                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2838                 break;
2839         }
2840     }
2841 
2842     WARN("Parameter not found.\n");
2843 
2844     return D3DERR_INVALIDCALL;
2845 }
2846 
2847 static HRESULT WINAPI d3dx_effect_GetFloatArray(ID3DXEffect *iface, D3DXHANDLE parameter, float *f, UINT count)
2848 {
2849     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2850     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2851 
2852     TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
2853 
2854     if (f && param && (param->class == D3DXPC_SCALAR
2855             || param->class == D3DXPC_VECTOR
2856             || param->class == D3DXPC_MATRIX_ROWS
2857             || param->class == D3DXPC_MATRIX_COLUMNS))
2858     {
2859         unsigned int i, size = min(count, param->bytes / sizeof(DWORD));
2860 
2861         for (i = 0; i < size; ++i)
2862             set_number(&f[i], D3DXPT_FLOAT, (DWORD *)param->data + i, param->type);
2863         return D3D_OK;
2864     }
2865 
2866     WARN("Parameter not found.\n");
2867 
2868     return D3DERR_INVALIDCALL;
2869 }
2870 
2871 static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
2872 {
2873     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2874     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2875 
2876     TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2877 
2878     if (param && !param->element_count)
2879     {
2880         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2881 
2882         switch (param->class)
2883         {
2884             case D3DXPC_SCALAR:
2885             case D3DXPC_VECTOR:
2886                 if (param->type == D3DXPT_INT && param->bytes == 4)
2887                 {
2888                     DWORD tmp;
2889 
2890                     TRACE("INT fixup.\n");
2891                     tmp = max(min(vector->z, 1.0f), 0.0f) * INT_FLOAT_MULTI;
2892                     tmp += ((DWORD)(max(min(vector->y, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8;
2893                     tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
2894                     tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
2895 
2896                     *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
2897                     return D3D_OK;
2898                 }
2899                 if (param->type == D3DXPT_FLOAT)
2900                 {
2901                     memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
2902                             vector, param->columns * sizeof(float));
2903                     return D3D_OK;
2904                 }
2905 
2906                 set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
2907                 return D3D_OK;
2908 
2909             case D3DXPC_MATRIX_ROWS:
2910             case D3DXPC_OBJECT:
2911             case D3DXPC_STRUCT:
2912                 break;
2913 
2914             default:
2915                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2916                 break;
2917         }
2918     }
2919 
2920     WARN("Parameter not found.\n");
2921 
2922     return D3DERR_INVALIDCALL;
2923 }
2924 
2925 static HRESULT WINAPI d3dx_effect_GetVector(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector)
2926 {
2927     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2928     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2929 
2930     TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector);
2931 
2932     if (vector && param && !param->element_count)
2933     {
2934         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2935 
2936         switch (param->class)
2937         {
2938             case D3DXPC_SCALAR:
2939             case D3DXPC_VECTOR:
2940                 if (param->type == D3DXPT_INT && param->bytes == 4)
2941                 {
2942                     TRACE("INT fixup.\n");
2943                     vector->x = (((*(int *)param->data) & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
2944                     vector->y = (((*(int *)param->data) & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
2945                     vector->z = ((*(int *)param->data) & 0xff) * INT_FLOAT_MULTI_INVERSE;
2946                     vector->w = (((*(int *)param->data) & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
2947                     return D3D_OK;
2948                 }
2949                 get_vector(param, vector);
2950                 return D3D_OK;
2951 
2952             case D3DXPC_MATRIX_ROWS:
2953             case D3DXPC_OBJECT:
2954             case D3DXPC_STRUCT:
2955                 break;
2956 
2957             default:
2958                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
2959                 break;
2960         }
2961     }
2962 
2963     WARN("Parameter not found.\n");
2964 
2965     return D3DERR_INVALIDCALL;
2966 }
2967 
2968 static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
2969         const D3DXVECTOR4 *vector, UINT count)
2970 {
2971     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
2972     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
2973 
2974     TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
2975 
2976     if (param && param->element_count && param->element_count >= count)
2977     {
2978         unsigned int i;
2979         BYTE *data;
2980 
2981         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
2982 
2983         switch (param->class)
2984         {
2985             case D3DXPC_VECTOR:
2986                 data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
2987 
2988                 if (param->type == D3DXPT_FLOAT)
2989                 {
2990                     if (param->columns == 4)
2991                     {
2992                         memcpy(data, vector, count * 4 * sizeof(float));
2993                     }
2994                     else
2995                     {
2996                         for (i = 0; i < count; ++i)
2997                             memcpy((float *)data + param->columns * i, vector + i,
2998                                     param->columns * sizeof(float));
2999                     }
3000                     return D3D_OK;
3001                 }
3002 
3003                 for (i = 0; i < count; ++i)
3004                     set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
3005 
3006                 return D3D_OK;
3007 
3008             case D3DXPC_SCALAR:
3009             case D3DXPC_MATRIX_ROWS:
3010             case D3DXPC_OBJECT:
3011             case D3DXPC_STRUCT:
3012                 break;
3013 
3014             default:
3015                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3016                 break;
3017         }
3018     }
3019 
3020     WARN("Parameter not found.\n");
3021 
3022     return D3DERR_INVALIDCALL;
3023 }
3024 
3025 static HRESULT WINAPI d3dx_effect_GetVectorArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3026         D3DXVECTOR4 *vector, UINT count)
3027 {
3028     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3029     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3030 
3031     TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count);
3032 
3033     if (!count)
3034         return D3D_OK;
3035 
3036     if (vector && param && count <= param->element_count)
3037     {
3038         unsigned int i;
3039 
3040         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3041 
3042         switch (param->class)
3043         {
3044             case D3DXPC_VECTOR:
3045                 for (i = 0; i < count; ++i)
3046                     get_vector(&param->members[i], &vector[i]);
3047                 return D3D_OK;
3048 
3049             case D3DXPC_SCALAR:
3050             case D3DXPC_MATRIX_ROWS:
3051             case D3DXPC_OBJECT:
3052             case D3DXPC_STRUCT:
3053                 break;
3054 
3055             default:
3056                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3057                 break;
3058         }
3059     }
3060 
3061     WARN("Parameter not found.\n");
3062 
3063     return D3DERR_INVALIDCALL;
3064 }
3065 
3066 static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix)
3067 {
3068     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3069     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3070 
3071     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3072 
3073     if (param && !param->element_count)
3074     {
3075         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3076 
3077         switch (param->class)
3078         {
3079             case D3DXPC_MATRIX_ROWS:
3080                 set_matrix(param, matrix, param_get_data_and_dirtify(effect, param,
3081                         param->rows * param->columns * sizeof(float), TRUE));
3082                 return D3D_OK;
3083 
3084             case D3DXPC_SCALAR:
3085             case D3DXPC_VECTOR:
3086             case D3DXPC_OBJECT:
3087             case D3DXPC_STRUCT:
3088                 break;
3089 
3090             default:
3091                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3092                 break;
3093         }
3094     }
3095 
3096     WARN("Parameter not found.\n");
3097 
3098     return D3DERR_INVALIDCALL;
3099 }
3100 
3101 static HRESULT WINAPI d3dx_effect_GetMatrix(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix)
3102 {
3103     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3104     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3105 
3106     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3107 
3108     if (matrix && param && !param->element_count)
3109     {
3110         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3111 
3112         switch (param->class)
3113         {
3114             case D3DXPC_MATRIX_ROWS:
3115                 get_matrix(param, matrix, FALSE);
3116                 return D3D_OK;
3117 
3118             case D3DXPC_SCALAR:
3119             case D3DXPC_VECTOR:
3120             case D3DXPC_OBJECT:
3121             case D3DXPC_STRUCT:
3122                 break;
3123 
3124             default:
3125                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3126                 break;
3127         }
3128     }
3129 
3130     WARN("Parameter not found.\n");
3131 
3132     return D3DERR_INVALIDCALL;
3133 }
3134 
3135 static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3136         const D3DXMATRIX *matrix, UINT count)
3137 {
3138     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3139     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3140 
3141     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3142 
3143     if (param && param->element_count >= count)
3144     {
3145         unsigned int i;
3146         BYTE *data;
3147 
3148         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3149 
3150         switch (param->class)
3151         {
3152             case D3DXPC_MATRIX_ROWS:
3153                 data = param_get_data_and_dirtify(effect, param, count * param->rows
3154                         * param->columns * sizeof(float), TRUE);
3155 
3156                 for (i = 0; i < count; ++i)
3157                     set_matrix(&param->members[i], &matrix[i],
3158                             data + i * param->rows * param->columns * sizeof(float));
3159 
3160                 return D3D_OK;
3161 
3162             case D3DXPC_SCALAR:
3163             case D3DXPC_VECTOR:
3164             case D3DXPC_OBJECT:
3165             case D3DXPC_STRUCT:
3166                 break;
3167 
3168             default:
3169                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3170                 break;
3171         }
3172     }
3173 
3174     WARN("Parameter not found.\n");
3175 
3176     return D3DERR_INVALIDCALL;
3177 }
3178 
3179 static HRESULT WINAPI d3dx_effect_GetMatrixArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3180         D3DXMATRIX *matrix, UINT count)
3181 {
3182     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3183     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3184 
3185     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3186 
3187     if (!count)
3188         return D3D_OK;
3189 
3190     if (matrix && param && count <= param->element_count)
3191     {
3192         unsigned int i;
3193 
3194         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3195 
3196         switch (param->class)
3197         {
3198             case D3DXPC_MATRIX_ROWS:
3199                 for (i = 0; i < count; ++i)
3200                     get_matrix(&param->members[i], &matrix[i], FALSE);
3201                 return D3D_OK;
3202 
3203             case D3DXPC_SCALAR:
3204             case D3DXPC_VECTOR:
3205             case D3DXPC_OBJECT:
3206             case D3DXPC_STRUCT:
3207                 break;
3208 
3209             default:
3210                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3211                 break;
3212         }
3213     }
3214 
3215     WARN("Parameter not found.\n");
3216 
3217     return D3DERR_INVALIDCALL;
3218 }
3219 
3220 static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3221         const D3DXMATRIX **matrix, UINT count)
3222 {
3223     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3224     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3225 
3226     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3227 
3228     if (param && count <= param->element_count)
3229     {
3230         unsigned int i;
3231         BYTE *data;
3232 
3233         switch (param->class)
3234         {
3235             case D3DXPC_MATRIX_ROWS:
3236                 data = param_get_data_and_dirtify(effect, param, count * param->rows
3237                         * param->columns * sizeof(float), TRUE);
3238 
3239                 for (i = 0; i < count; ++i)
3240                     set_matrix(&param->members[i], matrix[i], data + i * param->rows
3241                             * param->columns * sizeof(float));
3242 
3243                 return D3D_OK;
3244 
3245             case D3DXPC_SCALAR:
3246             case D3DXPC_VECTOR:
3247             case D3DXPC_OBJECT:
3248                 break;
3249 
3250             default:
3251                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3252                 break;
3253         }
3254     }
3255 
3256     WARN("Parameter not found.\n");
3257 
3258     return D3DERR_INVALIDCALL;
3259 }
3260 
3261 static HRESULT WINAPI d3dx_effect_GetMatrixPointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3262         D3DXMATRIX **matrix, UINT count)
3263 {
3264     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3265     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3266 
3267     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3268 
3269     if (!count)
3270         return D3D_OK;
3271 
3272     if (param && matrix && count <= param->element_count)
3273     {
3274         unsigned int i;
3275 
3276         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3277 
3278         switch (param->class)
3279         {
3280             case D3DXPC_MATRIX_ROWS:
3281                 for (i = 0; i < count; ++i)
3282                     get_matrix(&param->members[i], matrix[i], FALSE);
3283                 return D3D_OK;
3284 
3285             case D3DXPC_SCALAR:
3286             case D3DXPC_VECTOR:
3287             case D3DXPC_OBJECT:
3288                 break;
3289 
3290             default:
3291                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3292                 break;
3293         }
3294     }
3295 
3296     WARN("Parameter not found.\n");
3297 
3298     return D3DERR_INVALIDCALL;
3299 }
3300 
3301 static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3302         const D3DXMATRIX *matrix)
3303 {
3304     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3305     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3306 
3307     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3308 
3309     if (param && !param->element_count)
3310     {
3311         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3312 
3313         switch (param->class)
3314         {
3315             case D3DXPC_MATRIX_ROWS:
3316                 set_matrix_transpose(param, matrix, param_get_data_and_dirtify(effect, param,
3317                         param->rows * param->columns * sizeof(float), TRUE));
3318                 return D3D_OK;
3319 
3320             case D3DXPC_SCALAR:
3321             case D3DXPC_VECTOR:
3322             case D3DXPC_OBJECT:
3323             case D3DXPC_STRUCT:
3324                 break;
3325 
3326             default:
3327                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3328                 break;
3329         }
3330     }
3331 
3332     WARN("Parameter not found.\n");
3333 
3334     return D3DERR_INVALIDCALL;
3335 }
3336 
3337 static HRESULT WINAPI d3dx_effect_GetMatrixTranspose(ID3DXEffect *iface, D3DXHANDLE parameter,
3338         D3DXMATRIX *matrix)
3339 {
3340     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3341     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3342 
3343     TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix);
3344 
3345     if (matrix && param && !param->element_count)
3346     {
3347         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3348 
3349         switch (param->class)
3350         {
3351             case D3DXPC_SCALAR:
3352             case D3DXPC_VECTOR:
3353                 get_matrix(param, matrix, FALSE);
3354                 return D3D_OK;
3355 
3356             case D3DXPC_MATRIX_ROWS:
3357                 get_matrix(param, matrix, TRUE);
3358                 return D3D_OK;
3359 
3360             case D3DXPC_OBJECT:
3361             case D3DXPC_STRUCT:
3362                 break;
3363 
3364             default:
3365                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3366                 break;
3367         }
3368     }
3369 
3370     WARN("Parameter not found.\n");
3371 
3372     return D3DERR_INVALIDCALL;
3373 }
3374 
3375 static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3376         const D3DXMATRIX *matrix, UINT count)
3377 {
3378     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3379     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3380 
3381     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3382 
3383     if (param && param->element_count >= count)
3384     {
3385         unsigned int i;
3386         BYTE *data;
3387 
3388         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3389 
3390         switch (param->class)
3391         {
3392             case D3DXPC_MATRIX_ROWS:
3393                 data = param_get_data_and_dirtify(effect, param, count * param->rows
3394                         * param->columns * sizeof(float), TRUE);
3395 
3396                 for (i = 0; i < count; ++i)
3397                     set_matrix_transpose(&param->members[i], &matrix[i], data
3398                             + i * param->rows * param->columns * sizeof(float));
3399 
3400                 return D3D_OK;
3401 
3402             case D3DXPC_SCALAR:
3403             case D3DXPC_VECTOR:
3404             case D3DXPC_OBJECT:
3405             case D3DXPC_STRUCT:
3406                 break;
3407 
3408             default:
3409                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3410                 break;
3411         }
3412     }
3413 
3414     WARN("Parameter not found.\n");
3415 
3416     return D3DERR_INVALIDCALL;
3417 }
3418 
3419 static HRESULT WINAPI d3dx_effect_GetMatrixTransposeArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3420         D3DXMATRIX *matrix, UINT count)
3421 {
3422     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3423     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3424 
3425     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3426 
3427     if (!count)
3428         return D3D_OK;
3429 
3430     if (matrix && param && count <= param->element_count)
3431     {
3432         unsigned int i;
3433 
3434         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3435 
3436         switch (param->class)
3437         {
3438             case D3DXPC_MATRIX_ROWS:
3439                 for (i = 0; i < count; ++i)
3440                     get_matrix(&param->members[i], &matrix[i], TRUE);
3441                 return D3D_OK;
3442 
3443             case D3DXPC_SCALAR:
3444             case D3DXPC_VECTOR:
3445             case D3DXPC_OBJECT:
3446             case D3DXPC_STRUCT:
3447                 break;
3448 
3449             default:
3450                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3451                 break;
3452         }
3453     }
3454 
3455     WARN("Parameter not found.\n");
3456 
3457     return D3DERR_INVALIDCALL;
3458 }
3459 
3460 static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3461         const D3DXMATRIX **matrix, UINT count)
3462 {
3463     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3464     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3465 
3466     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3467 
3468     if (param && count <= param->element_count)
3469     {
3470         unsigned int i;
3471         BYTE *data;
3472 
3473         switch (param->class)
3474         {
3475             case D3DXPC_MATRIX_ROWS:
3476                 data = param_get_data_and_dirtify(effect, param, count * param->rows
3477                         * param->columns * sizeof(float), TRUE);
3478 
3479                 for (i = 0; i < count; ++i)
3480                     set_matrix_transpose(&param->members[i], matrix[i], data
3481                             + i * param->rows * param->columns * sizeof(float));
3482 
3483                 return D3D_OK;
3484 
3485             case D3DXPC_SCALAR:
3486             case D3DXPC_VECTOR:
3487             case D3DXPC_OBJECT:
3488                 break;
3489 
3490             default:
3491                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3492                 break;
3493         }
3494     }
3495 
3496     WARN("Parameter not found.\n");
3497 
3498     return D3DERR_INVALIDCALL;
3499 }
3500 
3501 static HRESULT WINAPI d3dx_effect_GetMatrixTransposePointerArray(ID3DXEffect *iface, D3DXHANDLE parameter,
3502         D3DXMATRIX **matrix, UINT count)
3503 {
3504     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3505     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3506 
3507     TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count);
3508 
3509     if (!count)
3510         return D3D_OK;
3511 
3512     if (matrix && param && count <= param->element_count)
3513     {
3514         unsigned int i;
3515 
3516         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
3517 
3518         switch (param->class)
3519         {
3520             case D3DXPC_MATRIX_ROWS:
3521                 for (i = 0; i < count; ++i)
3522                     get_matrix(&param->members[i], matrix[i], TRUE);
3523                 return D3D_OK;
3524 
3525             case D3DXPC_SCALAR:
3526             case D3DXPC_VECTOR:
3527             case D3DXPC_OBJECT:
3528                 break;
3529 
3530             default:
3531                 FIXME("Unhandled class %s.\n", debug_d3dxparameter_class(param->class));
3532                 break;
3533         }
3534     }
3535 
3536     WARN("Parameter not found.\n");
3537 
3538     return D3DERR_INVALIDCALL;
3539 }
3540 
3541 static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char *string)
3542 {
3543     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3544     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3545 
3546     TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
3547 
3548     if (param && param->type == D3DXPT_STRING)
3549         return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
3550 
3551     WARN("Parameter not found.\n");
3552 
3553     return D3DERR_INVALIDCALL;
3554 }
3555 
3556 static HRESULT WINAPI d3dx_effect_GetString(ID3DXEffect *iface, D3DXHANDLE parameter, const char **string)
3557 {
3558     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3559     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3560 
3561     TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string);
3562 
3563     if (string && param && !param->element_count && param->type == D3DXPT_STRING)
3564     {
3565         *string = *(const char **)param->data;
3566         TRACE("Returning %s.\n", debugstr_a(*string));
3567         return D3D_OK;
3568     }
3569 
3570     WARN("Parameter not found.\n");
3571 
3572     return D3DERR_INVALIDCALL;
3573 }
3574 
3575 static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3576         IDirect3DBaseTexture9 *texture)
3577 {
3578     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3579     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3580 
3581     TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3582 
3583     if (param && !param->element_count
3584             && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3585             || param->type == D3DXPT_TEXTURE2D || param->type ==  D3DXPT_TEXTURE3D
3586             || param->type == D3DXPT_TEXTURECUBE))
3587     {
3588         IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
3589                 sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
3590         IDirect3DBaseTexture9 *old_texture = *data;
3591 
3592         *data = texture;
3593 
3594         if (texture == old_texture)
3595             return D3D_OK;
3596 
3597         if (texture)
3598             IDirect3DBaseTexture9_AddRef(texture);
3599         if (old_texture)
3600             IDirect3DBaseTexture9_Release(old_texture);
3601 
3602         return D3D_OK;
3603     }
3604 
3605     WARN("Parameter not found.\n");
3606 
3607     return D3DERR_INVALIDCALL;
3608 }
3609 
3610 static HRESULT WINAPI d3dx_effect_GetTexture(ID3DXEffect *iface, D3DXHANDLE parameter,
3611         IDirect3DBaseTexture9 **texture)
3612 {
3613     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3614     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3615 
3616     TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture);
3617 
3618     if (texture && param && !param->element_count
3619             && (param->type == D3DXPT_TEXTURE || param->type == D3DXPT_TEXTURE1D
3620             || param->type == D3DXPT_TEXTURE2D || param->type ==  D3DXPT_TEXTURE3D
3621             || param->type == D3DXPT_TEXTURECUBE))
3622     {
3623         *texture = *(IDirect3DBaseTexture9 **)param->data;
3624         if (*texture)
3625             IDirect3DBaseTexture9_AddRef(*texture);
3626         TRACE("Returning %p.\n", *texture);
3627         return D3D_OK;
3628     }
3629 
3630     WARN("Parameter not found.\n");
3631 
3632     return D3DERR_INVALIDCALL;
3633 }
3634 
3635 static HRESULT WINAPI d3dx_effect_GetPixelShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3636         IDirect3DPixelShader9 **shader)
3637 {
3638     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3639     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3640 
3641     TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3642 
3643     if (shader && param && !param->element_count && param->type == D3DXPT_PIXELSHADER)
3644     {
3645         if ((*shader = *(IDirect3DPixelShader9 **)param->data))
3646             IDirect3DPixelShader9_AddRef(*shader);
3647         TRACE("Returning %p.\n", *shader);
3648         return D3D_OK;
3649     }
3650 
3651     WARN("Parameter not found.\n");
3652 
3653     return D3DERR_INVALIDCALL;
3654 }
3655 
3656 static HRESULT WINAPI d3dx_effect_GetVertexShader(ID3DXEffect *iface, D3DXHANDLE parameter,
3657         IDirect3DVertexShader9 **shader)
3658 {
3659     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3660     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3661 
3662     TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader);
3663 
3664     if (shader && param && !param->element_count && param->type == D3DXPT_VERTEXSHADER)
3665     {
3666         if ((*shader = *(IDirect3DVertexShader9 **)param->data))
3667             IDirect3DVertexShader9_AddRef(*shader);
3668         TRACE("Returning %p.\n", *shader);
3669         return D3D_OK;
3670     }
3671 
3672     WARN("Parameter not found.\n");
3673 
3674     return D3DERR_INVALIDCALL;
3675 }
3676 
3677 static HRESULT WINAPI d3dx_effect_SetArrayRange(ID3DXEffect *iface, D3DXHANDLE parameter, UINT start, UINT end)
3678 {
3679     FIXME("iface %p, parameter %p, start %u, end %u stub.\n", iface, parameter, start, end);
3680 
3681     return E_NOTIMPL;
3682 }
3683 
3684 /*** ID3DXEffect methods ***/
3685 static HRESULT WINAPI d3dx_effect_GetPool(ID3DXEffect *iface, ID3DXEffectPool **pool)
3686 {
3687     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3688 
3689     TRACE("iface %p, pool %p.\n", effect, pool);
3690 
3691     if (!pool)
3692     {
3693         WARN("Invalid argument supplied.\n");
3694         return D3DERR_INVALIDCALL;
3695     }
3696 
3697     *pool = NULL;
3698     if (effect->pool)
3699     {
3700         *pool = &effect->pool->ID3DXEffectPool_iface;
3701         (*pool)->lpVtbl->AddRef(*pool);
3702     }
3703 
3704     TRACE("Returning pool %p.\n", *pool);
3705 
3706     return S_OK;
3707 }
3708 
3709 static HRESULT WINAPI d3dx_effect_SetTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3710 {
3711     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3712     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3713 
3714     TRACE("iface %p, technique %p\n", iface, technique);
3715 
3716     if (tech)
3717     {
3718         effect->active_technique = tech;
3719         TRACE("Technique %p\n", tech);
3720         return D3D_OK;
3721     }
3722 
3723     WARN("Technique not found.\n");
3724 
3725     return D3DERR_INVALIDCALL;
3726 }
3727 
3728 static D3DXHANDLE WINAPI d3dx_effect_GetCurrentTechnique(ID3DXEffect *iface)
3729 {
3730     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
3731 
3732     TRACE("iface %p\n", This);
3733 
3734     return get_technique_handle(This->active_technique);
3735 }
3736 
3737 static HRESULT WINAPI d3dx_effect_ValidateTechnique(ID3DXEffect *iface, D3DXHANDLE technique)
3738 {
3739     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3740     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3741     HRESULT ret = D3D_OK;
3742     unsigned int i, j;
3743 
3744     FIXME("iface %p, technique %p semi-stub.\n", iface, technique);
3745 
3746     if (!tech)
3747     {
3748         ret = D3DERR_INVALIDCALL;
3749         goto done;
3750     }
3751     for (i = 0; i < tech->pass_count; ++i)
3752     {
3753         struct d3dx_pass *pass = &tech->passes[i];
3754 
3755         for (j = 0; j < pass->state_count; ++j)
3756         {
3757             struct d3dx_state *state = &pass->states[j];
3758 
3759             if (state_table[state->operation].class == SC_VERTEXSHADER
3760                     || state_table[state->operation].class == SC_PIXELSHADER)
3761             {
3762                 struct d3dx_parameter *param;
3763                 void *param_value;
3764                 BOOL param_dirty;
3765                 HRESULT hr;
3766 
3767                 if (FAILED(hr = d3dx9_get_param_value_ptr(pass, &pass->states[j], &param_value, &param,
3768                         FALSE, &param_dirty)))
3769                     return hr;
3770 
3771                 if (param->object_id && effect->objects[param->object_id].creation_failed)
3772                 {
3773                     ret = E_FAIL;
3774                     goto done;
3775                 }
3776             }
3777         }
3778     }
3779 done:
3780     TRACE("Returning %#x.\n", ret);
3781     return ret;
3782 }
3783 
3784 static HRESULT WINAPI d3dx_effect_FindNextValidTechnique(ID3DXEffect *iface, D3DXHANDLE technique,
3785         D3DXHANDLE *next_technique)
3786 {
3787     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3788     struct d3dx_technique *prev_tech, *tech;
3789     unsigned int i;
3790 
3791     TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
3792 
3793     if (technique)
3794     {
3795         if (!(prev_tech = get_valid_technique(effect, technique)))
3796             return D3DERR_INVALIDCALL;
3797 
3798         for (i = 0; i < effect->technique_count; ++i)
3799         {
3800             tech = &effect->techniques[i];
3801             if (tech == prev_tech)
3802             {
3803                 ++i;
3804                 break;
3805             }
3806         }
3807     }
3808     else
3809     {
3810         i = 0;
3811     }
3812 
3813     for (; i < effect->technique_count; ++i)
3814     {
3815         tech = &effect->techniques[i];
3816         if (SUCCEEDED(d3dx_effect_ValidateTechnique(iface, get_technique_handle(tech))))
3817         {
3818             *next_technique = get_technique_handle(tech);
3819             return D3D_OK;
3820         }
3821     }
3822 
3823     *next_technique = get_technique_handle(&effect->techniques[0]);
3824     return S_FALSE;
3825 }
3826 
3827 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3828         void *data);
3829 
3830 static BOOL walk_param_eval_dep(struct d3dx_param_eval *param_eval, walk_parameter_dep_func param_func,
3831         void *data)
3832 {
3833     struct d3dx_parameter **params;
3834     unsigned int i, param_count;
3835 
3836     if (!param_eval)
3837         return FALSE;
3838 
3839     params = param_eval->shader_inputs.inputs_param;
3840     param_count = param_eval->shader_inputs.input_count;
3841     for (i = 0; i < param_count; ++i)
3842     {
3843         if (walk_parameter_dep(params[i], param_func, data))
3844             return TRUE;
3845     }
3846 
3847     params = param_eval->pres.inputs.inputs_param;
3848     param_count = param_eval->pres.inputs.input_count;
3849     for (i = 0; i < param_count; ++i)
3850     {
3851         if (walk_parameter_dep(params[i], param_func, data))
3852             return TRUE;
3853     }
3854     return FALSE;
3855 }
3856 
3857 static BOOL walk_state_dep(struct d3dx_state *state, walk_parameter_dep_func param_func,
3858         void *data)
3859 {
3860     if (state->type == ST_CONSTANT && is_param_type_sampler(state->parameter.type))
3861     {
3862         if (walk_parameter_dep(&state->parameter, param_func, data))
3863             return TRUE;
3864     }
3865     else if (state->type == ST_ARRAY_SELECTOR || state->type == ST_PARAMETER)
3866     {
3867         if (walk_parameter_dep(state->referenced_param, param_func, data))
3868             return TRUE;
3869     }
3870     return walk_param_eval_dep(state->parameter.param_eval, param_func, data);
3871 }
3872 
3873 static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
3874         void *data)
3875 {
3876     unsigned int i;
3877     unsigned int member_count;
3878 
3879     param = &param->top_level_param->param;
3880     if (param_func(data, param))
3881         return TRUE;
3882 
3883     if (walk_param_eval_dep(param->param_eval, param_func, data))
3884         return TRUE;
3885 
3886     if (param->class == D3DXPC_OBJECT && is_param_type_sampler(param->type))
3887     {
3888         struct d3dx_sampler *sampler;
3889         unsigned int sampler_idx;
3890         unsigned int samplers_count = max(param->element_count, 1);
3891 
3892         for (sampler_idx = 0; sampler_idx < samplers_count; ++sampler_idx)
3893         {
3894             sampler = param->element_count ? param->members[sampler_idx].data : param->data;
3895             for (i = 0; i < sampler->state_count; ++i)
3896             {
3897                 if (walk_state_dep(&sampler->states[i], param_func, data))
3898                     return TRUE;
3899             }
3900         }
3901         return FALSE;
3902     }
3903 
3904     member_count = param->element_count ? param->element_count : param->member_count;
3905     for (i = 0; i < member_count; ++i)
3906     {
3907         if (walk_param_eval_dep(param->members[i].param_eval, param_func, data))
3908             return TRUE;
3909     }
3910 
3911     return FALSE;
3912 }
3913 
3914 static BOOL is_parameter_used(struct d3dx_parameter *param, struct d3dx_technique *tech)
3915 {
3916     unsigned int i, j;
3917     struct d3dx_pass *pass;
3918 
3919     if (!tech || !param)
3920         return FALSE;
3921 
3922     for (i = 0; i < tech->pass_count; ++i)
3923     {
3924         pass = &tech->passes[i];
3925         for (j = 0; j < pass->state_count; ++j)
3926         {
3927             if (walk_state_dep(&pass->states[j], is_same_parameter, param))
3928                 return TRUE;
3929         }
3930     }
3931     return FALSE;
3932 }
3933 
3934 static BOOL WINAPI d3dx_effect_IsParameterUsed(ID3DXEffect *iface, D3DXHANDLE parameter, D3DXHANDLE technique)
3935 {
3936     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3937     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
3938     struct d3dx_technique *tech = get_valid_technique(effect, technique);
3939     BOOL ret;
3940 
3941     TRACE("iface %p, parameter %p, technique %p.\n", iface, parameter, technique);
3942     TRACE("param %p, name %s, tech %p.\n", param, param ? debugstr_a(param->name) : "", tech);
3943 
3944     ret = is_parameter_used(param, tech);
3945     TRACE("Returning %#x.\n", ret);
3946     return ret;
3947 }
3948 
3949 static HRESULT WINAPI d3dx_effect_Begin(ID3DXEffect *iface, UINT *passes, DWORD flags)
3950 {
3951     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
3952     struct d3dx_technique *technique = effect->active_technique;
3953 
3954     TRACE("iface %p, passes %p, flags %#x.\n", iface, passes, flags);
3955 
3956     if (technique)
3957     {
3958         if (flags & ~(D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESAMPLERSTATE | D3DXFX_DONOTSAVESHADERSTATE))
3959             WARN("Invalid flags (%#x) specified.\n", flags);
3960 
3961         if (flags & D3DXFX_DONOTSAVESTATE)
3962         {
3963             TRACE("State capturing disabled.\n");
3964         }
3965         else
3966         {
3967             HRESULT hr;
3968             unsigned int i;
3969 
3970             if (!technique->saved_state)
3971             {
3972                 ID3DXEffectStateManager *manager;
3973 
3974                 manager = effect->manager;
3975                 effect->manager = NULL;
3976                 if (FAILED(hr = IDirect3DDevice9_BeginStateBlock(effect->device)))
3977                     ERR("BeginStateBlock failed, hr %#x.\n", hr);
3978                 for (i = 0; i < technique->pass_count; i++)
3979                     d3dx9_apply_pass_states(effect, &technique->passes[i], TRUE);
3980                 if (FAILED(hr = IDirect3DDevice9_EndStateBlock(effect->device, &technique->saved_state)))
3981                     ERR("EndStateBlock failed, hr %#x.\n", hr);
3982                 effect->manager = manager;
3983             }
3984             if (FAILED(hr = IDirect3DStateBlock9_Capture(technique->saved_state)))
3985                 ERR("StateBlock Capture failed, hr %#x.\n", hr);
3986         }
3987 
3988         if (passes)
3989             *passes = technique->pass_count;
3990         effect->started = TRUE;
3991         effect->begin_flags = flags;
3992 
3993         return D3D_OK;
3994     }
3995 
3996     WARN("Invalid argument supplied.\n");
3997 
3998     return D3DERR_INVALIDCALL;
3999 }
4000 
4001 static HRESULT WINAPI d3dx_effect_BeginPass(ID3DXEffect *iface, UINT pass)
4002 {
4003     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4004     struct d3dx_technique *technique = effect->active_technique;
4005 
4006     TRACE("iface %p, pass %u\n", effect, pass);
4007 
4008     if (technique && pass < technique->pass_count && !effect->active_pass)
4009     {
4010         HRESULT hr;
4011 
4012         memset(effect->current_light, 0, sizeof(effect->current_light));
4013         memset(&effect->current_material, 0, sizeof(effect->current_material));
4014 
4015         if (SUCCEEDED(hr = d3dx9_apply_pass_states(effect, &technique->passes[pass], TRUE)))
4016             effect->active_pass = &technique->passes[pass];
4017         return hr;
4018     }
4019 
4020     WARN("Invalid argument supplied.\n");
4021 
4022     return D3DERR_INVALIDCALL;
4023 }
4024 
4025 static HRESULT WINAPI d3dx_effect_CommitChanges(ID3DXEffect *iface)
4026 {
4027     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4028 
4029     TRACE("iface %p.\n", iface);
4030 
4031     if (!effect->active_pass)
4032     {
4033         WARN("Called without an active pass.\n");
4034         return D3D_OK;
4035     }
4036     return d3dx9_apply_pass_states(effect, effect->active_pass, FALSE);
4037 }
4038 
4039 static HRESULT WINAPI d3dx_effect_EndPass(ID3DXEffect *iface)
4040 {
4041     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4042 
4043     TRACE("iface %p\n", This);
4044 
4045     if (This->active_pass)
4046     {
4047          This->active_pass = NULL;
4048          return D3D_OK;
4049     }
4050 
4051     WARN("Invalid call.\n");
4052 
4053     return D3DERR_INVALIDCALL;
4054 }
4055 
4056 static HRESULT WINAPI d3dx_effect_End(ID3DXEffect *iface)
4057 {
4058     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4059     struct d3dx_technique *technique = effect->active_technique;
4060 
4061     TRACE("iface %p.\n", iface);
4062 
4063     if (!effect->started)
4064         return D3D_OK;
4065 
4066     if (effect->begin_flags & D3DXFX_DONOTSAVESTATE)
4067     {
4068         TRACE("State restoring disabled.\n");
4069     }
4070     else
4071     {
4072         HRESULT hr;
4073 
4074         if (technique && technique->saved_state)
4075         {
4076             if (FAILED(hr = IDirect3DStateBlock9_Apply(technique->saved_state)))
4077                 ERR("State block apply failed, hr %#x.\n", hr);
4078         }
4079         else
4080             ERR("No saved state.\n");
4081     }
4082 
4083     effect->started = FALSE;
4084 
4085     return D3D_OK;
4086 }
4087 
4088 static HRESULT WINAPI d3dx_effect_GetDevice(ID3DXEffect *iface, struct IDirect3DDevice9 **device)
4089 {
4090     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4091 
4092     TRACE("iface %p, device %p\n", This, device);
4093 
4094     if (!device)
4095     {
4096         WARN("Invalid argument supplied.\n");
4097         return D3DERR_INVALIDCALL;
4098     }
4099 
4100     IDirect3DDevice9_AddRef(This->device);
4101 
4102     *device = This->device;
4103 
4104     TRACE("Returning device %p\n", *device);
4105 
4106     return S_OK;
4107 }
4108 
4109 static BOOL param_on_lost_device(void *data, struct d3dx_parameter *param)
4110 {
4111     struct IDirect3DVolumeTexture9 *volume_texture;
4112     struct IDirect3DCubeTexture9 *cube_texture;
4113     struct IDirect3DTexture9 *texture;
4114     D3DSURFACE_DESC surface_desc;
4115     D3DVOLUME_DESC volume_desc;
4116 
4117     if (param->class == D3DXPC_OBJECT && !param->element_count)
4118     {
4119         switch (param->type)
4120         {
4121             case D3DXPT_TEXTURE:
4122             case D3DXPT_TEXTURE1D:
4123             case D3DXPT_TEXTURE2D:
4124                 texture = *(IDirect3DTexture9 **)param->data;
4125                 if (!texture)
4126                     return FALSE;
4127                 IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
4128                 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4129                     return FALSE;
4130                 break;
4131             case D3DXPT_TEXTURE3D:
4132                 volume_texture = *(IDirect3DVolumeTexture9 **)param->data;
4133                 if (!volume_texture)
4134                     return FALSE;
4135                 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
4136                 if (volume_desc.Pool != D3DPOOL_DEFAULT)
4137                     return FALSE;
4138                 break;
4139             case D3DXPT_TEXTURECUBE:
4140                 cube_texture = *(IDirect3DCubeTexture9 **)param->data;
4141                 if (!cube_texture)
4142                     return FALSE;
4143                 IDirect3DTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
4144                 if (surface_desc.Pool != D3DPOOL_DEFAULT)
4145                     return FALSE;
4146                 break;
4147             default:
4148                 return FALSE;
4149         }
4150         IUnknown_Release(*(IUnknown **)param->data);
4151         *(IUnknown **)param->data = NULL;
4152     }
4153     return FALSE;
4154 }
4155 
4156 static HRESULT WINAPI d3dx_effect_OnLostDevice(ID3DXEffect *iface)
4157 {
4158     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4159     unsigned int i;
4160 
4161     TRACE("iface %p.\n", iface);
4162 
4163     for (i = 0; i < effect->parameter_count; ++i)
4164         walk_parameter_tree(&effect->parameters[i].param, param_on_lost_device, NULL);
4165 
4166     return D3D_OK;
4167 }
4168 
4169 static HRESULT WINAPI d3dx_effect_OnResetDevice(ID3DXEffect *iface)
4170 {
4171     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4172 
4173     FIXME("(%p)->(): stub\n", This);
4174 
4175     return E_NOTIMPL;
4176 }
4177 
4178 static HRESULT WINAPI d3dx_effect_SetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager *manager)
4179 {
4180     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4181 
4182     TRACE("iface %p, manager %p\n", This, manager);
4183 
4184     if (manager) IUnknown_AddRef(manager);
4185     if (This->manager) IUnknown_Release(This->manager);
4186 
4187     This->manager = manager;
4188 
4189     return D3D_OK;
4190 }
4191 
4192 static HRESULT WINAPI d3dx_effect_GetStateManager(ID3DXEffect *iface, ID3DXEffectStateManager **manager)
4193 {
4194     struct d3dx_effect *This = impl_from_ID3DXEffect(iface);
4195 
4196     TRACE("iface %p, manager %p\n", This, manager);
4197 
4198     if (!manager)
4199     {
4200         WARN("Invalid argument supplied.\n");
4201         return D3DERR_INVALIDCALL;
4202     }
4203 
4204     if (This->manager) IUnknown_AddRef(This->manager);
4205     *manager = This->manager;
4206 
4207     return D3D_OK;
4208 }
4209 
4210 static HRESULT WINAPI d3dx_effect_BeginParameterBlock(ID3DXEffect *iface)
4211 {
4212     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4213 
4214     TRACE("iface %p.\n", iface);
4215 
4216     if (effect->current_parameter_block)
4217     {
4218         WARN("Parameter block is already started.\n");
4219         return D3DERR_INVALIDCALL;
4220     }
4221 
4222     effect->current_parameter_block = heap_alloc_zero(sizeof(*effect->current_parameter_block));
4223     memcpy(effect->current_parameter_block->magic_string, parameter_block_magic_string,
4224             sizeof(parameter_block_magic_string));
4225     effect->current_parameter_block->effect = effect;
4226 
4227     return D3D_OK;
4228 }
4229 
4230 static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
4231 {
4232     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4233     struct d3dx_parameter_block *ret;
4234 
4235     TRACE("iface %p.\n", iface);
4236 
4237     if (!effect->current_parameter_block)
4238     {
4239         WARN("No active parameter block.\n");
4240         return NULL;
4241     }
4242     ret = effect->current_parameter_block;
4243 
4244     ret->buffer = heap_realloc(ret->buffer, ret->offset);
4245     ret->size = ret->offset;
4246 
4247     effect->current_parameter_block = NULL;
4248     list_add_tail(&effect->parameter_block_list, &ret->entry);
4249     return (D3DXHANDLE)ret;
4250 }
4251 
4252 static HRESULT WINAPI d3dx_effect_ApplyParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4253 {
4254     struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4255     struct d3dx_recorded_parameter *record;
4256 
4257     TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4258 
4259     if (!block || !block->offset)
4260         return D3DERR_INVALIDCALL;
4261 
4262     record = (struct d3dx_recorded_parameter *)block->buffer;
4263     while ((BYTE *)record < block->buffer + block->offset)
4264     {
4265         set_value(record->param, record + 1, record->bytes,
4266                 param_get_data_and_dirtify(block->effect, record->param, record->bytes, TRUE));
4267         record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
4268     }
4269     assert((BYTE *)record == block->buffer + block->offset);
4270     return D3D_OK;
4271 }
4272 
4273 #if D3DX_SDK_VERSION >= 26
4274 static HRESULT WINAPI d3dx_effect_DeleteParameterBlock(ID3DXEffect *iface, D3DXHANDLE parameter_block)
4275 {
4276     struct d3dx_parameter_block *block = get_valid_parameter_block(parameter_block);
4277     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4278     struct d3dx_parameter_block *b;
4279 
4280     TRACE("iface %p, parameter_block %p.\n", iface, parameter_block);
4281 
4282     if (!block)
4283         return D3DERR_INVALIDCALL;
4284 
4285     LIST_FOR_EACH_ENTRY(b, &effect->parameter_block_list, struct d3dx_parameter_block, entry)
4286     {
4287         if (b == block)
4288         {
4289             list_remove(&b->entry);
4290             free_parameter_block(b);
4291             return D3D_OK;
4292         }
4293     }
4294 
4295     WARN("Block is not found in issued block list, not freeing memory.\n");
4296     return D3DERR_INVALIDCALL;
4297 }
4298 #endif
4299 
4300 static HRESULT WINAPI d3dx_effect_CloneEffect(ID3DXEffect *iface, IDirect3DDevice9 *device,
4301         ID3DXEffect **new_effect)
4302 {
4303     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
4304 
4305     FIXME("iface %p, device %p, new_effect %p stub.\n", effect, device, new_effect);
4306 
4307     if (!new_effect)
4308         return D3DERR_INVALIDCALL;
4309 
4310     if (effect->flags & D3DXFX_NOT_CLONEABLE)
4311         return E_FAIL;
4312 
4313     if (!device)
4314         return D3DERR_INVALIDCALL;
4315 
4316     return E_NOTIMPL;
4317 }
4318 
4319 #if D3DX_SDK_VERSION >= 27
4320 static HRESULT WINAPI d3dx_effect_SetRawValue(ID3DXEffect *iface, D3DXHANDLE parameter, const void *data,
4321         UINT byte_offset, UINT bytes)
4322 {
4323     FIXME("iface %p, parameter %p, data %p, byte_offset %u, bytes %u stub!\n",
4324             iface, parameter, data, byte_offset, bytes);
4325 
4326     return E_NOTIMPL;
4327 }
4328 #endif
4329 
4330 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
4331 {
4332     /*** IUnknown methods ***/
4333     d3dx_effect_QueryInterface,
4334     d3dx_effect_AddRef,
4335     d3dx_effect_Release,
4336     /*** ID3DXBaseEffect methods ***/
4337     d3dx_effect_GetDesc,
4338     d3dx_effect_GetParameterDesc,
4339     d3dx_effect_GetTechniqueDesc,
4340     d3dx_effect_GetPassDesc,
4341     d3dx_effect_GetFunctionDesc,
4342     d3dx_effect_GetParameter,
4343     d3dx_effect_GetParameterByName,
4344     d3dx_effect_GetParameterBySemantic,
4345     d3dx_effect_GetParameterElement,
4346     d3dx_effect_GetTechnique,
4347     d3dx_effect_GetTechniqueByName,
4348     d3dx_effect_GetPass,
4349     d3dx_effect_GetPassByName,
4350     d3dx_effect_GetFunction,
4351     d3dx_effect_GetFunctionByName,
4352     d3dx_effect_GetAnnotation,
4353     d3dx_effect_GetAnnotationByName,
4354     d3dx_effect_SetValue,
4355     d3dx_effect_GetValue,
4356     d3dx_effect_SetBool,
4357     d3dx_effect_GetBool,
4358     d3dx_effect_SetBoolArray,
4359     d3dx_effect_GetBoolArray,
4360     d3dx_effect_SetInt,
4361     d3dx_effect_GetInt,
4362     d3dx_effect_SetIntArray,
4363     d3dx_effect_GetIntArray,
4364     d3dx_effect_SetFloat,
4365     d3dx_effect_GetFloat,
4366     d3dx_effect_SetFloatArray,
4367     d3dx_effect_GetFloatArray,
4368     d3dx_effect_SetVector,
4369     d3dx_effect_GetVector,
4370     d3dx_effect_SetVectorArray,
4371     d3dx_effect_GetVectorArray,
4372     d3dx_effect_SetMatrix,
4373     d3dx_effect_GetMatrix,
4374     d3dx_effect_SetMatrixArray,
4375     d3dx_effect_GetMatrixArray,
4376     d3dx_effect_SetMatrixPointerArray,
4377     d3dx_effect_GetMatrixPointerArray,
4378     d3dx_effect_SetMatrixTranspose,
4379     d3dx_effect_GetMatrixTranspose,
4380     d3dx_effect_SetMatrixTransposeArray,
4381     d3dx_effect_GetMatrixTransposeArray,
4382     d3dx_effect_SetMatrixTransposePointerArray,
4383     d3dx_effect_GetMatrixTransposePointerArray,
4384     d3dx_effect_SetString,
4385     d3dx_effect_GetString,
4386     d3dx_effect_SetTexture,
4387     d3dx_effect_GetTexture,
4388     d3dx_effect_GetPixelShader,
4389     d3dx_effect_GetVertexShader,
4390     d3dx_effect_SetArrayRange,
4391     /*** ID3DXEffect methods ***/
4392     d3dx_effect_GetPool,
4393     d3dx_effect_SetTechnique,
4394     d3dx_effect_GetCurrentTechnique,
4395     d3dx_effect_ValidateTechnique,
4396     d3dx_effect_FindNextValidTechnique,
4397     d3dx_effect_IsParameterUsed,
4398     d3dx_effect_Begin,
4399     d3dx_effect_BeginPass,
4400     d3dx_effect_CommitChanges,
4401     d3dx_effect_EndPass,
4402     d3dx_effect_End,
4403     d3dx_effect_GetDevice,
4404     d3dx_effect_OnLostDevice,
4405     d3dx_effect_OnResetDevice,
4406     d3dx_effect_SetStateManager,
4407     d3dx_effect_GetStateManager,
4408     d3dx_effect_BeginParameterBlock,
4409     d3dx_effect_EndParameterBlock,
4410     d3dx_effect_ApplyParameterBlock,
4411 #if D3DX_SDK_VERSION >= 26
4412     d3dx_effect_DeleteParameterBlock,
4413 #endif
4414     d3dx_effect_CloneEffect,
4415 #if D3DX_SDK_VERSION >= 27
4416     d3dx_effect_SetRawValue
4417 #endif
4418 };
4419 
4420 static inline struct ID3DXEffectCompilerImpl *impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
4421 {
4422     return CONTAINING_RECORD(iface, struct ID3DXEffectCompilerImpl, ID3DXEffectCompiler_iface);
4423 }
4424 
4425 /*** IUnknown methods ***/
4426 static HRESULT WINAPI ID3DXEffectCompilerImpl_QueryInterface(ID3DXEffectCompiler *iface, REFIID riid, void **object)
4427 {
4428     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
4429 
4430     if (IsEqualGUID(riid, &IID_IUnknown)
4431             || IsEqualGUID(riid, &IID_ID3DXEffectCompiler))
4432     {
4433         iface->lpVtbl->AddRef(iface);
4434         *object = iface;
4435         return S_OK;
4436     }
4437 
4438     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
4439 
4440     *object = NULL;
4441     return E_NOINTERFACE;
4442 }
4443 
4444 static ULONG WINAPI ID3DXEffectCompilerImpl_AddRef(ID3DXEffectCompiler *iface)
4445 {
4446     struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4447     ULONG refcount = InterlockedIncrement(&compiler->ref);
4448 
4449     TRACE("%p increasing refcount to %u.\n", iface, refcount);
4450 
4451     return refcount;
4452 }
4453 
4454 static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
4455 {
4456     struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface);
4457     ULONG refcount = InterlockedDecrement(&compiler->ref);
4458 
4459     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
4460 
4461     if (!refcount)
4462     {
4463         heap_free(compiler);
4464     }
4465 
4466     return refcount;
4467 }
4468 
4469 /*** ID3DXBaseEffect methods ***/
4470 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc)
4471 {
4472     FIXME("iface %p, desc %p stub!\n", iface, desc);
4473 
4474     return E_NOTIMPL;
4475 }
4476 
4477 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface,
4478         D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc)
4479 {
4480     FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc);
4481 
4482     return E_NOTIMPL;
4483 }
4484 
4485 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface,
4486         D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc)
4487 {
4488     FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc);
4489 
4490     return E_NOTIMPL;
4491 }
4492 
4493 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface,
4494         D3DXHANDLE pass, D3DXPASS_DESC *desc)
4495 {
4496     FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc);
4497 
4498     return E_NOTIMPL;
4499 }
4500 
4501 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface,
4502         D3DXHANDLE shader, D3DXFUNCTION_DESC *desc)
4503 {
4504     FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc);
4505 
4506     return E_NOTIMPL;
4507 }
4508 
4509 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface,
4510         D3DXHANDLE parameter, UINT index)
4511 {
4512     FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4513 
4514     return NULL;
4515 }
4516 
4517 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface,
4518         D3DXHANDLE parameter, const char *name)
4519 {
4520     FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name));
4521 
4522     return NULL;
4523 }
4524 
4525 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface,
4526         D3DXHANDLE parameter, const char *semantic)
4527 {
4528     FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic));
4529 
4530     return NULL;
4531 }
4532 
4533 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface,
4534         D3DXHANDLE parameter, UINT index)
4535 {
4536     FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
4537 
4538     return NULL;
4539 }
4540 
4541 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index)
4542 {
4543     FIXME("iface %p, index %u stub!\n", iface, index);
4544 
4545     return NULL;
4546 }
4547 
4548 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name)
4549 {
4550     FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4551 
4552     return NULL;
4553 }
4554 
4555 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index)
4556 {
4557     FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index);
4558 
4559     return NULL;
4560 }
4561 
4562 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface,
4563         D3DXHANDLE technique, const char *name)
4564 {
4565     FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name));
4566 
4567     return NULL;
4568 }
4569 
4570 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index)
4571 {
4572     FIXME("iface %p, index %u stub!\n", iface, index);
4573 
4574     return NULL;
4575 }
4576 
4577 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name)
4578 {
4579     FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
4580 
4581     return NULL;
4582 }
4583 
4584 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface,
4585         D3DXHANDLE object, UINT index)
4586 {
4587     FIXME("iface %p, object %p, index %u stub!\n", iface, object, index);
4588 
4589     return NULL;
4590 }
4591 
4592 static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface,
4593         D3DXHANDLE object, const char *name)
4594 {
4595     FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name));
4596 
4597     return NULL;
4598 }
4599 
4600 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface,
4601         D3DXHANDLE parameter, const void *data, UINT bytes)
4602 {
4603     FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4604 
4605     return E_NOTIMPL;
4606 }
4607 
4608 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface,
4609         D3DXHANDLE parameter, void *data, UINT bytes)
4610 {
4611     FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
4612 
4613     return E_NOTIMPL;
4614 }
4615 
4616 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b)
4617 {
4618     FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b);
4619 
4620     return E_NOTIMPL;
4621 }
4622 
4623 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b)
4624 {
4625     FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b);
4626 
4627     return E_NOTIMPL;
4628 }
4629 
4630 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface,
4631         D3DXHANDLE parameter, const BOOL *b, UINT count)
4632 {
4633     FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4634 
4635     return E_NOTIMPL;
4636 }
4637 
4638 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface,
4639         D3DXHANDLE parameter, BOOL *b, UINT count)
4640 {
4641     FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
4642 
4643     return E_NOTIMPL;
4644 }
4645 
4646 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n)
4647 {
4648     FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n);
4649 
4650     return E_NOTIMPL;
4651 }
4652 
4653 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n)
4654 {
4655     FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n);
4656 
4657     return E_NOTIMPL;
4658 }
4659 
4660 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface,
4661         D3DXHANDLE parameter, const INT *n, UINT count)
4662 {
4663     FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4664 
4665     return E_NOTIMPL;
4666 }
4667 
4668 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface,
4669         D3DXHANDLE parameter, INT *n, UINT count)
4670 {
4671     FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
4672 
4673     return E_NOTIMPL;
4674 }
4675 
4676 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f)
4677 {
4678     FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f);
4679 
4680     return E_NOTIMPL;
4681 }
4682 
4683 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f)
4684 {
4685     FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f);
4686 
4687     return E_NOTIMPL;
4688 }
4689 
4690 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface,
4691         D3DXHANDLE parameter, const float *f, UINT count)
4692 {
4693     FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4694 
4695     return E_NOTIMPL;
4696 }
4697 
4698 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface,
4699         D3DXHANDLE parameter, float *f, UINT count)
4700 {
4701     FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
4702 
4703     return E_NOTIMPL;
4704 }
4705 
4706 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface,
4707         D3DXHANDLE parameter, const D3DXVECTOR4 *vector)
4708 {
4709     FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4710 
4711     return E_NOTIMPL;
4712 }
4713 
4714 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface,
4715         D3DXHANDLE parameter, D3DXVECTOR4 *vector)
4716 {
4717     FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
4718 
4719     return E_NOTIMPL;
4720 }
4721 
4722 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface,
4723         D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count)
4724 {
4725     FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4726 
4727     return E_NOTIMPL;
4728 }
4729 
4730 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface,
4731         D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count)
4732 {
4733     FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
4734 
4735     return E_NOTIMPL;
4736 }
4737 
4738 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface,
4739         D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4740 {
4741     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4742 
4743     return E_NOTIMPL;
4744 }
4745 
4746 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface,
4747         D3DXHANDLE parameter, D3DXMATRIX *matrix)
4748 {
4749     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4750 
4751     return E_NOTIMPL;
4752 }
4753 
4754 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface,
4755         D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4756 {
4757     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4758 
4759     return E_NOTIMPL;
4760 }
4761 
4762 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface,
4763         D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4764 {
4765     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4766 
4767     return E_NOTIMPL;
4768 }
4769 
4770 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface,
4771         D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4772 {
4773     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4774 
4775     return E_NOTIMPL;
4776 }
4777 
4778 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface,
4779         D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4780 {
4781     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4782 
4783     return E_NOTIMPL;
4784 }
4785 
4786 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface,
4787         D3DXHANDLE parameter, const D3DXMATRIX *matrix)
4788 {
4789     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4790 
4791     return E_NOTIMPL;
4792 }
4793 
4794 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface,
4795         D3DXHANDLE parameter, D3DXMATRIX *matrix)
4796 {
4797     FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
4798 
4799     return E_NOTIMPL;
4800 }
4801 
4802 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4803         D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count)
4804 {
4805     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4806 
4807     return E_NOTIMPL;
4808 }
4809 
4810 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface,
4811         D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count)
4812 {
4813     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4814 
4815     return E_NOTIMPL;
4816 }
4817 
4818 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4819         D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count)
4820 {
4821     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4822 
4823     return E_NOTIMPL;
4824 }
4825 
4826 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface,
4827         D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count)
4828 {
4829     FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
4830 
4831     return E_NOTIMPL;
4832 }
4833 
4834 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface,
4835         D3DXHANDLE parameter, const char *string)
4836 {
4837     FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string));
4838 
4839     return E_NOTIMPL;
4840 }
4841 
4842 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface,
4843         D3DXHANDLE parameter, const char **string)
4844 {
4845     FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string);
4846 
4847     return E_NOTIMPL;
4848 }
4849 
4850 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface,
4851         D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture)
4852 {
4853     FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4854 
4855     return E_NOTIMPL;
4856 }
4857 
4858 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface,
4859         D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture)
4860 {
4861     FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
4862 
4863     return E_NOTIMPL;
4864 }
4865 
4866 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface,
4867         D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader)
4868 {
4869     FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
4870 
4871     return E_NOTIMPL;
4872 }
4873 
4874 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface,
4875         D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader)
4876 {
4877     FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
4878 
4879     return E_NOTIMPL;
4880 }
4881 
4882 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface,
4883         D3DXHANDLE parameter, UINT start, UINT end)
4884 {
4885     FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end);
4886 
4887     return E_NOTIMPL;
4888 }
4889 
4890 /*** ID3DXEffectCompiler methods ***/
4891 static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal)
4892 {
4893     FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal);
4894 
4895     return E_NOTIMPL;
4896 }
4897 
4898 static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal)
4899 {
4900     FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal);
4901 
4902     return E_NOTIMPL;
4903 }
4904 
4905 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags,
4906         ID3DXBuffer **effect, ID3DXBuffer **error_msgs)
4907 {
4908     FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs);
4909 
4910     return E_NOTIMPL;
4911 }
4912 
4913 static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler *iface, D3DXHANDLE function,
4914         const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs,
4915         ID3DXConstantTable **constant_table)
4916 {
4917     FIXME("iface %p, function %p, target %s, flags %#x, shader %p, error_msgs %p, constant_table %p stub!\n",
4918             iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table);
4919 
4920     return E_NOTIMPL;
4921 }
4922 
4923 static const struct ID3DXEffectCompilerVtbl ID3DXEffectCompiler_Vtbl =
4924 {
4925     /*** IUnknown methods ***/
4926     ID3DXEffectCompilerImpl_QueryInterface,
4927     ID3DXEffectCompilerImpl_AddRef,
4928     ID3DXEffectCompilerImpl_Release,
4929     /*** ID3DXBaseEffect methods ***/
4930     ID3DXEffectCompilerImpl_GetDesc,
4931     ID3DXEffectCompilerImpl_GetParameterDesc,
4932     ID3DXEffectCompilerImpl_GetTechniqueDesc,
4933     ID3DXEffectCompilerImpl_GetPassDesc,
4934     ID3DXEffectCompilerImpl_GetFunctionDesc,
4935     ID3DXEffectCompilerImpl_GetParameter,
4936     ID3DXEffectCompilerImpl_GetParameterByName,
4937     ID3DXEffectCompilerImpl_GetParameterBySemantic,
4938     ID3DXEffectCompilerImpl_GetParameterElement,
4939     ID3DXEffectCompilerImpl_GetTechnique,
4940     ID3DXEffectCompilerImpl_GetTechniqueByName,
4941     ID3DXEffectCompilerImpl_GetPass,
4942     ID3DXEffectCompilerImpl_GetPassByName,
4943     ID3DXEffectCompilerImpl_GetFunction,
4944     ID3DXEffectCompilerImpl_GetFunctionByName,
4945     ID3DXEffectCompilerImpl_GetAnnotation,
4946     ID3DXEffectCompilerImpl_GetAnnotationByName,
4947     ID3DXEffectCompilerImpl_SetValue,
4948     ID3DXEffectCompilerImpl_GetValue,
4949     ID3DXEffectCompilerImpl_SetBool,
4950     ID3DXEffectCompilerImpl_GetBool,
4951     ID3DXEffectCompilerImpl_SetBoolArray,
4952     ID3DXEffectCompilerImpl_GetBoolArray,
4953     ID3DXEffectCompilerImpl_SetInt,
4954     ID3DXEffectCompilerImpl_GetInt,
4955     ID3DXEffectCompilerImpl_SetIntArray,
4956     ID3DXEffectCompilerImpl_GetIntArray,
4957     ID3DXEffectCompilerImpl_SetFloat,
4958     ID3DXEffectCompilerImpl_GetFloat,
4959     ID3DXEffectCompilerImpl_SetFloatArray,
4960     ID3DXEffectCompilerImpl_GetFloatArray,
4961     ID3DXEffectCompilerImpl_SetVector,
4962     ID3DXEffectCompilerImpl_GetVector,
4963     ID3DXEffectCompilerImpl_SetVectorArray,
4964     ID3DXEffectCompilerImpl_GetVectorArray,
4965     ID3DXEffectCompilerImpl_SetMatrix,
4966     ID3DXEffectCompilerImpl_GetMatrix,
4967     ID3DXEffectCompilerImpl_SetMatrixArray,
4968     ID3DXEffectCompilerImpl_GetMatrixArray,
4969     ID3DXEffectCompilerImpl_SetMatrixPointerArray,
4970     ID3DXEffectCompilerImpl_GetMatrixPointerArray,
4971     ID3DXEffectCompilerImpl_SetMatrixTranspose,
4972     ID3DXEffectCompilerImpl_GetMatrixTranspose,
4973     ID3DXEffectCompilerImpl_SetMatrixTransposeArray,
4974     ID3DXEffectCompilerImpl_GetMatrixTransposeArray,
4975     ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray,
4976     ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray,
4977     ID3DXEffectCompilerImpl_SetString,
4978     ID3DXEffectCompilerImpl_GetString,
4979     ID3DXEffectCompilerImpl_SetTexture,
4980     ID3DXEffectCompilerImpl_GetTexture,
4981     ID3DXEffectCompilerImpl_GetPixelShader,
4982     ID3DXEffectCompilerImpl_GetVertexShader,
4983     ID3DXEffectCompilerImpl_SetArrayRange,
4984     /*** ID3DXEffectCompiler methods ***/
4985     ID3DXEffectCompilerImpl_SetLiteral,
4986     ID3DXEffectCompilerImpl_GetLiteral,
4987     ID3DXEffectCompilerImpl_CompileEffect,
4988     ID3DXEffectCompilerImpl_CompileShader,
4989 };
4990 
4991 static HRESULT d3dx_parse_sampler(struct d3dx_effect *effect, struct d3dx_sampler *sampler,
4992         const char *data, const char **ptr, struct d3dx_object *objects)
4993 {
4994     HRESULT hr;
4995     UINT i;
4996 
4997     read_dword(ptr, &sampler->state_count);
4998     TRACE("Count: %u\n", sampler->state_count);
4999 
5000     sampler->states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler->states) * sampler->state_count);
5001     if (!sampler->states)
5002     {
5003         ERR("Out of memory\n");
5004         return E_OUTOFMEMORY;
5005     }
5006 
5007     for (i = 0; i < sampler->state_count; ++i)
5008     {
5009         hr = d3dx_parse_state(effect, &sampler->states[i], data, ptr, objects);
5010         if (hr != D3D_OK)
5011         {
5012             WARN("Failed to parse state %u\n", i);
5013             goto err_out;
5014         }
5015     }
5016 
5017     return D3D_OK;
5018 
5019 err_out:
5020 
5021     for (i = 0; i < sampler->state_count; ++i)
5022     {
5023         free_state(&sampler->states[i]);
5024     }
5025     HeapFree(GetProcessHeap(), 0, sampler->states);
5026     sampler->states = NULL;
5027 
5028     return hr;
5029 }
5030 
5031 static HRESULT d3dx_parse_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5032         void *value, const char *data, const char **ptr, struct d3dx_object *objects)
5033 {
5034     unsigned int i;
5035     HRESULT hr;
5036     UINT old_size = 0;
5037 
5038     if (param->element_count)
5039     {
5040         param->data = value;
5041 
5042         for (i = 0; i < param->element_count; ++i)
5043         {
5044             struct d3dx_parameter *member = &param->members[i];
5045 
5046             hr = d3dx_parse_value(effect, member, value ? (char *)value + old_size : NULL, data, ptr, objects);
5047             if (hr != D3D_OK)
5048             {
5049                 WARN("Failed to parse value %u\n", i);
5050                 return hr;
5051             }
5052 
5053             old_size += member->bytes;
5054         }
5055 
5056         return D3D_OK;
5057     }
5058 
5059     switch(param->class)
5060     {
5061         case D3DXPC_SCALAR:
5062         case D3DXPC_VECTOR:
5063         case D3DXPC_MATRIX_ROWS:
5064         case D3DXPC_MATRIX_COLUMNS:
5065             param->data = value;
5066             break;
5067 
5068         case D3DXPC_STRUCT:
5069             param->data = value;
5070 
5071             for (i = 0; i < param->member_count; ++i)
5072             {
5073                 struct d3dx_parameter *member = &param->members[i];
5074 
5075                 hr = d3dx_parse_value(effect, member, (char *)value + old_size, data, ptr, objects);
5076                 if (hr != D3D_OK)
5077                 {
5078                     WARN("Failed to parse value %u\n", i);
5079                     return hr;
5080                 }
5081 
5082                 old_size += member->bytes;
5083             }
5084             break;
5085 
5086         case D3DXPC_OBJECT:
5087             switch (param->type)
5088             {
5089                 case D3DXPT_STRING:
5090                 case D3DXPT_TEXTURE:
5091                 case D3DXPT_TEXTURE1D:
5092                 case D3DXPT_TEXTURE2D:
5093                 case D3DXPT_TEXTURE3D:
5094                 case D3DXPT_TEXTURECUBE:
5095                 case D3DXPT_PIXELSHADER:
5096                 case D3DXPT_VERTEXSHADER:
5097                     read_dword(ptr, &param->object_id);
5098                     TRACE("Id: %u\n", param->object_id);
5099                     objects[param->object_id].param = param;
5100                     param->data = value;
5101                     break;
5102 
5103                 case D3DXPT_SAMPLER:
5104                 case D3DXPT_SAMPLER1D:
5105                 case D3DXPT_SAMPLER2D:
5106                 case D3DXPT_SAMPLER3D:
5107                 case D3DXPT_SAMPLERCUBE:
5108                 {
5109                     struct d3dx_sampler *sampler;
5110 
5111                     sampler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sampler));
5112                     if (!sampler)
5113                         return E_OUTOFMEMORY;
5114 
5115                     hr = d3dx_parse_sampler(effect, sampler, data, ptr, objects);
5116                     if (hr != D3D_OK)
5117                     {
5118                         HeapFree(GetProcessHeap(), 0, sampler);
5119                         WARN("Failed to parse sampler\n");
5120                         return hr;
5121                     }
5122 
5123                     param->data = sampler;
5124                     break;
5125                 }
5126 
5127                 default:
5128                     FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5129                     break;
5130             }
5131             break;
5132 
5133         default:
5134             FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5135             break;
5136     }
5137 
5138     return D3D_OK;
5139 }
5140 
5141 static HRESULT d3dx_parse_init_value(struct d3dx_effect *effect, struct d3dx_parameter *param,
5142         const char *data, const char *ptr, struct d3dx_object *objects)
5143 {
5144     UINT size = param->bytes;
5145     HRESULT hr;
5146     void *value = NULL;
5147 
5148     TRACE("param size: %u\n", size);
5149 
5150     if (size)
5151     {
5152         value = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5153         if (!value)
5154         {
5155             ERR("Failed to allocate data memory.\n");
5156             return E_OUTOFMEMORY;
5157         }
5158 
5159         switch(param->class)
5160         {
5161             case D3DXPC_OBJECT:
5162                 break;
5163 
5164             case D3DXPC_SCALAR:
5165             case D3DXPC_VECTOR:
5166             case D3DXPC_MATRIX_ROWS:
5167             case D3DXPC_MATRIX_COLUMNS:
5168             case D3DXPC_STRUCT:
5169                 TRACE("Data: %s.\n", debugstr_an(ptr, size));
5170                 memcpy(value, ptr, size);
5171                 break;
5172 
5173             default:
5174                 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5175                 break;
5176         }
5177     }
5178 
5179     hr = d3dx_parse_value(effect, param, value, data, &ptr, objects);
5180     if (hr != D3D_OK)
5181     {
5182         WARN("Failed to parse value\n");
5183         HeapFree(GetProcessHeap(), 0, value);
5184         return hr;
5185     }
5186 
5187     return D3D_OK;
5188 }
5189 
5190 static HRESULT d3dx9_parse_name(char **name, const char *ptr)
5191 {
5192     DWORD size;
5193 
5194     read_dword(&ptr, &size);
5195     TRACE("Name size: %#x\n", size);
5196 
5197     if (!size)
5198     {
5199         return D3D_OK;
5200     }
5201 
5202     *name = HeapAlloc(GetProcessHeap(), 0, size);
5203     if (!*name)
5204     {
5205         ERR("Failed to allocate name memory.\n");
5206         return E_OUTOFMEMORY;
5207     }
5208 
5209     TRACE("Name: %s.\n", debugstr_an(ptr, size));
5210     memcpy(*name, ptr, size);
5211 
5212     return D3D_OK;
5213 }
5214 
5215 static HRESULT d3dx9_copy_data(struct d3dx_effect *effect, unsigned int object_id, const char **ptr)
5216 {
5217     struct d3dx_object *object = &effect->objects[object_id];
5218 
5219     if (object->size || object->data)
5220     {
5221         if (object_id)
5222             FIXME("Overwriting object id %u!\n", object_id);
5223         else
5224             TRACE("Overwriting object id 0.\n");
5225 
5226         HeapFree(GetProcessHeap(), 0, object->data);
5227         object->data = NULL;
5228     }
5229 
5230     read_dword(ptr, &object->size);
5231     TRACE("Data size: %#x.\n", object->size);
5232 
5233     if (!object->size)
5234         return D3D_OK;
5235 
5236     object->data = HeapAlloc(GetProcessHeap(), 0, object->size);
5237     if (!object->data)
5238     {
5239         ERR("Failed to allocate object memory.\n");
5240         return E_OUTOFMEMORY;
5241     }
5242 
5243     TRACE("Data: %s.\n", debugstr_an(*ptr, object->size));
5244     memcpy(object->data, *ptr, object->size);
5245 
5246     *ptr += ((object->size + 3) & ~3);
5247 
5248     return D3D_OK;
5249 }
5250 
5251 static void param_set_magic_number(struct d3dx_parameter *param)
5252 {
5253     memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string));
5254 }
5255 
5256 static int param_rb_compare(const void *key, const struct wine_rb_entry *entry)
5257 {
5258     const char *name = key;
5259     struct d3dx_parameter *param = WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
5260 
5261     return strcmp(name, param->full_name);
5262 }
5263 
5264 static void add_param_to_tree(struct d3dx_effect *effect, struct d3dx_parameter *param,
5265         struct d3dx_parameter *parent, char separator, unsigned int element)
5266 {
5267     const char *parent_name = parent ? parent->full_name : NULL;
5268     unsigned int i;
5269 
5270     TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n",
5271             param, debugstr_a(param->name), parent, element);
5272 
5273     if (parent_name)
5274     {
5275         unsigned int parent_name_len = strlen(parent_name);
5276         unsigned int name_len = strlen(param->name);
5277         unsigned int part_str_len;
5278         unsigned int len;
5279         char part_str[16];
5280 
5281         if (separator == '[')
5282         {
5283             sprintf(part_str, "[%u]", element);
5284             part_str_len = strlen(part_str);
5285             name_len = 0;
5286         }
5287         else
5288         {
5289             part_str[0] = separator;
5290             part_str[1] = 0;
5291             part_str_len = 1;
5292         }
5293         len = parent_name_len + part_str_len + name_len + 1;
5294 
5295         if (!(param->full_name = heap_alloc(len)))
5296         {
5297             ERR("Out of memory.\n");
5298             return;
5299         }
5300 
5301         memcpy(param->full_name, parent_name, parent_name_len);
5302         memcpy(param->full_name + parent_name_len, part_str, part_str_len);
5303         memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len);
5304         param->full_name[len - 1] = 0;
5305     }
5306     else
5307     {
5308         unsigned int len = strlen(param->name) + 1;
5309 
5310         if (!(param->full_name = heap_alloc(len)))
5311         {
5312             ERR("Out of memory.\n");
5313             return;
5314         }
5315 
5316         memcpy(param->full_name, param->name, len);
5317     }
5318     TRACE("Full name is %s.\n", param->full_name);
5319     wine_rb_put(&effect->param_tree, param->full_name, &param->rb_entry);
5320 
5321     if (is_top_level_parameter(param))
5322         for (i = 0; i < param->top_level_param->annotation_count; ++i)
5323             add_param_to_tree(effect, &param->top_level_param->annotations[i], param, '@', 0);
5324 
5325     if (param->element_count)
5326         for (i = 0; i < param->element_count; ++i)
5327             add_param_to_tree(effect, &param->members[i], param, '[', i);
5328     else
5329         for (i = 0; i < param->member_count; ++i)
5330             add_param_to_tree(effect, &param->members[i], param, '.', 0);
5331 }
5332 
5333 static HRESULT d3dx_parse_effect_typedef(struct d3dx_effect *effect, struct d3dx_parameter *param,
5334 	const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags)
5335 {
5336     DWORD offset;
5337     HRESULT hr;
5338     UINT i;
5339 
5340     param->flags = flags;
5341 
5342     if (!parent)
5343     {
5344         read_dword(ptr, (DWORD *)&param->type);
5345         TRACE("Type: %s\n", debug_d3dxparameter_type(param->type));
5346 
5347         read_dword(ptr, (DWORD *)&param->class);
5348         TRACE("Class: %s\n", debug_d3dxparameter_class(param->class));
5349 
5350         read_dword(ptr, &offset);
5351         TRACE("Type name offset: %#x\n", offset);
5352         hr = d3dx9_parse_name(&param->name, data + offset);
5353         if (hr != D3D_OK)
5354         {
5355             WARN("Failed to parse name\n");
5356             goto err_out;
5357         }
5358 
5359         read_dword(ptr, &offset);
5360         TRACE("Type semantic offset: %#x\n", offset);
5361         hr = d3dx9_parse_name(&param->semantic, data + offset);
5362         if (hr != D3D_OK)
5363         {
5364             WARN("Failed to parse semantic\n");
5365             goto err_out;
5366         }
5367 
5368         read_dword(ptr, &param->element_count);
5369         TRACE("Elements: %u\n", param->element_count);
5370 
5371         switch (param->class)
5372         {
5373             case D3DXPC_VECTOR:
5374                 read_dword(ptr, &param->columns);
5375                 TRACE("Columns: %u\n", param->columns);
5376 
5377                 read_dword(ptr, &param->rows);
5378                 TRACE("Rows: %u\n", param->rows);
5379 
5380                 /* sizeof(DWORD) * rows * columns */
5381                 param->bytes = 4 * param->rows * param->columns;
5382                 break;
5383 
5384             case D3DXPC_SCALAR:
5385             case D3DXPC_MATRIX_ROWS:
5386             case D3DXPC_MATRIX_COLUMNS:
5387                 read_dword(ptr, &param->rows);
5388                 TRACE("Rows: %u\n", param->rows);
5389 
5390                 read_dword(ptr, &param->columns);
5391                 TRACE("Columns: %u\n", param->columns);
5392 
5393                 /* sizeof(DWORD) * rows * columns */
5394                 param->bytes = 4 * param->rows * param->columns;
5395                 break;
5396 
5397             case D3DXPC_STRUCT:
5398                 read_dword(ptr, &param->member_count);
5399                 TRACE("Members: %u\n", param->member_count);
5400                 break;
5401 
5402             case D3DXPC_OBJECT:
5403                 switch (param->type)
5404                 {
5405                     case D3DXPT_STRING:
5406                     case D3DXPT_PIXELSHADER:
5407                     case D3DXPT_VERTEXSHADER:
5408                     case D3DXPT_TEXTURE:
5409                     case D3DXPT_TEXTURE1D:
5410                     case D3DXPT_TEXTURE2D:
5411                     case D3DXPT_TEXTURE3D:
5412                     case D3DXPT_TEXTURECUBE:
5413                         param->bytes = sizeof(void *);
5414                         break;
5415 
5416                     case D3DXPT_SAMPLER:
5417                     case D3DXPT_SAMPLER1D:
5418                     case D3DXPT_SAMPLER2D:
5419                     case D3DXPT_SAMPLER3D:
5420                     case D3DXPT_SAMPLERCUBE:
5421                         param->bytes = 0;
5422                         break;
5423 
5424                     default:
5425                         FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
5426                         break;
5427                 }
5428                 break;
5429 
5430             default:
5431                 FIXME("Unhandled class %s\n", debug_d3dxparameter_class(param->class));
5432                 break;
5433         }
5434     }
5435     else
5436     {
5437         /* elements */
5438         param->type = parent->type;
5439         param->class = parent->class;
5440         param->name = parent->name;
5441         param->semantic = parent->semantic;
5442         param->element_count = 0;
5443         param->member_count = parent->member_count;
5444         param->bytes = parent->bytes;
5445         param->rows = parent->rows;
5446         param->columns = parent->columns;
5447     }
5448 
5449     if (param->element_count)
5450     {
5451         unsigned int param_bytes = 0;
5452         const char *save_ptr = *ptr;
5453 
5454         param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->element_count);
5455         if (!param->members)
5456         {
5457             ERR("Out of memory\n");
5458             hr = E_OUTOFMEMORY;
5459             goto err_out;
5460         }
5461 
5462         for (i = 0; i < param->element_count; ++i)
5463         {
5464             *ptr = save_ptr;
5465 
5466             param_set_magic_number(&param->members[i]);
5467             hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, param, flags);
5468             if (hr != D3D_OK)
5469             {
5470                 WARN("Failed to parse member %u\n", i);
5471                 goto err_out;
5472             }
5473 
5474             param_bytes += param->members[i].bytes;
5475         }
5476 
5477         param->bytes = param_bytes;
5478     }
5479     else if (param->member_count)
5480     {
5481         param->members = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*param->members) * param->member_count);
5482         if (!param->members)
5483         {
5484             ERR("Out of memory\n");
5485             hr = E_OUTOFMEMORY;
5486             goto err_out;
5487         }
5488 
5489         for (i = 0; i < param->member_count; ++i)
5490         {
5491             param_set_magic_number(&param->members[i]);
5492             hr = d3dx_parse_effect_typedef(effect, &param->members[i], data, ptr, NULL, flags);
5493             if (hr != D3D_OK)
5494             {
5495                 WARN("Failed to parse member %u\n", i);
5496                 goto err_out;
5497             }
5498 
5499             param->bytes += param->members[i].bytes;
5500         }
5501     }
5502     return D3D_OK;
5503 
5504 err_out:
5505 
5506     if (param->members)
5507     {
5508         unsigned int count = param->element_count ? param->element_count : param->member_count;
5509 
5510         for (i = 0; i < count; ++i)
5511             free_parameter(&param->members[i], param->element_count != 0, TRUE);
5512         HeapFree(GetProcessHeap(), 0, param->members);
5513         param->members = NULL;
5514     }
5515 
5516     if (!parent)
5517     {
5518         HeapFree(GetProcessHeap(), 0, param->name);
5519         HeapFree(GetProcessHeap(), 0, param->semantic);
5520     }
5521     param->name = NULL;
5522     param->semantic = NULL;
5523 
5524     return hr;
5525 }
5526 
5527 static HRESULT d3dx_parse_effect_annotation(struct d3dx_effect *effect, struct d3dx_parameter *anno,
5528         const char *data, const char **ptr, struct d3dx_object *objects)
5529 {
5530     DWORD offset;
5531     const char *ptr2;
5532     HRESULT hr;
5533 
5534     anno->flags = D3DX_PARAMETER_ANNOTATION;
5535 
5536     read_dword(ptr, &offset);
5537     TRACE("Typedef offset: %#x\n", offset);
5538     ptr2 = data + offset;
5539     hr = d3dx_parse_effect_typedef(effect, anno, data, &ptr2, NULL, D3DX_PARAMETER_ANNOTATION);
5540     if (hr != D3D_OK)
5541     {
5542         WARN("Failed to parse type definition\n");
5543         return hr;
5544     }
5545 
5546     read_dword(ptr, &offset);
5547     TRACE("Value offset: %#x\n", offset);
5548     hr = d3dx_parse_init_value(effect, anno, data, data + offset, objects);
5549     if (hr != D3D_OK)
5550     {
5551         WARN("Failed to parse value\n");
5552         return hr;
5553     }
5554 
5555     return D3D_OK;
5556 }
5557 
5558 static HRESULT d3dx_parse_state(struct d3dx_effect *effect, struct d3dx_state *state,
5559         const char *data, const char **ptr, struct d3dx_object *objects)
5560 {
5561     struct d3dx_parameter *param = &state->parameter;
5562     enum STATE_CLASS state_class;
5563     const char *ptr2;
5564     void *new_data;
5565     DWORD offset;
5566     HRESULT hr;
5567 
5568     state->type = ST_CONSTANT;
5569 
5570     read_dword(ptr, &state->operation);
5571     if (state->operation >= ARRAY_SIZE(state_table))
5572     {
5573         WARN("Unknown state operation %u.\n", state->operation);
5574         return D3DERR_INVALIDCALL;
5575     }
5576 
5577     TRACE("Operation: %#x (%s)\n", state->operation, state_table[state->operation].name);
5578 
5579     read_dword(ptr, &state->index);
5580     TRACE("Index: %#x\n", state->index);
5581 
5582     read_dword(ptr, &offset);
5583     TRACE("Typedef offset: %#x\n", offset);
5584     ptr2 = data + offset;
5585     hr = d3dx_parse_effect_typedef(effect, param, data, &ptr2, NULL, 0);
5586     if (hr != D3D_OK)
5587     {
5588         WARN("Failed to parse type definition\n");
5589         goto err_out;
5590     }
5591 
5592     read_dword(ptr, &offset);
5593     TRACE("Value offset: %#x\n", offset);
5594     hr = d3dx_parse_init_value(effect, param, data, data + offset, objects);
5595     if (hr != D3D_OK)
5596     {
5597         WARN("Failed to parse value\n");
5598         goto err_out;
5599     }
5600 
5601     if (((state_class = state_table[state->operation].class) == SC_VERTEXSHADER
5602             || state_class == SC_PIXELSHADER || state_class == SC_TEXTURE)
5603             && param->bytes < sizeof(void *))
5604     {
5605         if (param->type != D3DXPT_INT || *(unsigned int *)param->data)
5606         {
5607             FIXME("Unexpected parameter for object, param->type %#x, param->class %#x, *param->data %#x.\n",
5608                     param->type, param->class, *(unsigned int *)param->data);
5609             hr = D3DXERR_INVALIDDATA;
5610             goto err_out;
5611         }
5612 
5613         new_data = heap_realloc(param->data, sizeof(void *));
5614         if (!new_data)
5615         {
5616             ERR("Out of memory.\n");
5617             hr = E_OUTOFMEMORY;
5618             goto err_out;
5619         }
5620         memset(new_data, 0, sizeof(void *));
5621         param->data = new_data;
5622         param->bytes = sizeof(void *);
5623     }
5624 
5625     return D3D_OK;
5626 
5627 err_out:
5628 
5629     free_parameter(param, FALSE, FALSE);
5630 
5631     return hr;
5632 }
5633 
5634 static HRESULT d3dx_parse_effect_parameter(struct d3dx_effect *effect, struct d3dx_top_level_parameter *param,
5635         const char *data, const char **ptr, struct d3dx_object *objects)
5636 {
5637     DWORD offset;
5638     HRESULT hr;
5639     unsigned int i;
5640     const char *ptr2;
5641 
5642     read_dword(ptr, &offset);
5643     TRACE("Typedef offset: %#x.\n", offset);
5644     ptr2 = data + offset;
5645 
5646     read_dword(ptr, &offset);
5647     TRACE("Value offset: %#x.\n", offset);
5648 
5649     read_dword(ptr, &param->param.flags);
5650     TRACE("Flags: %#x.\n", param->param.flags);
5651 
5652     read_dword(ptr, &param->annotation_count);
5653     TRACE("Annotation count: %u.\n", param->annotation_count);
5654 
5655     hr = d3dx_parse_effect_typedef(effect, &param->param, data, &ptr2, NULL, param->param.flags);
5656     if (hr != D3D_OK)
5657     {
5658         WARN("Failed to parse type definition.\n");
5659         return hr;
5660     }
5661 
5662     hr = d3dx_parse_init_value(effect, &param->param, data, data + offset, objects);
5663     if (hr != D3D_OK)
5664     {
5665         WARN("Failed to parse value.\n");
5666         return hr;
5667     }
5668 
5669     if (param->annotation_count)
5670     {
5671         param->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5672                 sizeof(*param->annotations) * param->annotation_count);
5673         if (!param->annotations)
5674         {
5675             ERR("Out of memory.\n");
5676             hr = E_OUTOFMEMORY;
5677             goto err_out;
5678         }
5679 
5680         for (i = 0; i < param->annotation_count; ++i)
5681         {
5682             param_set_magic_number(&param->annotations[i]);
5683             hr = d3dx_parse_effect_annotation(effect, &param->annotations[i], data, ptr, objects);
5684             if (hr != D3D_OK)
5685             {
5686                 WARN("Failed to parse annotation.\n");
5687                 goto err_out;
5688             }
5689         }
5690     }
5691 
5692     return D3D_OK;
5693 
5694 err_out:
5695 
5696     if (param->annotations)
5697     {
5698         for (i = 0; i < param->annotation_count; ++i)
5699             free_parameter(&param->annotations[i], FALSE, FALSE);
5700         HeapFree(GetProcessHeap(), 0, param->annotations);
5701         param->annotations = NULL;
5702     }
5703 
5704     return hr;
5705 }
5706 
5707 static HRESULT d3dx_parse_effect_pass(struct d3dx_effect *effect, struct d3dx_pass *pass,
5708         const char *data, const char **ptr, struct d3dx_object *objects)
5709 {
5710     DWORD offset;
5711     HRESULT hr;
5712     unsigned int i;
5713     struct d3dx_state *states = NULL;
5714     char *name = NULL;
5715 
5716     read_dword(ptr, &offset);
5717     TRACE("Pass name offset: %#x\n", offset);
5718     hr = d3dx9_parse_name(&name, data + offset);
5719     if (hr != D3D_OK)
5720     {
5721         WARN("Failed to parse name\n");
5722         goto err_out;
5723     }
5724 
5725     read_dword(ptr, &pass->annotation_count);
5726     TRACE("Annotation count: %u\n", pass->annotation_count);
5727 
5728     read_dword(ptr, &pass->state_count);
5729     TRACE("State count: %u\n", pass->state_count);
5730 
5731     if (pass->annotation_count)
5732     {
5733         pass->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5734                 sizeof(*pass->annotations) * pass->annotation_count);
5735         if (!pass->annotations)
5736         {
5737             ERR("Out of memory\n");
5738             hr = E_OUTOFMEMORY;
5739             goto err_out;
5740         }
5741 
5742         for (i = 0; i < pass->annotation_count; ++i)
5743         {
5744             param_set_magic_number(&pass->annotations[i]);
5745             hr = d3dx_parse_effect_annotation(effect, &pass->annotations[i], data, ptr, objects);
5746             if (hr != D3D_OK)
5747             {
5748                 WARN("Failed to parse annotation %u\n", i);
5749                 goto err_out;
5750             }
5751         }
5752     }
5753 
5754     if (pass->state_count)
5755     {
5756         states = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*states) * pass->state_count);
5757         if (!states)
5758         {
5759             ERR("Out of memory\n");
5760             hr = E_OUTOFMEMORY;
5761             goto err_out;
5762         }
5763 
5764         for (i = 0; i < pass->state_count; ++i)
5765         {
5766             hr = d3dx_parse_state(effect, &states[i], data, ptr, objects);
5767             if (hr != D3D_OK)
5768             {
5769                 WARN("Failed to parse annotation %u\n", i);
5770                 goto err_out;
5771             }
5772         }
5773     }
5774 
5775     pass->name = name;
5776     pass->states = states;
5777 
5778     return D3D_OK;
5779 
5780 err_out:
5781 
5782     if (pass->annotations)
5783     {
5784         for (i = 0; i < pass->annotation_count; ++i)
5785             free_parameter(&pass->annotations[i], FALSE, FALSE);
5786         HeapFree(GetProcessHeap(), 0, pass->annotations);
5787         pass->annotations = NULL;
5788     }
5789 
5790     if (states)
5791     {
5792         for (i = 0; i < pass->state_count; ++i)
5793         {
5794             free_state(&states[i]);
5795         }
5796         HeapFree(GetProcessHeap(), 0, states);
5797     }
5798 
5799     HeapFree(GetProcessHeap(), 0, name);
5800 
5801     return hr;
5802 }
5803 
5804 static HRESULT d3dx_parse_effect_technique(struct d3dx_effect *effect, struct d3dx_technique *technique,
5805         const char *data, const char **ptr, struct d3dx_object *objects)
5806 {
5807     DWORD offset;
5808     HRESULT hr;
5809     unsigned int i;
5810     char *name = NULL;
5811 
5812     read_dword(ptr, &offset);
5813     TRACE("Technique name offset: %#x\n", offset);
5814     hr = d3dx9_parse_name(&name, data + offset);
5815     if (hr != D3D_OK)
5816     {
5817         WARN("Failed to parse name\n");
5818         goto err_out;
5819     }
5820 
5821     read_dword(ptr, &technique->annotation_count);
5822     TRACE("Annotation count: %u\n", technique->annotation_count);
5823 
5824     read_dword(ptr, &technique->pass_count);
5825     TRACE("Pass count: %u\n", technique->pass_count);
5826 
5827     if (technique->annotation_count)
5828     {
5829         technique->annotations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5830                 sizeof(*technique->annotations) * technique->annotation_count);
5831         if (!technique->annotations)
5832         {
5833             ERR("Out of memory\n");
5834             hr = E_OUTOFMEMORY;
5835             goto err_out;
5836         }
5837 
5838         for (i = 0; i < technique->annotation_count; ++i)
5839         {
5840             param_set_magic_number(&technique->annotations[i]);
5841             hr = d3dx_parse_effect_annotation(effect, &technique->annotations[i], data, ptr, objects);
5842             if (hr != D3D_OK)
5843             {
5844                 WARN("Failed to parse annotation %u\n", i);
5845                 goto err_out;
5846             }
5847         }
5848     }
5849 
5850     if (technique->pass_count)
5851     {
5852         technique->passes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5853                 sizeof(*technique->passes) * technique->pass_count);
5854         if (!technique->passes)
5855         {
5856             ERR("Out of memory\n");
5857             hr = E_OUTOFMEMORY;
5858             goto err_out;
5859         }
5860 
5861         for (i = 0; i < technique->pass_count; ++i)
5862         {
5863             hr = d3dx_parse_effect_pass(effect, &technique->passes[i], data, ptr, objects);
5864             if (hr != D3D_OK)
5865             {
5866                 WARN("Failed to parse pass %u\n", i);
5867                 goto err_out;
5868             }
5869         }
5870     }
5871 
5872     technique->name = name;
5873 
5874     return D3D_OK;
5875 
5876 err_out:
5877 
5878     if (technique->passes)
5879     {
5880         for (i = 0; i < technique->pass_count; ++i)
5881             free_pass(&technique->passes[i]);
5882         HeapFree(GetProcessHeap(), 0, technique->passes);
5883         technique->passes = NULL;
5884     }
5885 
5886     if (technique->annotations)
5887     {
5888         for (i = 0; i < technique->annotation_count; ++i)
5889             free_parameter(&technique->annotations[i], FALSE, FALSE);
5890         HeapFree(GetProcessHeap(), 0, technique->annotations);
5891         technique->annotations = NULL;
5892     }
5893 
5894     HeapFree(GetProcessHeap(), 0, name);
5895 
5896     return hr;
5897 }
5898 
5899 static HRESULT d3dx9_create_object(struct d3dx_effect *effect, struct d3dx_object *object)
5900 {
5901     struct d3dx_parameter *param = object->param;
5902     IDirect3DDevice9 *device = effect->device;
5903     HRESULT hr;
5904 
5905     if (*(char **)param->data)
5906         ERR("Parameter data already allocated.\n");
5907 
5908     switch (param->type)
5909     {
5910         case D3DXPT_STRING:
5911             *(char **)param->data = HeapAlloc(GetProcessHeap(), 0, object->size);
5912             if (!*(char **)param->data)
5913             {
5914                 ERR("Out of memory.\n");
5915                 return E_OUTOFMEMORY;
5916             }
5917             memcpy(*(char **)param->data, object->data, object->size);
5918             break;
5919         case D3DXPT_VERTEXSHADER:
5920             if (FAILED(hr = IDirect3DDevice9_CreateVertexShader(device, object->data,
5921                     (IDirect3DVertexShader9 **)param->data)))
5922             {
5923                 WARN("Failed to create vertex shader.\n");
5924                 object->creation_failed = TRUE;
5925             }
5926             break;
5927         case D3DXPT_PIXELSHADER:
5928             if (FAILED(hr = IDirect3DDevice9_CreatePixelShader(device, object->data,
5929                     (IDirect3DPixelShader9 **)param->data)))
5930             {
5931                 WARN("Failed to create pixel shader.\n");
5932                 object->creation_failed = TRUE;
5933             }
5934             break;
5935         default:
5936             break;
5937     }
5938     return D3D_OK;
5939 }
5940 
5941 static HRESULT d3dx_parse_array_selector(struct d3dx_effect *effect, struct d3dx_state *state,
5942         const char **skip_constants, unsigned int skip_constants_count)
5943 {
5944     DWORD string_size;
5945     struct d3dx_parameter *param = &state->parameter;
5946     struct d3dx_object *object = &effect->objects[param->object_id];
5947     char *ptr = object->data;
5948     HRESULT ret;
5949 
5950     TRACE("Parsing array entry selection state for parameter %p.\n", param);
5951 
5952     string_size = *(DWORD *)ptr;
5953     state->referenced_param = get_parameter_by_name(effect, NULL, ptr + 4);
5954     if (state->referenced_param)
5955     {
5956         TRACE("Mapping to parameter %s.\n", debugstr_a(state->referenced_param->name));
5957     }
5958     else
5959     {
5960         FIXME("Referenced parameter %s not found.\n", ptr + 4);
5961         return D3DXERR_INVALIDDATA;
5962     }
5963     TRACE("Unknown DWORD: 0x%.8x.\n", *(DWORD *)(ptr + string_size));
5964 
5965     if (string_size % sizeof(DWORD))
5966         FIXME("Unaligned string_size %u.\n", string_size);
5967     if (FAILED(ret = d3dx_create_param_eval(effect, (DWORD *)(ptr + string_size) + 1,
5968             object->size - (string_size + sizeof(DWORD)), D3DXPT_INT, &param->param_eval,
5969             get_version_counter_ptr(effect), NULL, 0)))
5970         return ret;
5971     ret = D3D_OK;
5972     param = state->referenced_param;
5973     if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER)
5974     {
5975         unsigned int i;
5976 
5977         for (i = 0; i < param->element_count; i++)
5978         {
5979             if (param->members[i].type != param->type)
5980             {
5981                 FIXME("Unexpected member parameter type %u, expected %u.\n", param->members[i].type, param->type);
5982                 return D3DXERR_INVALIDDATA;
5983             }
5984             if (!param->members[i].param_eval)
5985             {
5986                 TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
5987                 object = &effect->objects[param->members[i].object_id];
5988                 if (FAILED(ret = d3dx_create_param_eval(effect, object->data, object->size, param->type,
5989                         &param->members[i].param_eval, get_version_counter_ptr(effect),
5990                         skip_constants, skip_constants_count)))
5991                     break;
5992             }
5993         }
5994     }
5995     return ret;
5996 }
5997 
5998 static HRESULT d3dx_parse_resource(struct d3dx_effect *effect, const char *data, const char **ptr,
5999         const char **skip_constants, unsigned int skip_constants_count)
6000 {
6001     DWORD technique_index;
6002     DWORD index, state_index, usage, element_index;
6003     struct d3dx_state *state;
6004     struct d3dx_parameter *param;
6005     struct d3dx_object *object;
6006     HRESULT hr = E_FAIL;
6007 
6008     read_dword(ptr, &technique_index);
6009     TRACE("technique_index: %u\n", technique_index);
6010 
6011     read_dword(ptr, &index);
6012     TRACE("index: %u\n", index);
6013 
6014     read_dword(ptr, &element_index);
6015     TRACE("element_index: %u\n", element_index);
6016 
6017     read_dword(ptr, &state_index);
6018     TRACE("state_index: %u\n", state_index);
6019 
6020     read_dword(ptr, &usage);
6021     TRACE("usage: %u\n", usage);
6022 
6023     if (technique_index == 0xffffffff)
6024     {
6025         struct d3dx_parameter *parameter;
6026         struct d3dx_sampler *sampler;
6027 
6028         if (index >= effect->parameter_count)
6029         {
6030             FIXME("Index out of bounds: index %u >= parameter_count %u\n", index, effect->parameter_count);
6031             return E_FAIL;
6032         }
6033 
6034         parameter = &effect->parameters[index].param;
6035         if (element_index != 0xffffffff)
6036         {
6037             if (element_index >= parameter->element_count && parameter->element_count != 0)
6038             {
6039                 FIXME("Index out of bounds: element_index %u >= element_count %u\n", element_index, parameter->element_count);
6040                 return E_FAIL;
6041             }
6042 
6043             if (parameter->element_count)
6044                 parameter = &parameter->members[element_index];
6045         }
6046 
6047         sampler = parameter->data;
6048         if (state_index >= sampler->state_count)
6049         {
6050             FIXME("Index out of bounds: state_index %u >= state_count %u\n", state_index, sampler->state_count);
6051             return E_FAIL;
6052         }
6053 
6054         state = &sampler->states[state_index];
6055     }
6056     else
6057     {
6058         struct d3dx_technique *technique;
6059         struct d3dx_pass *pass;
6060 
6061         if (technique_index >= effect->technique_count)
6062         {
6063             FIXME("Index out of bounds: technique_index %u >= technique_count %u.\n", technique_index,
6064                   effect->technique_count);
6065             return E_FAIL;
6066         }
6067 
6068         technique = &effect->techniques[technique_index];
6069         if (index >= technique->pass_count)
6070         {
6071             FIXME("Index out of bounds: index %u >= pass_count %u\n", index, technique->pass_count);
6072             return E_FAIL;
6073         }
6074 
6075         pass = &technique->passes[index];
6076         if (state_index >= pass->state_count)
6077         {
6078             FIXME("Index out of bounds: state_index %u >= state_count %u\n", state_index, pass->state_count);
6079             return E_FAIL;
6080         }
6081 
6082         state = &pass->states[state_index];
6083     }
6084 
6085     TRACE("State operation %#x (%s).\n", state->operation, state_table[state->operation].name);
6086     param = &state->parameter;
6087     TRACE("Using object id %u.\n", param->object_id);
6088     object = &effect->objects[param->object_id];
6089 
6090     TRACE("Usage %u: class %s, type %s.\n", usage, debug_d3dxparameter_class(param->class),
6091             debug_d3dxparameter_type(param->type));
6092     switch (usage)
6093     {
6094         case 0:
6095             switch (param->type)
6096             {
6097                 case D3DXPT_VERTEXSHADER:
6098                 case D3DXPT_PIXELSHADER:
6099                     state->type = ST_CONSTANT;
6100                     if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6101                         return hr;
6102 
6103                     if (object->data)
6104                     {
6105                         if (FAILED(hr = d3dx9_create_object(effect, object)))
6106                             return hr;
6107                         if (FAILED(hr = d3dx_create_param_eval(effect, object->data, object->size, param->type,
6108                                 &param->param_eval, get_version_counter_ptr(effect),
6109                                 skip_constants, skip_constants_count)))
6110                             return hr;
6111                     }
6112                     break;
6113 
6114                 case D3DXPT_BOOL:
6115                 case D3DXPT_INT:
6116                 case D3DXPT_FLOAT:
6117                 case D3DXPT_STRING:
6118                     state->type = ST_FXLC;
6119                     if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6120                         return hr;
6121                     if (FAILED(hr = d3dx_create_param_eval(effect, object->data, object->size, param->type,
6122                             &param->param_eval, get_version_counter_ptr(effect), NULL, 0)))
6123                         return hr;
6124                     break;
6125 
6126                 default:
6127                     FIXME("Unhandled type %s\n", debug_d3dxparameter_type(param->type));
6128                     break;
6129             }
6130             break;
6131 
6132         case 1:
6133             state->type = ST_PARAMETER;
6134             if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6135                 return hr;
6136 
6137             TRACE("Looking for parameter %s.\n", debugstr_a(object->data));
6138             state->referenced_param = get_parameter_by_name(effect, NULL, object->data);
6139             if (state->referenced_param)
6140             {
6141                 struct d3dx_parameter *refpar = state->referenced_param;
6142 
6143                 TRACE("Mapping to parameter %p, having object id %u.\n", refpar, refpar->object_id);
6144                 if (refpar->type == D3DXPT_VERTEXSHADER || refpar->type == D3DXPT_PIXELSHADER)
6145                 {
6146                     struct d3dx_object *refobj = &effect->objects[refpar->object_id];
6147 
6148                     if (!refpar->param_eval)
6149                     {
6150                         if (FAILED(hr = d3dx_create_param_eval(effect, refobj->data, refobj->size,
6151                                 refpar->type, &refpar->param_eval, get_version_counter_ptr(effect),
6152                                 skip_constants, skip_constants_count)))
6153                             return hr;
6154                     }
6155                 }
6156             }
6157             else
6158             {
6159                 FIXME("Referenced parameter %s not found.\n", (char *)object->data);
6160                 return D3DXERR_INVALIDDATA;
6161             }
6162             break;
6163 
6164         case 2:
6165             state->type = ST_ARRAY_SELECTOR;
6166             if (FAILED(hr = d3dx9_copy_data(effect, param->object_id, ptr)))
6167                 return hr;
6168             hr = d3dx_parse_array_selector(effect, state, skip_constants, skip_constants_count);
6169             break;
6170 
6171         default:
6172             FIXME("Unknown usage %x\n", usage);
6173             break;
6174     }
6175 
6176     return hr;
6177 }
6178 
6179 static BOOL param_set_top_level_param(void *top_level_param, struct d3dx_parameter *param)
6180 {
6181     param->top_level_param = top_level_param;
6182     return FALSE;
6183 }
6184 
6185 static HRESULT d3dx_parse_effect(struct d3dx_effect *effect, const char *data, UINT data_size,
6186         DWORD start, const char **skip_constants, unsigned int skip_constants_count)
6187 {
6188     const char *ptr = data + start;
6189     UINT stringcount, resourcecount;
6190     HRESULT hr;
6191     UINT i;
6192 
6193     read_dword(&ptr, &effect->parameter_count);
6194     TRACE("Parameter count: %u.\n", effect->parameter_count);
6195 
6196     read_dword(&ptr, &effect->technique_count);
6197     TRACE("Technique count: %u.\n", effect->technique_count);
6198 
6199     skip_dword_unknown(&ptr, 1);
6200 
6201     read_dword(&ptr, &effect->object_count);
6202     TRACE("Object count: %u.\n", effect->object_count);
6203 
6204     effect->objects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6205             sizeof(*effect->objects) * effect->object_count);
6206     if (!effect->objects)
6207     {
6208         ERR("Out of memory.\n");
6209         hr = E_OUTOFMEMORY;
6210         goto err_out;
6211     }
6212 
6213     wine_rb_init(&effect->param_tree, param_rb_compare);
6214     if (effect->parameter_count)
6215     {
6216         effect->parameters = heap_alloc_zero(sizeof(*effect->parameters) * effect->parameter_count);
6217         if (!effect->parameters)
6218         {
6219             ERR("Out of memory.\n");
6220             hr = E_OUTOFMEMORY;
6221             goto err_out;
6222         }
6223 
6224         for (i = 0; i < effect->parameter_count; ++i)
6225         {
6226             param_set_magic_number(&effect->parameters[i].param);
6227             hr = d3dx_parse_effect_parameter(effect, &effect->parameters[i], data, &ptr, effect->objects);
6228             if (hr != D3D_OK)
6229             {
6230                 WARN("Failed to parse parameter %u.\n", i);
6231                 goto err_out;
6232             }
6233             walk_parameter_tree(&effect->parameters[i].param, param_set_top_level_param, &effect->parameters[i]);
6234             add_param_to_tree(effect, &effect->parameters[i].param, NULL, 0, 0);
6235         }
6236     }
6237 
6238     if (effect->technique_count)
6239     {
6240         effect->techniques = heap_alloc_zero(sizeof(*effect->techniques) * effect->technique_count);
6241         if (!effect->techniques)
6242         {
6243             ERR("Out of memory.\n");
6244             hr = E_OUTOFMEMORY;
6245             goto err_out;
6246         }
6247 
6248         for (i = 0; i < effect->technique_count; ++i)
6249         {
6250             TRACE("Parsing technique %u.\n", i);
6251             hr = d3dx_parse_effect_technique(effect, &effect->techniques[i], data, &ptr, effect->objects);
6252             if (hr != D3D_OK)
6253             {
6254                 WARN("Failed to parse technique %u.\n", i);
6255                 goto err_out;
6256             }
6257         }
6258     }
6259 
6260     read_dword(&ptr, &stringcount);
6261     TRACE("String count: %u.\n", stringcount);
6262 
6263     read_dword(&ptr, &resourcecount);
6264     TRACE("Resource count: %u.\n", resourcecount);
6265 
6266     for (i = 0; i < stringcount; ++i)
6267     {
6268         DWORD id;
6269 
6270         read_dword(&ptr, &id);
6271         TRACE("id: %u.\n", id);
6272 
6273         if (FAILED(hr = d3dx9_copy_data(effect, id, &ptr)))
6274             goto err_out;
6275 
6276         if (effect->objects[id].data)
6277         {
6278             if (FAILED(hr = d3dx9_create_object(effect, &effect->objects[id])))
6279                 goto err_out;
6280         }
6281     }
6282 
6283     for (i = 0; i < resourcecount; ++i)
6284     {
6285         TRACE("parse resource %u.\n", i);
6286 
6287         hr = d3dx_parse_resource(effect, data, &ptr, skip_constants, skip_constants_count);
6288         if (hr != D3D_OK)
6289         {
6290             WARN("Failed to parse resource %u.\n", i);
6291             goto err_out;
6292         }
6293     }
6294 
6295     for (i = 0; i < effect->parameter_count; ++i)
6296     {
6297         if (FAILED(hr = d3dx_pool_sync_shared_parameter(effect->pool, &effect->parameters[i])))
6298             goto err_out;
6299         effect->parameters[i].version_counter = get_version_counter_ptr(effect);
6300         set_dirty(&effect->parameters[i].param);
6301     }
6302     return D3D_OK;
6303 
6304 err_out:
6305 
6306     if (effect->techniques)
6307     {
6308         for (i = 0; i < effect->technique_count; ++i)
6309             free_technique(&effect->techniques[i]);
6310         heap_free(effect->techniques);
6311         effect->techniques = NULL;
6312     }
6313 
6314     if (effect->parameters)
6315     {
6316         for (i = 0; i < effect->parameter_count; ++i)
6317         {
6318             free_top_level_parameter(&effect->parameters[i]);
6319         }
6320         heap_free(effect->parameters);
6321         effect->parameters = NULL;
6322     }
6323 
6324     if (effect->objects)
6325     {
6326         for (i = 0; i < effect->object_count; ++i)
6327         {
6328             free_object(&effect->objects[i]);
6329         }
6330         HeapFree(GetProcessHeap(), 0, effect->objects);
6331         effect->objects = NULL;
6332     }
6333 
6334     return hr;
6335 }
6336 
6337 #define INITIAL_CONST_NAMES_SIZE 4
6338 
6339 static char *next_valid_constant_name(char **string)
6340 {
6341     char *ret = *string;
6342     char *next;
6343 
6344     while (*ret && !isalpha(*ret) && *ret != '_')
6345         ++ret;
6346     if (!*ret)
6347         return NULL;
6348 
6349     next = ret + 1;
6350     while (isalpha(*next) || isdigit(*next) || *next == '_')
6351         ++next;
6352     if (*next)
6353         *next++ = 0;
6354     *string = next;
6355     return ret;
6356 }
6357 
6358 static const char **parse_skip_constants_string(char *skip_constants_string, unsigned int *names_count)
6359 {
6360     const char **names, **new_alloc;
6361     const char *name;
6362     char *s;
6363     unsigned int size = INITIAL_CONST_NAMES_SIZE;
6364 
6365     names = HeapAlloc(GetProcessHeap(), 0, sizeof(*names) * size);
6366     if (!names)
6367         return NULL;
6368 
6369     *names_count = 0;
6370     s = skip_constants_string;
6371     while ((name = next_valid_constant_name(&s)))
6372     {
6373         if (*names_count == size)
6374         {
6375             size *= 2;
6376             new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, sizeof(*names) * size);
6377             if (!new_alloc)
6378             {
6379                 HeapFree(GetProcessHeap(), 0, names);
6380                 return NULL;
6381             }
6382             names = new_alloc;
6383         }
6384         names[(*names_count)++] = name;
6385     }
6386     new_alloc = HeapReAlloc(GetProcessHeap(), 0, names, *names_count * sizeof(*names));
6387     if (!new_alloc)
6388         return names;
6389     return new_alloc;
6390 }
6391 
6392 static HRESULT d3dx9_effect_init(struct d3dx_effect *effect, struct IDirect3DDevice9 *device,
6393         const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6394         UINT eflags, ID3DBlob **errors, struct ID3DXEffectPool *pool, const char *skip_constants_string)
6395 {
6396 #if D3DX_SDK_VERSION <= 36
6397     UINT compile_flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
6398 #else
6399     UINT compile_flags = 0;
6400 #endif
6401     ID3DBlob *bytecode = NULL, *temp_errors = NULL;
6402     unsigned int skip_constants_count = 0;
6403     char *skip_constants_buffer = NULL;
6404     const char **skip_constants = NULL;
6405     const char *ptr = data;
6406     DWORD tag, offset;
6407     unsigned int i, j;
6408     HRESULT hr;
6409 
6410     TRACE("effect %p, device %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, errors %p, "
6411             "pool %p, skip_constants %s.\n",
6412             effect, device, data, data_size, defines, include, eflags, errors, pool,
6413             debugstr_a(skip_constants_string));
6414 
6415     effect->ID3DXEffect_iface.lpVtbl = &ID3DXEffect_Vtbl;
6416     effect->ref = 1;
6417 
6418     if (pool)
6419     {
6420         effect->pool = unsafe_impl_from_ID3DXEffectPool(pool);
6421         pool->lpVtbl->AddRef(pool);
6422     }
6423 
6424     IDirect3DDevice9_AddRef(device);
6425     effect->device = device;
6426 
6427     effect->flags = eflags;
6428 
6429     list_init(&effect->parameter_block_list);
6430 
6431     read_dword(&ptr, &tag);
6432     TRACE("Tag: %x\n", tag);
6433 
6434     if (tag != d3dx9_effect_version(9, 1))
6435     {
6436         TRACE("HLSL ASCII effect, trying to compile it.\n");
6437         hr = D3DCompile(data, data_size, NULL, defines, include,
6438                 NULL, "fx_2_0", compile_flags, eflags, &bytecode, &temp_errors);
6439         if (FAILED(hr))
6440         {
6441             WARN("Failed to compile ASCII effect.\n");
6442             if (bytecode)
6443                 ID3D10Blob_Release(bytecode);
6444             if (temp_errors)
6445             {
6446                 const char *error_string = ID3D10Blob_GetBufferPointer(temp_errors);
6447                 const char *string_ptr;
6448 
6449                 while (*error_string)
6450                 {
6451                     string_ptr = error_string;
6452                     while (*string_ptr && *string_ptr != '\n' && *string_ptr != '\r'
6453                            && string_ptr - error_string < 80)
6454                         ++string_ptr;
6455                     TRACE("%s\n", debugstr_an(error_string, string_ptr - error_string));
6456                     error_string = string_ptr;
6457                     while (*error_string == '\n' || *error_string == '\r')
6458                         ++error_string;
6459                 }
6460             }
6461             if (errors)
6462                 *errors = temp_errors;
6463             else if (temp_errors)
6464                 ID3D10Blob_Release(temp_errors);
6465             return hr;
6466         }
6467         if (!bytecode)
6468         {
6469             FIXME("No output from effect compilation.\n");
6470             return D3DERR_INVALIDCALL;
6471         }
6472         if (errors)
6473             *errors = temp_errors;
6474         else if (temp_errors)
6475             ID3D10Blob_Release(temp_errors);
6476 
6477         ptr = ID3D10Blob_GetBufferPointer(bytecode);
6478         read_dword(&ptr, &tag);
6479         TRACE("Tag: %x\n", tag);
6480     }
6481 
6482     if (skip_constants_string)
6483     {
6484         skip_constants_buffer = HeapAlloc(GetProcessHeap(), 0,
6485                 sizeof(*skip_constants_buffer) * (strlen(skip_constants_string) + 1));
6486         if (!skip_constants_buffer)
6487         {
6488             if (bytecode)
6489                 ID3D10Blob_Release(bytecode);
6490             return E_OUTOFMEMORY;
6491         }
6492         strcpy(skip_constants_buffer, skip_constants_string);
6493 
6494         if (!(skip_constants = parse_skip_constants_string(skip_constants_buffer, &skip_constants_count)))
6495         {
6496             HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6497             if (bytecode)
6498                 ID3D10Blob_Release(bytecode);
6499             return E_OUTOFMEMORY;
6500         }
6501     }
6502     read_dword(&ptr, &offset);
6503     TRACE("Offset: %x\n", offset);
6504 
6505     hr = d3dx_parse_effect(effect, ptr, data_size, offset, skip_constants, skip_constants_count);
6506     if (bytecode)
6507         ID3D10Blob_Release(bytecode);
6508     if (hr != D3D_OK)
6509     {
6510         FIXME("Failed to parse effect.\n");
6511         HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6512         HeapFree(GetProcessHeap(), 0, skip_constants);
6513         return hr;
6514     }
6515 
6516     for (i = 0; i < skip_constants_count; ++i)
6517     {
6518         struct d3dx_parameter *param;
6519         param = get_parameter_by_name(effect, NULL, skip_constants[i]);
6520         if (param)
6521         {
6522             for (j = 0; j < effect->technique_count; ++j)
6523             {
6524                 if (is_parameter_used(param, &effect->techniques[j]))
6525                 {
6526                     WARN("skip_constants parameter %s is used in technique %u.\n",
6527                             debugstr_a(skip_constants[i]), j);
6528                     HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6529                     HeapFree(GetProcessHeap(), 0, skip_constants);
6530                     return D3DERR_INVALIDCALL;
6531                 }
6532             }
6533         }
6534         else
6535         {
6536             TRACE("skip_constants parameter %s not found.\n",
6537                     debugstr_a(skip_constants[i]));
6538         }
6539     }
6540 
6541     HeapFree(GetProcessHeap(), 0, skip_constants_buffer);
6542     HeapFree(GetProcessHeap(), 0, skip_constants);
6543 
6544     /* initialize defaults - check because of unsupported ascii effects */
6545     if (effect->techniques)
6546     {
6547         effect->active_technique = &effect->techniques[0];
6548         effect->active_pass = NULL;
6549     }
6550 
6551     return D3D_OK;
6552 }
6553 
6554 HRESULT WINAPI D3DXCreateEffectEx(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6555         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skip_constants, DWORD flags,
6556         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6557 {
6558     struct d3dx_effect *object;
6559     HRESULT hr;
6560 
6561     TRACE("device %p, srcdata %p, srcdatalen %u, defines %p, include %p,"
6562             " skip_constants %p, flags %#x, pool %p, effect %p, compilation_errors %p.\n",
6563             device, srcdata, srcdatalen, defines, include,
6564             skip_constants, flags, pool, effect, compilation_errors);
6565 
6566     if (compilation_errors)
6567         *compilation_errors = NULL;
6568 
6569     if (!device || !srcdata)
6570         return D3DERR_INVALIDCALL;
6571 
6572     if (!srcdatalen)
6573         return E_FAIL;
6574 
6575     /* Native dll allows effect to be null so just return D3D_OK after doing basic checks */
6576     if (!effect)
6577         return D3D_OK;
6578 
6579     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6580     if (!object)
6581         return E_OUTOFMEMORY;
6582 
6583     hr = d3dx9_effect_init(object, device, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6584             (ID3DInclude *)include, flags, (ID3DBlob **)compilation_errors, pool, skip_constants);
6585     if (FAILED(hr))
6586     {
6587         WARN("Failed to create effect object, hr %#x.\n", hr);
6588         d3dx_effect_cleanup(object);
6589         return hr;
6590     }
6591 
6592     *effect = &object->ID3DXEffect_iface;
6593 
6594     TRACE("Created ID3DXEffect %p\n", object);
6595 
6596     return D3D_OK;
6597 }
6598 
6599 HRESULT WINAPI D3DXCreateEffect(struct IDirect3DDevice9 *device, const void *srcdata, UINT srcdatalen,
6600         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6601         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilation_errors)
6602 {
6603     TRACE("(%p, %p, %u, %p, %p, %#x, %p, %p, %p): Forwarded to D3DXCreateEffectEx\n", device, srcdata, srcdatalen, defines,
6604         include, flags, pool, effect, compilation_errors);
6605 
6606     return D3DXCreateEffectEx(device, srcdata, srcdatalen, defines, include, NULL, flags, pool, effect, compilation_errors);
6607 }
6608 
6609 static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compiler,
6610         const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include,
6611         UINT eflags, ID3DBlob **error_messages)
6612 {
6613     TRACE("compiler %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, error_messages %p.\n",
6614             compiler, data, data_size, defines, include, eflags, error_messages);
6615 
6616     compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl;
6617     compiler->ref = 1;
6618 
6619     FIXME("ID3DXEffectCompiler implementation is only a stub.\n");
6620 
6621     return D3D_OK;
6622 }
6623 
6624 HRESULT WINAPI D3DXCreateEffectCompiler(const char *srcdata, UINT srcdatalen, const D3DXMACRO *defines,
6625         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **compiler, ID3DXBuffer **parse_errors)
6626 {
6627     struct ID3DXEffectCompilerImpl *object;
6628     HRESULT hr;
6629 
6630     TRACE("srcdata %p, srcdatalen %u, defines %p, include %p, flags %#x, compiler %p, parse_errors %p\n",
6631             srcdata, srcdatalen, defines, include, flags, compiler, parse_errors);
6632 
6633     if (!srcdata || !compiler)
6634     {
6635         WARN("Invalid arguments supplied\n");
6636         return D3DERR_INVALIDCALL;
6637     }
6638 
6639     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6640     if (!object)
6641         return E_OUTOFMEMORY;
6642 
6643     hr = d3dx9_effect_compiler_init(object, srcdata, srcdatalen, (const D3D_SHADER_MACRO *)defines,
6644             (ID3DInclude *)include, flags, (ID3DBlob **)parse_errors);
6645     if (FAILED(hr))
6646     {
6647         WARN("Failed to initialize effect compiler\n");
6648         HeapFree(GetProcessHeap(), 0, object);
6649         return hr;
6650     }
6651 
6652     *compiler = &object->ID3DXEffectCompiler_iface;
6653 
6654     TRACE("Created ID3DXEffectCompiler %p\n", object);
6655 
6656     return D3D_OK;
6657 }
6658 
6659 /*** IUnknown methods ***/
6660 static HRESULT WINAPI d3dx_effect_pool_QueryInterface(ID3DXEffectPool *iface, REFIID riid, void **object)
6661 {
6662     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
6663 
6664     if (IsEqualGUID(riid, &IID_IUnknown) ||
6665         IsEqualGUID(riid, &IID_ID3DXEffectPool))
6666     {
6667         iface->lpVtbl->AddRef(iface);
6668         *object = iface;
6669         return S_OK;
6670     }
6671 
6672     WARN("Interface %s not found\n", debugstr_guid(riid));
6673 
6674     return E_NOINTERFACE;
6675 }
6676 
6677 static ULONG WINAPI d3dx_effect_pool_AddRef(ID3DXEffectPool *iface)
6678 {
6679     struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6680     ULONG refcount = InterlockedIncrement(&pool->refcount);
6681 
6682     TRACE("%p increasing refcount to %u.\n", pool, refcount);
6683 
6684     return refcount;
6685 }
6686 
6687 static void free_effect_pool(struct d3dx_effect_pool *pool)
6688 {
6689     unsigned int i;
6690 
6691     for (i = 0; i < pool->size; ++i)
6692     {
6693         if (pool->shared_data[i].count)
6694         {
6695             unsigned int j;
6696 
6697             WARN("Releasing pool with referenced parameters.\n");
6698 
6699             param_set_data_pointer(&pool->shared_data[i].parameters[0]->param, NULL, FALSE, TRUE);
6700             pool->shared_data[i].parameters[0]->shared_data = NULL;
6701 
6702             for (j = 1; j < pool->shared_data[i].count; ++j)
6703             {
6704                 walk_parameter_tree(&pool->shared_data[i].parameters[j]->param, param_zero_data_func, NULL);
6705                 pool->shared_data[i].parameters[j]->shared_data = NULL;
6706             }
6707             HeapFree(GetProcessHeap(), 0, pool->shared_data[i].parameters);
6708         }
6709     }
6710     HeapFree(GetProcessHeap(), 0, pool->shared_data);
6711     HeapFree(GetProcessHeap(), 0, pool);
6712 }
6713 
6714 static ULONG WINAPI d3dx_effect_pool_Release(ID3DXEffectPool *iface)
6715 {
6716     struct d3dx_effect_pool *pool = impl_from_ID3DXEffectPool(iface);
6717     ULONG refcount = InterlockedDecrement(&pool->refcount);
6718 
6719     TRACE("%p decreasing refcount to %u.\n", pool, refcount);
6720 
6721     if (!refcount)
6722         free_effect_pool(pool);
6723 
6724     return refcount;
6725 }
6726 
6727 static const struct ID3DXEffectPoolVtbl ID3DXEffectPool_Vtbl =
6728 {
6729     /*** IUnknown methods ***/
6730     d3dx_effect_pool_QueryInterface,
6731     d3dx_effect_pool_AddRef,
6732     d3dx_effect_pool_Release
6733 };
6734 
6735 static inline struct d3dx_effect_pool *unsafe_impl_from_ID3DXEffectPool(ID3DXEffectPool *iface)
6736 {
6737     if (!iface)
6738         return NULL;
6739 
6740     assert(iface->lpVtbl == &ID3DXEffectPool_Vtbl);
6741     return impl_from_ID3DXEffectPool(iface);
6742 }
6743 
6744 HRESULT WINAPI D3DXCreateEffectPool(ID3DXEffectPool **pool)
6745 {
6746     struct d3dx_effect_pool *object;
6747 
6748     TRACE("pool %p.\n", pool);
6749 
6750     if (!pool)
6751         return D3DERR_INVALIDCALL;
6752 
6753     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6754     if (!object)
6755         return E_OUTOFMEMORY;
6756 
6757     object->ID3DXEffectPool_iface.lpVtbl = &ID3DXEffectPool_Vtbl;
6758     object->refcount = 1;
6759 
6760     *pool = &object->ID3DXEffectPool_iface;
6761 
6762     return S_OK;
6763 }
6764 
6765 HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6766         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6767         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6768 {
6769     struct d3dx_include_from_file include_from_file;
6770     const void *buffer;
6771     unsigned int size;
6772     char *filename_a;
6773     HRESULT ret;
6774 
6775     TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6776             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6777             device, debugstr_w(srcfile), defines, include, debugstr_a(skipconstants),
6778             flags, pool, effect, compilationerrors);
6779 
6780     if (!device || !srcfile)
6781         return D3DERR_INVALIDCALL;
6782 
6783     if (!include)
6784     {
6785         include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl;
6786         include = &include_from_file.ID3DXInclude_iface;
6787     }
6788 
6789     size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL);
6790     filename_a = heap_alloc(size);
6791     if (!filename_a)
6792         return E_OUTOFMEMORY;
6793     WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL);
6794 
6795     EnterCriticalSection(&from_file_mutex);
6796     ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size);
6797     if (FAILED(ret))
6798     {
6799         LeaveCriticalSection(&from_file_mutex);
6800         heap_free(filename_a);
6801         return D3DXERR_INVALIDDATA;
6802     }
6803 
6804     ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool,
6805             effect, compilationerrors);
6806 
6807     ID3DXInclude_Close(include, buffer);
6808     LeaveCriticalSection(&from_file_mutex);
6809     heap_free(filename_a);
6810     return ret;
6811 }
6812 
6813 HRESULT WINAPI D3DXCreateEffectFromFileExA(struct IDirect3DDevice9 *device, const char *srcfile,
6814         const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags,
6815         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6816 {
6817     WCHAR *srcfileW;
6818     HRESULT ret;
6819     DWORD len;
6820 
6821     TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, "
6822             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6823             device, debugstr_a(srcfile), defines, include, debugstr_a(skipconstants),
6824             flags, pool, effect, compilationerrors);
6825 
6826     if (!srcfile)
6827         return D3DERR_INVALIDCALL;
6828 
6829     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
6830     srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
6831     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
6832 
6833     ret = D3DXCreateEffectFromFileExW(device, srcfileW, defines, include, skipconstants, flags, pool, effect, compilationerrors);
6834     HeapFree(GetProcessHeap(), 0, srcfileW);
6835 
6836     return ret;
6837 }
6838 
6839 HRESULT WINAPI D3DXCreateEffectFromFileW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
6840         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6841         struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6842 {
6843     TRACE("(void): relay\n");
6844     return D3DXCreateEffectFromFileExW(device, srcfile, defines, include, NULL, flags, pool, effect, compilationerrors);
6845 }
6846 
6847 HRESULT WINAPI D3DXCreateEffectFromFileA(struct IDirect3DDevice9 *device, const char *srcfile,
6848         const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags, struct ID3DXEffectPool *pool,
6849         struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6850 {
6851     TRACE("(void): relay\n");
6852     return D3DXCreateEffectFromFileExA(device, srcfile, defines, include, NULL, flags, pool, effect, compilationerrors);
6853 }
6854 
6855 HRESULT WINAPI D3DXCreateEffectFromResourceExW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6856         const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
6857         DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6858 {
6859     HRSRC resinfo;
6860     void *buffer;
6861     DWORD size;
6862 
6863     TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
6864             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6865             device, srcmodule, debugstr_w(srcresource), defines, include, debugstr_a(skipconstants),
6866             flags, pool, effect, compilationerrors);
6867 
6868     if (!device)
6869         return D3DERR_INVALIDCALL;
6870 
6871     if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
6872         return D3DXERR_INVALIDDATA;
6873 
6874     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6875         return D3DXERR_INVALIDDATA;
6876 
6877     return D3DXCreateEffectEx(device, buffer, size, defines, include,
6878             skipconstants, flags, pool, effect, compilationerrors);
6879 }
6880 
6881 HRESULT WINAPI D3DXCreateEffectFromResourceExA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6882         const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants,
6883         DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6884 {
6885     HRSRC resinfo;
6886     void *buffer;
6887     DWORD size;
6888 
6889     TRACE("device %p, srcmodule %p, srcresource %s, defines %p, include %p, skipconstants %s, "
6890             "flags %#x, pool %p, effect %p, compilationerrors %p.\n",
6891             device, srcmodule, debugstr_a(srcresource), defines, include, debugstr_a(skipconstants),
6892             flags, pool, effect, compilationerrors);
6893 
6894     if (!device)
6895         return D3DERR_INVALIDCALL;
6896 
6897     if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
6898         return D3DXERR_INVALIDDATA;
6899 
6900     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6901         return D3DXERR_INVALIDDATA;
6902 
6903     return D3DXCreateEffectEx(device, buffer, size, defines, include,
6904             skipconstants, flags, pool, effect, compilationerrors);
6905 }
6906 
6907 HRESULT WINAPI D3DXCreateEffectFromResourceW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6908         const WCHAR *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6909         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6910 {
6911     TRACE("(void): relay\n");
6912     return D3DXCreateEffectFromResourceExW(device, srcmodule, srcresource, defines, include, NULL, flags, pool, effect, compilationerrors);
6913 }
6914 
6915 HRESULT WINAPI D3DXCreateEffectFromResourceA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
6916         const char *srcresource, const D3DXMACRO *defines, struct ID3DXInclude *include, DWORD flags,
6917         struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors)
6918 {
6919     TRACE("(void): relay\n");
6920     return D3DXCreateEffectFromResourceExA(device, srcmodule, srcresource, defines, include, NULL, flags, pool, effect, compilationerrors);
6921 }
6922 
6923 HRESULT WINAPI D3DXCreateEffectCompilerFromFileW(const WCHAR *srcfile, const D3DXMACRO *defines,
6924         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6925 {
6926     void *buffer;
6927     HRESULT ret;
6928     DWORD size;
6929 
6930     TRACE("srcfile %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6931             debugstr_w(srcfile), defines, include, flags, effectcompiler, parseerrors);
6932 
6933     if (!srcfile)
6934         return D3DERR_INVALIDCALL;
6935 
6936     ret = map_view_of_file(srcfile, &buffer, &size);
6937 
6938     if (FAILED(ret))
6939         return D3DXERR_INVALIDDATA;
6940 
6941     ret = D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
6942     UnmapViewOfFile(buffer);
6943 
6944     return ret;
6945 }
6946 
6947 HRESULT WINAPI D3DXCreateEffectCompilerFromFileA(const char *srcfile, const D3DXMACRO *defines,
6948         ID3DXInclude *include, DWORD flags, ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6949 {
6950     WCHAR *srcfileW;
6951     HRESULT ret;
6952     DWORD len;
6953 
6954     TRACE("srcfile %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6955             debugstr_a(srcfile), defines, include, flags, effectcompiler, parseerrors);
6956 
6957     if (!srcfile)
6958         return D3DERR_INVALIDCALL;
6959 
6960     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
6961     srcfileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*srcfileW));
6962     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, len);
6963 
6964     ret = D3DXCreateEffectCompilerFromFileW(srcfileW, defines, include, flags, effectcompiler, parseerrors);
6965     HeapFree(GetProcessHeap(), 0, srcfileW);
6966 
6967     return ret;
6968 }
6969 
6970 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceA(HMODULE srcmodule, const char *srcresource,
6971         const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
6972         ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6973 {
6974     HRSRC resinfo;
6975     void *buffer;
6976     DWORD size;
6977 
6978     TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6979             srcmodule, debugstr_a(srcresource), defines, include, flags, effectcompiler, parseerrors);
6980 
6981     if (!(resinfo = FindResourceA(srcmodule, srcresource, (const char *)RT_RCDATA)))
6982         return D3DXERR_INVALIDDATA;
6983 
6984     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
6985         return D3DXERR_INVALIDDATA;
6986 
6987     return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
6988 }
6989 
6990 HRESULT WINAPI D3DXCreateEffectCompilerFromResourceW(HMODULE srcmodule, const WCHAR *srcresource,
6991         const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags,
6992         ID3DXEffectCompiler **effectcompiler, ID3DXBuffer **parseerrors)
6993 {
6994     HRSRC resinfo;
6995     void *buffer;
6996     DWORD size;
6997 
6998     TRACE("srcmodule %p, srcresource %s, defines %p, include %p, flags %#x, effectcompiler %p, parseerrors %p.\n",
6999             srcmodule, debugstr_w(srcresource), defines, include, flags, effectcompiler, parseerrors);
7000 
7001     if (!(resinfo = FindResourceW(srcmodule, srcresource, (const WCHAR *)RT_RCDATA)))
7002         return D3DXERR_INVALIDDATA;
7003 
7004     if (FAILED(load_resource_into_memory(srcmodule, resinfo, &buffer, &size)))
7005         return D3DXERR_INVALIDDATA;
7006 
7007     return D3DXCreateEffectCompiler(buffer, size, defines, include, flags, effectcompiler, parseerrors);
7008 }
7009 
7010 HRESULT WINAPI D3DXDisassembleEffect(ID3DXEffect *effect, BOOL enable_color_code, ID3DXBuffer **disassembly)
7011 {
7012     FIXME("(%p, %u, %p): stub\n", effect, enable_color_code, disassembly);
7013 
7014     return D3DXERR_INVALIDDATA;
7015 }
7016