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