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