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