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