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